2020年04月26日

ruby の Date と Time の間にある strftime の違い

Date (DateTime) と Time では strftime の指定子の扱いに微妙な差がある。

ついでなので date コマンド(GNU coreutils 8.30) とも比較して、異なるものが以下の通り。 指定子の意味について詳しくは Time#strftimeDate._strptime に書いてある。(Date#strftime のドキュメントは指定子の一覧しかない)

specifiersDateTime#strftimeTime#strftimedate(1)
%Q1577199600000%Q%Q
%v24-Dec-201924-DEC-2019%v
%Z+00:00UTCUTC
%+Tue Dec 24 15:00:00 +00:00 2019%+%+

%Q

Date/DateTimeのみ。「1970-01-01 00:00:00 UTC からの経過ミリ秒」。要は %s のミリ秒版。

Time で表記するなら、秒の小数点以下を表す %N と幅指定子を組み合わせて strftime("%s%3N") とする。

%Z (と %+)

Time#strftime のドキュメントによれば:

  • %Z: タイムゾーン (環境依存)
  • %+: date(1)の形式 (%a %b %e %H:%M:%S %Z %Y)

「環境依存」とは OS のシステム関数に依存してるからだったかな?とにかく、 Time や date(1) はタイムゾーン (UTC) を返すのに対して、Dateではゾーンではなくオフセット(+00:00)。

ということはこの環境で Date の「%+」を Time で完璧に再現するなら「%Z」ではなく、コロン入りの「%:z」を使う必要がある。

> t = Time.new(2019, 12, 25).gmtime
> t.to_datetime.strftime('%+')
=> "Tue Dec 24 15:00:00 +00:00 2019"
> t.strftime('%a %b %e %H:%M:%S %Z %Y')
=> "Tue Dec 24 15:00:00 UTC 2019"
> t.strftime('%a %b %e %H:%M:%S %:z %Y')
=> "Tue Dec 24 15:00:00 +00:00 2019"

ちなみに date(1) を英語で実行すると、タイムゾーンが使われる。(少なくとも手元の環境では)

$ LC_ALL=C date --utc --date="@1577199600"
Tue Dec 24 15:00:00 UTC 2019

%v

「VMS形式の日付」とあり、OpenVMSを指すものと思われるが、月の大文字の扱いが違う。実際、Dateのドキュメントには %e-%b-%Y 、 Time のには %e-%^b-%4Y (^は大文字にする) とある。

そもそもなんでこの指定子が入ってるのかわからない。

確認用

require "date"
require "time"

# https://docs.ruby-lang.org/ja/latest/method/Date/i/strftime.html
specifiers = %{%A, %a, %B, %b, %C, %c, %D, %d, %e, %F, %G, %g, %H, %h, %I, %j, %k, %L, %l, %M, %m, %N, %n, %P, %p, %Q, %R, %r, %S, %s, %T, %t, %U, %u, %V, %v, %W, %w, %X, %x, %Y, %y, %Z, %z, %:z, %::z, %:::z, %%, %+}.split(", ")

@time = Time.now.gmtime
@datetime = @time.to_datetime

puts ["specifier", "DateTime#strftime", "Time#strftime", "date(1)"].join("\t")
specifiers.each do \|pat\|
  strs = [@datetime, @time].map{\|obj\| obj.strftime(pat) }
  next if strs.uniq.length == 1
  strs << `date +#{pat} --utc --date="@#{@time.to_i}"`.chomp

  puts ([pat] + strs).join("\t")
end
posted by かぷらす at 15:57
"ruby の Date と Time の間にある strftime の違い"へのコメント
コメントを書く
お名前:

メールアドレス:

ホームページアドレス:

コメント: