it-roy-ru.com

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

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

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

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

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

Спасибо

105
cydonia

Смотрите: http://api.rubyonrails.org/classes/ActionView/Helpers/DateHelper.html

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

Подводя итог:

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

182
Lev Lukomsky

Строковый оператор Ruby % слишком недооценен и часто забыт.

"%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"

Прекрасный.

38
IAmNaN

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

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

20
Cristobal Viedma

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

  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"
    

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

12
Sheharyar

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

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

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

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

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

3
Igor Springer

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

2
Cyril Duchon-Doris