From: Tanaka Akira Date: 2009-03-28T22:39:22+09:00 Subject: [ruby-dev:38196] Re: big time In article <20090328.134401.209982445.tadf@dotrb.org>, Tadayoshi Funaba writes: > o Time は標準である > o Time に欠点があるのはしかたがない 「time_t だから」という理由に反論するのはなかなか難しかった のでしょう。 今、私が反論するなら「time_t が本当に必要になるまでは time_t な値を作らなくてもいいんじゃないの」ということになります。 たとえば、ファイルのタイムスタンプに設定するには time_t な値 がどうしても必要ですが、以下でいうと Time.utc じゃなくて File.utime で例外にすればいいんじゃないのか、ということです。 % ./ruby -e ' t = Time.utc(3333,1,1) p t File.utime(t, t, "file") ' 3333-01-01 00:00:00 UTC -e:4:in `utime': time out of system range (ArgumentError) from -e:4:in `
' まぁ、本当に難しいのはシステムが提供してくれない時差の情報で あって、これについては DateTime だろうが Time だろうが無理な ものは無理です。文句をいわれたらシステムが提供してくれないか ら、といういいわけをすることになるでしょう。DateTime と Time の違いは、システムが提供してくれたら Time は使うというところ でしょうか。 > 実装の内容はわかってないですが、仕様面だと、API において 99 を 1999 に > 読み換える、ということが ruby の Time でも行なわれているので、そういう > のも考える必要がありますかね。 あぁ、いまのところ残してありますが、これを機になくすのが妥当 でしょうね。 Ruby 1.8.0 から (-w をつければ) 警告してましたし。 警告を付けたのは私ですが、結局なにもいわれませんでしたね。 > 実現すれば、これまで ruby のいくつかの組み込みクラス、モジュールでは、 > Unix/C の機能へのラッパーとしての縛りが設計上の拘りとして効いていました > が、今後はもう少し柔軟に対応する、という転換点になると思います。 私は、Unix とは異なる抽象を採用させるというのを何回か行って ます。readpartial とか nonblocking I/O とか、最近でいえば socket option あたりもそうかな。 POSIX にないという意味では Time#utc_offset もそうですよね。 これは 4.4BSD や GNU/Linux にあったので Ruby 独自というわけ ではありませんが。 なので、今までも可能ではあったと思います。 重要なのは必要性をちゃんと説明することでしょうか。 ... あぁ、そういえば今回は必要性を述べてませんね。失念してい ました。 なので、いまさらですが述べておきます。 外界にある時刻は必ずしも Time で表現可能とは限りません。 たとえば、メールを読み込んだ時、Date フィールドから取り出し た時刻をプログラムから扱いやすくするには Time のようなクラス で表現することが有効です。そうなっていれば、たとえば時刻を比 較してメールを時刻順に並べたりすることが簡単にできます。 しかし、残念なことに Date: Sat, 28 Mar 3610 14:55:43 +0200 などといった Date フィールドをもつメールを送りつけることを防 ぐものは何もありません。 (この例は今日到着した spam から採った実際のものです。) そして、こういう時刻を Time オブジェクトにしようとすると ArgumentError になってしまいます。 % /usr/bin/ruby -rtime -e 'p Time.rfc822("Sat, 28 Mar 3610 14:55:43 +0200")' /usr/lib/ruby/1.8/time.rb:292:in `utc': time out of range (ArgumentError) from /usr/lib/ruby/1.8/time.rb:292:in `rfc822' from -e:1 これは、time_t では西暦3610年の時刻を表現できないためです。 このため、メールを読み込んだときに Time オブジェクトを生成す ると、メールによっては例外が起きるのでうまくいきません。 しかし、Time オブジェクトが time_t を常に必要とするわけでは ありません。ファイルのタイムスタンプを設定する等、システムと のインターフェースでは必要になりますが、それはそういうインター フェースを使った段階で例外を起こせばいいのではないでしょうか。 単に Ruby の内部で Time オブジェクトを生成し、比較したりする ぶんには time_t の値を生成する必要はないはずです。 こういう時刻の範囲の問題は、メールだけに限りません。たとえば YAML 内の時刻とか、SQL で扱う時刻とか、一般に time_t とは関 係ない文脈で表現された時刻を扱うときには常に問題になります。 そういうときは DateTime を使えというのが FAQ ですが、そもそ も FAQ になるほど Time が使われているという現実があるわけで、 Time でやってもいいんじゃないでしょうか。 また、DateTime だと閏秒が扱えないという問題もあります。気に する人は多くないかもしれませんし、Time であってもシステム次 第ですが。 Time を拡張する上での問題点はいくつかありますが、以下のよう にそれなりに解決可能です。ちょっと無理をしているところもあり ますけれど。 (ここに [ruby-dev:38191] の実装上の問題点と対処の話を挿入) どんなもんでしょう? -- [田中 哲][たなか あきら][Tanaka Akira]