2

入力する100.daysと [編集:どうやら] Fixnum が得られることがわかりまし8640000

> 100.days.equal?(8640000)
 => true 

これを試すまで、これら2つの値は交換可能だと思っていたでしょう:

x = Time.now.to_date
=> Wed, 31 Oct 2012 
> [x + 100.days, x + 8640000]
=> [Fri, 08 Feb 2013, Mon, 07 May 25668] 

明らかに等しい値を同じ日付に追加すると、異なる結果が得られるのはなぜですか?

上記の結果は、Rails バージョン 3.1.3 と Ruby バージョン 1.9.2p320 を使用した Rails コンソールからのものです。(最新バージョンにアップグレードする必要があることはわかっています...)

4

2 に答える 2

6

100.daysは Fixnum を返さず、 を返します。これはActiveSupport::Duration、ほとんどの操作で整数のように見えるようにかなり努力します。

Date#+Duration が追加されてTime#+いるかどうかを検出するためにオーバーライドされ、追加されている場合は、単に整数値を追加するのではなく、適切に計算します (Time.+ は秒数を期待します。つまり、+ 86400 は 1 日進みますが、Date.+ は日数なので、+86400 は 86400 日進みます)。

さらに、サマータイムが実施される日に 1 日を追加するなど、いくつかの特殊なケースについても説明します。これTime.now + 1.monthにより、当月の日数に関係なく、1 暦月進めることもできます。

于 2012-10-31T22:33:06.090 に答える
1

フレデリックの回答が提供するものに加えて、日付に8640000を追加することは、時間に8640000を追加することと同じではなく、100.days100日の正しい指定でもありません。

100.days「この値は日数を表す」ではなく、「100 日の秒数を教えてください」という意味を考えてください。Rails は以前は秒数を返していましたが、凝った/よりスマートになり、それを期間に変更して、日付の計算が正しいことを行うことができるようにしました。そのより洗練された/よりスマートなことは、実際に何が起こっているのかをマスクすることによって遭遇したような問題を引き起こし、あなたが知るまでデバッグを困難にします.

日付の計算では、秒ではなく日の値が想定されますが、時間では秒が必要です。したがって、次の操作を行い100 * 24 * 60 * 60 = 8640000ます。

100 * 24 * 60 * 60               => 8640000
date = Date.parse('31 Oct 2012') => Wed, 31 Oct 2012
time = Time.new(2012, 10, 31)    => 2012-10-31 00:00:00 -0700

date + 8640000                   => Mon, 07 May 25668
time + 8640000                   => 2013-02-08 00:00:00 -0700
date + 100                       => Fri, 08 Feb 2013

時間と日付を扱うのは面倒な場合があり、書いたコードの忘れた場所でバグに遭遇することは間違いありません。ActiveSupport::Duration 部分は、日付/時刻オフセットの一部を処理することで役立ちます。最善の戦術は、Date/DateTime または Time のいずれかを使用し、どうしても必要な場合を除き、それらを混在させないことです。それらを混在させる必要がある場合は、コードをメソッドにボトルネックさせて、問題が発生した場合に調べる場所を 1 か所にします。

Time が処理できるよりも大きな範囲を処理する必要がある場合は、Date と DateTime を使用します。また、DateTime には他にも便利な機能がいくつかあります。それ以外の場合は、OS と C により密接に結合されているので Time を使用します (そして、そこに私のルーツのいくつかを明らかにしました。 )

于 2012-10-31T22:54:42.867 に答える