web-dev-qa-db-fra.com

Convertissez la durée en heures: minutes: secondes (ou similaire) en Rails 3 ou Ruby

J'ai l'impression qu'il existe un moyen simple/intégré de faire cela, mais je ne le trouve pas.

J'ai une durée (en secondes) dans un entier et je veux l'afficher dans un format convivial.

par exemple. 3600 serait affiché comme "01:00:00" ou "1 heure" ou quelque chose.

Je peux le faire avec time_ago_in_words(Time.zone.now+3600) mais cela ressemble à un peu de bidouille, il n'y a aucune raison d'ajouter/de soustraire du temps actuel simplement pour formater cette valeur. Y a-t-il une duration_in_words() ou quelque chose?

Merci

107
cydonia

Voir: http://api.rubyonrails.org/classes/ActionView/Helpers/DateHelper.html

distance_of_time_in_words(3600)
 => "about 1 hour"
75
allan

En résumé:

en admettant que total_seconds = 3600

Option 1:

distance_of_time_in_words(total_seconds) #=> "about 1 hour"

Option 2:

Time.at(total_seconds).utc.strftime("%H:%M:%S") #=> "01:00:00"

Option 3:

seconds = total_seconds % 60
minutes = (total_seconds / 60) % 60
hours = total_seconds / (60 * 60)

format("%02d:%02d:%02d", hours, minutes, seconds) #=> "01:00:00"

utilisez Option1 si vous voulez des mots, Option2 si vous voulez le format H: M: S, Option si vous voulez le format H: M: S et il peut y avoir plus de 24 heures

184
Lev Lukomsky

La chaîne de Ruby % L’opérateur est trop méconnu et souvent oublié.

"%02d:%02d:%02d:%02d" % [t/86400, t/3600%24, t/60%60, t%60]

Étant donné que t est une durée en secondes, ceci émet une chaîne séparée par des points et complétée par des points, y compris les jours. Exemple:

t = 123456
"%02d:%02d:%02d:%02d" % [t/86400, t/3600%24, t/60%60, t%60]
=> "01:10:17:36"

Charmant.

39
IAmNaN

Je suppose que vous pourriez faire quelque chose comme:

(Time.mktime(0)+3600).strftime("%H:%M:%S")

Pour le formater comme vous le souhaitez.

BTW, à l’origine, j’ai pensé utiliser Time.at (), mais il semble que l’heure de l'époque sur mon Ubuntu soit le jeudi 01 janvier à 01:00:00 au lieu de 1970 et non à 00:00:00 comme prévu, et donc si je le fais:

Time.at(3600).strftime("%H:%M:%S")

Me donne 1 heure de plus que voulu.

21
Cristobal Viedma

J'utilise ceci pour afficher les durées dans mon Rails Project:

  1. Ajoutez une méthode personnalisée à la classe Integer. Vous pouvez créer un nouveau fichier nommé pretty_duration.rb dans le dossier initializers:

    class Integer
        def pretty_duration
            parse_string = 
                if self < 3600
                    '%M:%S'
                else
                    '%H:%M:%S'
                end
    
            Time.at(self).utc.strftime(parse_string)
        end
    end
    
  2. Appel seconds.pretty_duration n'importe où dans votre projet:

    275.pretty_duration     # => "04:35"
    9823.pretty_duration    # => "02:43:43"
    

Cette réponse se construit sur Code de Lev Lukomsky

13
Sheharyar

Celui-ci utilise la méthode obscure divmod pour diviser et modulo en même temps, donc il gère correctement Float secondes:

def duration(seconds)
  minutes, seconds = seconds.divmod(60)
  hours, minutes = minutes.divmod(60)
  days, hours = hours.divmod(24)

  "#{days.to_s.rjust(3)}d #{hours.to_s.rjust(2)}h #{minutes.to_s.rjust(2)}m #{seconds}s"
end
8
Brent Royal-Gordon

Soyez prudent avec la durée supérieure à un jour.

(timing/3600).to_i.to_s.rjust(2,'0') + ":"+Time.at(timing).utc.strftime("%M:%S")
4
Xiao Bin

Une réponse inspirée de celle de Lev Lukomsky tirant parti d'ActiveSupport :: Duration et de la gestion en millisecondes (utile pour le code de référence)

# duration in ms modulus number of ms in one second
milliseconds = duration.in_milliseconds % 1.second.in_milliseconds

# duration in seconds modulus number of seconds in one minute
seconds = (duration / 1.second) % (1.minute / 1.second)

# duration in minutes modulus number of minutes in one hour
minutes = (duration / 1.minute) % (1.hour / 1.minute)

# duration in hours modulus number of hours in one day
hours = (duration / 1.hour) % (1.day / 1.hour)

format("%02d:%02d:%02d:%03d", hours, minutes, seconds, milliseconds) #=> "12:05:00:001"

Bien sûr, vous pouvez étendre cela facilement avec des jours, des mois, des années, etc. en utilisant les méthodes ActiveSupport associées et en répétant la même structure.

Gardez à l'esprit que pour de trop longues durées, cela peut être inexact, car la durée d'un mois n'est pas fixée en nombre de jours, et je ne suis pas sûr de savoir comment AS: Duration traite de cela.

3
Cyril Duchon-Doris

En utilisant Time.utc.strftime fonctionne uniquement pour les valeurs lorsque le nombre total d’heures est inférieur à 24:

2.2.2 :004 > Time.at(60 * 60).utc.strftime('%H h %M m')
=> "01 h 00 m"

Pour des valeurs supérieures, les résultats sont incorrects:

2.2.2 :006 > Time.at(60 * 60 * 24).utc.strftime('%H h %M m')
 => "00 h 00 m"

Je suggère d'utiliser la méthode la plus simple que j'ai trouvée pour résoudre ce problème:

  def formatted_duration total_seconds
    hours = total_seconds / (60 * 60)
    minutes = (total_seconds / 60) % 60
    seconds = total_seconds % 60
    "#{ hours } h #{ minutes } m #{ seconds } s"
  end

Vous pouvez toujours ajuster la valeur renvoyée à vos besoins.

3
Igor Springer
    hours = 3.5456
    value = (hours*60).divmod(60).map{ |a| "%02d"%[a.floor] }.join(":")
    => "03:32"
0
Luciano Ribas