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
Voir: http://api.rubyonrails.org/classes/ActionView/Helpers/DateHelper.html
distance_of_time_in_words(3600)
=> "about 1 hour"
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
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.
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.
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
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
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
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")
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.
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.
hours = 3.5456
value = (hours*60).divmod(60).map{ |a| "%02d"%[a.floor] }.join(":")
=> "03:32"