Конвертировать продолжительность в часы: минуты: секунды (или аналогичные) в Rails 3 или Ruby - PullRequest
106 голосов
/ 14 ноября 2010

У меня есть ощущение, что есть простой / встроенный способ сделать это, но я не могу его найти.

У меня есть продолжительность (в секундах) в целом числе, и я хочу отобразить еев дружественном формате.

например, 3600 будет отображаться как "01:00:00" или "1 час" или что-то еще.

Я могу сделать это с time_ago_in_words(Time.zone.now+3600), но похоженемного хак, нет причин добавлять / вычитать из текущего времени только для форматирования этого значения.Есть duration_in_words() или что-то?

Спасибо

Ответы [ 9 ]

184 голосов
/ 29 марта 2012

Суммирование:

при условии, что 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, Option3 , если вы хотите H: M: S формат и может быть более 24 часов

75 голосов
/ 14 ноября 2010

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

distance_of_time_in_words(3600)
 => "about 1 hour"
38 голосов
/ 16 апреля 2015

Оператор Ruby's 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"

прекрасный.

21 голосов
/ 14 ноября 2010

Полагаю, вы могли бы сделать что-то вроде:

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

Чтобы отформатировать его как хотите.

Кстати, изначально я думал об использовании Time.at (), но кажется, что EPOCHвремя в моем Ubuntu - четверг 01 января 01:00:00 +0100 1970, а не 00:00:00 часов, как я ожидал, и поэтому, если я это сделаю:

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

Дает мне на 1 час больше, чем хотелось.

13 голосов
/ 06 марта 2015

Я использую это, чтобы показать продолжительность времени в моем Rails Project:

  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
    
  2. Звоните seconds.pretty_duration в любом месте вашего проекта:

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

Этот ответ основан на Код Льва Лукомского

8 голосов
/ 26 января 2017

Этот метод использует скрытый метод 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
4 голосов
/ 11 августа 2014

Будьте осторожны с продолжительностью, превышающей один день.

(timing/3600).to_i.to_s.rjust(2,'0') + ":"+Time.at(timing).utc.strftime("%M:%S")
3 голосов
/ 16 августа 2018

Ответ, вдохновленный тем, что Лев Лукомский использовал в своих интересах 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: продолжительность имеет дело с этим.

3 голосов
/ 02 июня 2015

Использование 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

Вы всегда можете настроить возвращаемое значение в соответствии со своими потребностями.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...