tags:

views:

22

answers:

1

Ruby's Time.parse() works for dates from Dec 14 1901 up Jan 18 2038 (this appears to be system dependent):

# works
irb(main):038:0> Time.parse('14-12-1901')
=> Sat Dec 14 00:00:00 -0600 1901

# doesn't work
irb(main):039:0> Time.parse('13-12-1901')
ArgumentError: time out of range
    from /usr/lib/ruby/1.8/time.rb:184:in `local'
    from /usr/lib/ruby/1.8/time.rb:184:in `make_time'
    from /usr/lib/ruby/1.8/time.rb:243:in `parse'
    from (irb):39
    from /usr/lib/ruby/1.8/date/format.rb:214

I can't think of the reason why it stops working there. Why the odd cut-off? How can I programatically get the valid range?

+3  A: 

Ruby's Time class is a wrapper around time_t, which uses a signed int to represent seconds since the beginning of the Unix epoch. With a 32-bit int, this causes the 1901-2038 boundaries you're experiencing. This is often referred to as the Y2038 bug.

PHP actually suffers from this same bug, so while this is a weird source for answering a Ruby question, here's an except from the PHP manual:

The valid range of a timestamp is typically from Fri, 13 Dec 1901 20:45:54 UTC to Tue, 19 Jan 2038 03:14:07 UTC. (These are the dates that correspond to the minimum and maximum values for a 32-bit signed integer.) Additionally, not all platforms support negative timestamps, therefore your date range may be limited to no earlier than the Unix epoch.

According to this article, Ruby 1.9.2 should fix this issue (and Rails accounts for it as well).

Alternately, you can use the DateTime class, which is able to parse the dates you're having issues with:

DateTime.parse('13-12-1901').strftime("%Y-%m-%d")
=> "1901-12-13"
Daniel Vandersluis
Ah it all makes sense now. 2038-1902 ~= 136 years ~= 4.29 x 10^9 seconds ~= 2^32.
Confluence