We're using Ruby 1.9.3, and I found what appears to be a strange Ruby error with Time#to_date
Time.new(1).to_date
returns 3 January 0001 when it should return 1 January 0001.
I discovered this problem accidentally. It seems if I call .to_datetime.to_date
,
the result would be correct.
I also found some other related weirdness. See the irb console output below. (Note I'm using irb, not rails console to ensure that it's only Ruby I'm using, not any add-on stuff of 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)>
Could someone explain why this happens? Is this related to Unix time somehow?
It seems DateTime is more reliable, at least with Ruby 1.9.3.
Advertisements. The Time class represents dates and times in Ruby. It is a thin layer over the system date and time functionality provided by the operating system. This class may be unable on your system to represent dates before 1970 or after 2038.
It's because of how leap year is implemented in the ruby Time.to_date
method.
Note that the cutoff for your strange behavior happens between 1583 and 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)>
Where 1583's date is correct but 1582's is incorrect. If you look at the source for Time.to_date
, you can see that it always considers a date to be a Gregorian calendar date - i.e. it includes leap year. Also note that the switch to the Gregorian calendar was in 1582, explaining the cutoff for the behavior above. (For those really interested in the source code, note that the call to decode_year is passing -1 as the style
parameter, which always makes all calls to that function use a Gregorian calendar date.)
So that means any dates before 1583 will be incorrect when displaying them with this method.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With