Ответ 1
Смотрите: http://api.rubyonrails.org/classes/ActionView/Helpers/DateHelper.html
distance_of_time_in_words(3600)
=> "about 1 hour"
У меня есть ощущение, что есть простой/встроенный способ сделать это, но я не могу его найти.
У меня есть продолжительность (в секундах) целого числа, и я хочу отобразить ее в дружественном формате.
например. 3600 будет отображаться как "01:00:00" или "1 час" или что-то в этом роде.
Я могу сделать это с помощью time_ago_in_words(Time.zone.now+3600)
, но это похоже на взлох, нет причин добавлять/вычитать из текущего времени только для форматирования этого значения. Есть ли duration_in_words()
или что-то?
Спасибо
Смотрите: http://api.rubyonrails.org/classes/ActionView/Helpers/DateHelper.html
distance_of_time_in_words(3600)
=> "about 1 hour"
Подведение итогов:
предполагая, что total_seconds = 3600
Вариант 1:
distance_of_time_in_words(total_seconds) #=> "about 1 hour"
Вариант 2:
Time.at(total_seconds).utc.strftime("%H:%M:%S") #=> "01:00:00"
Вариант 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"
используйте Option1, если вам нужны слова, Option2, если вы хотите формат H: M: S, вариант 3, если вы хотите формат H: M: S, и может быть более 24 часов
Оператор Ruby string %
слишком недооценен и забыт.
"%02d:%02d:%02d:%02d" % [t/86400, t/3600%24, t/60%60, t%60]
При заданном t длительность в секундах, это испускает нулевую пробитую строку с двоеточием, включая дни. Пример:
t = 123456
"%02d:%02d:%02d:%02d" % [t/86400, t/3600%24, t/60%60, t%60]
=> "01:10:17:36"
Прекрасный.
Я думаю, вы могли бы сделать что-то вроде:
(Time.mktime(0)+3600).strftime("%H:%M:%S")
Отформатировать его по своему усмотрению.
Кстати, изначально я думал об использовании Time.at(), но кажется, что время EPOCH на моем Ubuntu - Thu Jan 01 01:00:00 +0100 1970, а не 00:00:00 часов, как я и ожидал, и, следовательно, если Я:
Time.at(3600).strftime("%H:%M:%S")
Дает мне на 1 час больше, чем нужно.
Добавить собственный метод в класс Integer
. Вы можете создать новый файл с именем pretty_duration.rb
в папке 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
Вызовите seconds.pretty_duration
в любом месте вашего проекта:
275.pretty_duration # => "04:35"
9823.pretty_duration # => "02:43:43"
Этот ответ строится на Лев Лукомский код
Этот метод использует неясный divmod
метод для деления и модуляции в одно и то же время, поэтому он правильно выполняет Float
секунды:
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
Будьте осторожны с длительностью более одного дня.
(timing/3600).to_i.to_s.rjust(2,'0') + ":"+Time.at(timing).utc.strftime("%M:%S")
Использование Time.utc.strftime
работает только для значений, когда общее количество часов меньше 24:
2.2.2 :004 > Time.at(60 * 60).utc.strftime('%H h %M m')
=> "01 h 00 m"
При больших значениях он возвращает неверные результаты:
2.2.2 :006 > Time.at(60 * 60 * 24).utc.strftime('%H h %M m')
=> "00 h 00 m"
Я предлагаю использовать простейший метод, который я нашел для этой проблемы:
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
Вы всегда можете настроить возвращаемое значение в соответствии с вашими потребностями.
Ответ, вдохновленный Львом Лукомским, который использует ActiveSupport :: Duration и обрабатывает миллисекунды (полезно для тестирования кода)
# 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"
Конечно, вы можете легко расширить это на дни, месяцы, годы и т.д., используя связанные методы ActiveSupport и повторяя ту же структуру.
Имейте в виду, что для слишком длительных периодов это может быть неточным, поскольку продолжительность в 1 месяц не фиксирована числом дней, и я не уверен, как AS: Duration справляется с этим.
hours = 3.5456
value = (hours*60).divmod(60).map{ |a| "%02d"%[a.floor] }.join(":")
=> "03:32"