Ruby Time#to_date()方法返回错误的日期

时间:2014-03-20 14:10:47

标签: ruby

我们正在使用Ruby 1.9.3,我发现Time#to_date

出现了一个奇怪的Ruby错误

Time.new(1).to_date将于0001年1月3日返回,届时应返回0001年1月1日。

我意外地发现了这个问题。好像我打电话给.to_datetime.to_date, 结果是正确的。

我还发现了一些其他相关的怪异。请参阅下面的irb控制台输出。 (注意我使用的是irb,而不是rails控制台,以确保它只是我正在使用的Ruby, 不是Rails的任何附加内容。)

>> require "Time"
=> true
>> Time.new(1).to_date
=> #<Date: 0001-01-03 ((1721426j,0s,0n),+0s,2299161j)>
>> Time.new(1).to_datetime
=> #<DateTime: 0001-01-01T00:00:00+01:00 ((1721423j,82800s,0n),+3600s,2299161j)>
>> Time.new(1).to_datetime.to_date
=> #<Date: 0001-01-01 ((1721424j,0s,0n),+0s,2299161j)>
>> Time.new(100).to_date
=> #<Date: 0100-01-03 ((1757585j,0s,0n),+0s,2299161j)>
>> Time.new(1969).to_date
=> #<Date: 1969-01-01 ((2440223j,0s,0n),+0s,2299161j)>
>> Time.new(500).to_date
=> #<Date: 0499-12-31 ((1903682j,0s,0n),+0s,2299161j)>
>> Time.new(1000).to_date
=> #<Date: 0999-12-27 ((2086303j,0s,0n),+0s,2299161j)>
>> Time.new(2014).to_date
=> #<Date: 2014-01-01 ((2456659j,0s,0n),+0s,2299161j)>
>> Time.new(1,1,1,10,0,0, "+00:00").to_date
=> #<Date: 0001-01-03 ((1721426j,0s,0n),+0s,2299161j)>
>> DateTime.new(1,1,1,10,0,0, "+00:00").to_date
=> #<Date: 0001-01-01 ((1721424j,0s,0n),+0s,2299161j)>

有人可以解释为什么会这样吗?这是否与Unix时间有关?

似乎DateTime更可靠,至少使用Ruby 1.9.3。

1 个答案:

答案 0 :(得分:5)

这是因为在ruby Time.to_date方法中实现了闰年。

请注意,您的奇怪行为的截止发生在1583和1582之间:

>    Time.new(1583).to_date
=> #<Date: 1583-01-01 ((2299239j,0s,0n),+0s,2299161j)>
>    Time.new(1582).to_date
=> #<Date: 1581-12-22 ((2298874j,0s,0n),+0s,2299161j)>

1583的日期是正确的,但1582的日期不正确。如果您查看Time.to_date的{​​{3}},则可以看到它始终将日期视为source - 即它包含闰年。另请注意,切换到公历是在1582年,解释了上述行为的截止。 (对于那些对源代码真正感兴趣的人,请注意对Gregorian calendar date的调用是将{-1}作为style参数传递,这总是使对该函数的所有调用都使用公历日期。)

这意味着使用此方法显示1583之前的任何日期都是不正确的。