秒数を「◯時間◯分◯秒」の形式で表示する処理をこの前書いていて、アレ?ってなったのでメモしておきます この時はTimeで変換すればいいじゃん!と思っていました・・・
# 10秒の場合 Time.at(10).strftime("%H時間%M分%S秒") => "00時間00分10秒" # 60秒の場合 Time.at(60).strftime("%H時間%M分%S秒") => "00時間01分00秒" # 360秒の場合 Time.at(360).strftime("%H時間%M分%S秒") => "00時間06分00秒" # 3600秒の場合 Time.at(3600).strftime("%H時間%M分%S秒") => "01時間00分00秒"
上の結果を見て「お、ちゃんとできてるじゃん!」と思っていました……が。
以下が期待値なのですが、実際に Time.at
を使ってみると…
実行結果
# OK Time.at(86399).strftime("%H時間%M分%S秒") => "23時間59分59秒" # アレ????? Time.at(86400).strftime("%H時間%M分%S秒") => "00時間00分00秒" # アレ????? Time.at(86401).strftime("%H時間%M分%S秒") => "00時間00分01秒" # 123456秒って 34時間17分36秒 のはずじゃない? Time.at(123456).strftime("%H時間%M分%S秒") => "10時間17分36秒"
Time オブジェクトは時刻を起算時からの経過秒数で保持しています。起算時は協定世界時(UTC、もしくはその旧称から GMT とも表記されます) の 1970年1月1日午前0時です。なお、うるう秒を勘定するかどうかはシステムによります。
unit に応じて seconds + xseconds ミリ秒などの時刻を表す Time オブジェクトを返します。[PARAM] seconds:起算時からの経過秒数を表わす値をInteger、 Float、 Rational、または他のNumericで指定します。
Time.at(seconds) は「1970年1月1日 00:00:00 UTC」から seconds 秒後の "時刻" を生成します。 下記のコードは「1970年1月2日 10:17:36 UTC」という“時刻”を作っていて、strftime("%H") で表示されるのはその日の「時刻(10時)」です。
Time.at(123456).to_s => "1970-01-02 10:17:36 +0000"
この状態で strftime("%H") を使うと、「その日」の時刻(つまり0〜23)で返されるため、24時間を超えると0に戻ってしまうというわけです。
こんな感じ
seconds = 123456 => 123456 hours = seconds / 3600 => 34 minutes = (seconds % 3600) / 60 => 17 secs = seconds % 60 => 36 format("%02d時間%02d分%02d秒", hours, minutes, secs) => "34時間17分36秒"