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

Zac*_* Xu 9 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)>
Run Code Online (Sandbox Code Playgroud)

有人能解释为什么会这样吗?这与Unix时间有什么关系吗?

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

mra*_*lau 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)>
Run Code Online (Sandbox Code Playgroud)

1583的日期是正确的,但1582的日期不正确.如果你看一下Time.to_date,你可以看到,它始终认为一个日期是公历日期 -即它包括闰年.另请注意,切换到公历是在1582年,解释了上述行为的截止.(对于那些对源代码真正感兴趣的人,请注意,对decode_year的调用是将-1作为style参数传递,它总是使对该函数的所有调用都使用公历日期.)

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