web-dev-qa-db-ja.com

Rails 3またはRubyの期間を時間:分:秒(または同様の)に変換します

私はこれを行うためのシンプルな/組み込みの方法があると感じていますが、それを見つけることができません。

整数の期間(秒単位)があり、わかりやすい形式で表示したい。

例えば3600は「01:00:00」または「1時間」などと表示されます。

私はtime_ago_in_words(Time.zone.now+3600)でそれを行うことができますが、それはちょっとしたハックのように感じます。この値をフォーマットするためだけに現在の時間から加算/減算する理由はありません。 duration_in_words()などがありますか?

ありがとう

107
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時間以上かかる場合があります

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

素敵。

39
IAmNaN

次のようなこともできると思います:

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

必要に応じてフォーマットします。

ところで、もともとはTime.at()を使用することを考えていましたが、私のUbuntuのエポック時間は木曜日1月01日01:00:00 +0100 1970であり、予想どおり00:00:00時間ではないようです。

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

必要以上に1時間長くなります。

21

これを使用して、Railsプロジェクトの期間を表示します。

  1. Integerクラスにカスタムメソッドを追加します。 initializersフォルダーにpretty_duration.rbという名前の新しいファイルを作成できます。

    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"
    

この答えは Lev Lukomsky's Codeに基づいています

13
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
8

1日より長い期間に注意してください。

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

ActiveSupport :: Durationを利用し、ミリ秒を処理するLev Lukomskyのものからヒントを得た回答(ベンチマークコードに有用)

# 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がそれをどのように処理するかわかりません。

3

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
    hours = 3.5456
    value = (hours*60).divmod(60).map{ |a| "%02d"%[a.floor] }.join(":")
    => "03:32"
0
Luciano Ribas