From: Tanaka Akira <akr@...> Date: 2009-03-28T02:18:08+09:00 Subject: [ruby-dev:38191] big time 思い立って、time_t を越える範囲を Time で扱うことに挑戦して みました。 http://www.a-k-r.org/tmp/ruby-big-time.patch 内部的には timespec のかわりに VALUE を使ってあります。 % ./ruby -ve 'p Time.utc(5670000000)' ruby 1.9.2dev (2009-03-27) [i686-linux] 5670000000-01-01 00:00:00 UTC % ./ruby -ve 'p Time.now - 12000 * 365 * 24 * 60 * 60' ruby 1.9.2dev (2009-03-27) [i686-linux] -9983-03-15 07:44:10 +0900 これを実現するのに問題になるのは、結局、以下の情報をどうやっ て得るかという点です。これらの情報さえあれば、あとは計算でど うにかできます。 * システムのタイムゾーンにおける時差 * 閏秒 localtime/gmtime が使えれば、これらの情報を得られるので すが、time_t の範囲外では使えませんし、範囲内でも使えないこ とがある、というのが問題です。 (範囲内で使えない例: 64bit time_t では 32bit tm_year が overflow する) どう対処したかというと、まず閏秒はシステムが知っている範囲だ けを扱っています。1年後よりも先の閏秒がどうなるかは誰も知ら ないので、32bit time_t な環境でも 2037年になるまでは、閏秒の 情報はすべて得られます。(もちろん、システムの管理者が閏秒の 情報を使用すると決心して、ちゃんと情報を更新していれば、です が) 時差は厄介で、特定の時刻におけるタイムゾーンの時差を得る確実 な方法はありません。てきとうに決めています。この処理について は工夫の余地はあるかもしれません。 (Matz 日記で以前紹介されていた、Perl のはやってません。) ただ、どうせこれは無理な話なので、プログラムから時差を指定す る API を用意する方向のほうが適切でしょう。 内部的には UTC からの offset を Time object 毎に保持するデー タ構造になっているので、API を用意すれば、Time オブジェクト の時差を自由に設定できるようになります。 あと、グレゴリオ歴しか扱っていないので、いくら過去に遡っても ユリウス歴にはなりません。(もちろん天保歴にもなりません) また、Time#subsec を追加してあります。これは内部表現で Rational を使えるので、nsec では完全な情報を取り出せないから です。0 <= subsec < 1 の範囲で秒よりも小さな部分を返します。 こうなると DateTime とどう違うのか、という話になる気もします が、おそらく閏秒が最大の違いになる気がします。実世界の (シス テムの) 時刻を扱えるという意味では利点であり、n日後とかの計 算を難しくするという意味では欠点でしょうか。 どうでしょう? -- [田中 哲][たなか あきら][Tanaka Akira]