BLOGTIMES
2009/09/21

日付のGMT変換にハマる

  ruby 
このエントリーをはてなブックマークに追加

Rubyには日付を扱うクラスとして、TimeとDateTimeという2つのクラスがあります。TimeはSQLの型のように日付は格納できないように見えますが、どちらも日付と時刻が格納できます。おそらく何らかの歴史的な経緯があって、結果としてこうなっているんだとは思いますが、実はその違いが良くわかっていません。time_tとstruct tmの違いみたいなものでしょうか。

ただ、これらのクラスはタイムゾーンの扱いがちょっと違うようで、時刻をGMT変換しようとしたらハマってしまいました。

require 'time' require 'date' str = '2009-09-21T00:00:00' DateTime.parse(str).to_s # => "2009-09-21T00:00:00Z" DateTime.parse(str).new_offset(0).to_s # => "2009-09-21T00:00:00Z" Time.parse(str).gmtime.iso8601 # => "2009-09-20T15:00:00Z" str = '2009-09-21T00:00:00+0900' DateTime.parse(str).to_s # => "2009-09-21T00:00:00+0900" DateTime.parse(str).new_offset(0).to_s # => "2009-09-20T15:00:00Z" Time.parse(str).gmtime.iso8601 # => "2009-09-20T15:00:00Z"

おそらくシステムの設定に依存するとはおもいますが、上記を見ると分かるとおり、僕の環境では日付にタイムゾーンがついていないとDateTimeは日時をUTCとしてとらえており、Timeはローカル時としてとらえているようです。タイムゾーンがついていない場合にはローカル時として扱ってくれると言う意味では、Timeを常用するのが安全なんですかね。


    トラックバックについて
    Trackback URL:
    お気軽にどうぞ。トラックバック前にポリシーをお読みください。[policy]
    このエントリへのTrackbackにはこのURLが必要です→https://blog.cles.jp/item/3214
    Trackbacks
    このエントリにトラックバックはありません
    Comments
    愛のあるツッコミをお気軽にどうぞ。[policy]
    古いエントリについてはコメント制御しているため、即時に反映されないことがあります。
    ぬるぽ (2009/10/26 23:42) <%HatenaAuth()%>

    日付にタイムゾーンがついていないとDateTimeは日時をUTCとしてとらえており、Timeはローカル時としてとらえているようです。タイムゾーンがついていない場合にはローカル時として扱ってくれると言う意味では、Timeを常用するのが安全なんですかね。

    タイムゾーン付きでないISO8601もどき形式をISO8601としてちゃんと解釈しているのがDateTime.parse(が呼ぶParseDate.parse)、単にTとかZとか知らん文字を読み飛ばして適当に時間作るのがTime.parse、ということなのではないでしょうかね。

    hsur (2009/10/27 04:04) <%HatenaAuth()%>

    ISO8601はタイムゾーン必須なのですか?それは認識していませんでした。
    ちなみにTime.parseはタイムゾーンをきちんと認識しているようですよ。

    Time.parse('2009-09-21T00:00:00Z').gmtime.iso8601 # => "2009-09-21T00:00:00Z"
    Time.parse('2009-09-21T00:00:00+0900').gmtime.iso8601 # => "2009-09-20T15:00:00Z"

    Rubyのドキュメントにこれらの挙動の違いが記載されていないことが問題だと思うんですよね。

    Comments Form

    コメントは承認後の表示となります。
    OpenIDでログインすると、即時に公開されます。

    OpenID を使ってログインすることができます。

    Identity URL: Yahoo! JAPAN IDでログイン