Конвертировать длительность в часы: минуты: секунды (или аналогичные) в Rails 3 или Ruby

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

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

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

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

Спасибо

Ответ 2

Подведение итогов:

предполагая, что 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 часов

Ответ 3

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

Прекрасный.

Ответ 4

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

(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 час больше, чем нужно.

Ответ 5

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

  • Добавить собственный метод в класс 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"
    

Этот ответ строится на Лев Лукомский код

Ответ 6

Этот метод использует неясный 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

Ответ 7

Будьте осторожны с длительностью более одного дня.

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

Ответ 8

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

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

Ответ 9

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

Ответ 10

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