読者です 読者をやめる 読者になる 読者になる

TimeとDateTimeと2038年問題

Ruby

現在の Unix システムでの最大時刻は、協定世界時の2038年1月19日午前3時14分7秒です。

http://www.ruby-lang.org/ja/man/?cmd=view;name=Time

Timeは2038/1/19以降がエラーになる。

>> Time.gm(2038,1,19).strftime("%Y-%m-%d %a")
=> "2038-01-19 Tue"
>> Time.gm(2038,1,20).strftime("%Y-%m-%d %a")
ArgumentError: time out of range
        from (irb):7:in `gm'
        from (irb):7
        from :0

DateTimeはもっとずっと先まで大丈夫。

>> require 'date'
=> true
>> DateTime.civil(2038,1,19).strftime("%Y-%m-%d %a")
=> "2038-01-19 Tue"
>> DateTime.civil(2038,1,20).strftime("%Y-%m-%d %a")
=> "2038-01-20 Wed"
>> DateTime.civil(99999999999999,1,20).strftime("%Y-%m-%d %a")
=> "99999999999999-01-20 Sun"
>> DateTime.civil(999999999999999,1,20).strftime("%Y-%m-%d %a")
=> "999999999999999-01-20 Sun"
>> DateTime.civil(9999999999999999,1,20).strftime("%Y-%m-%d %a")
ArgumentError: invalid date
        from /usr/lib/ruby/1.8/date.rb:1173:in `civil'
        from (irb):14
        from :0

ActionWebserviceが:timeのデータをDateTimeで受け取ってしまうのは何でだろうと思っていましたが、ここらへんが一番の原因なのかなー。


Timeの下限は1901年12月13日20時45分52秒。

>> Time.gm(1901,12,13,20,45,52).strftime("%Y-%m-%d %a")
=> "1901-12-13 Fri"
>> Time.gm(1901,12,13,20,45,51).strftime("%Y-%m-%d %a")
ArgumentError: time out of range
        from (irb):45:in `gm'
        from (irb):45
>> Time.gm(1901,12,13,20,45,52).to_i
=> -2147483648

これはOSに依存するみたい。

Time [compat] 負の time_t を扱えるようになりました(OSがサポートしている場合に限る)

http://www.ruby-lang.org/ja/man/index.cgi?cmd=view;name=1.6.8%A4%AB%A4%E91.8.0%A4%D8%A4%CE%CA%D1%B9%B9%C5%C0(%A4%DE%A4%C8%A4%E1)

手元の環境(MySQL)だと、ActiveRecordがTIMESTAMPの範囲外の日付をnilにしてくれる。DBの値がNULLの場合と区別がつかない。すごく危険な感じ。Timeの代わりにDateTimeを使う方法はあるのかな?