Working around the year 2038 bug in Ruby's Time class?

I would have never imagined that I’d be bitten by the Y2038 bug
someday… but it just happened and, trust me, it hurts!

I have to deal with a database containing datetime fields with dates
up to 2050 and more. ActiveRecord raises an exception because Ruby’s
Time class implementation.

Besides running Ruby on a 64-bit platform, what can be done to avoid
that?

Does a transparent, dynamic replacement exists for the Time class?
I googled for this but couldn’t find anything…

As a last resort, is there a “clean” way to disable Time conversions
in AR? It would be cool to be able to do this on a per-class basis?

Cheers,

Xavier

Xavier wrote:

I would have never imagined that I’d be bitten by the Y2038 bug
someday… but it just happened and, trust me, it hurts!

I have to deal with a database containing datetime fields with dates
up to 2050 and more. ActiveRecord raises an exception because Ruby’s
Time class implementation.

Besides running Ruby on a 64-bit platform, what can be done to avoid
that?

Does a transparent, dynamic replacement exists for the Time class?
I googled for this but couldn’t find anything…

As a last resort, is there a “clean” way to disable Time conversions
in AR? It would be cool to be able to do this on a per-class basis?

Cheers,

Xavier

Is it possible to use Date instead of Time? I think it has a much
greater range of values.

The issue here is that ActiveRecord’s SQL/Ruby type mapper explicitly
uses Time and the exception is raised in there, not in my application
code…

What database are you using? What is the SQL structure of the table
with
the field in question?

Okay. Is your column in question of type datetime or smalldatetime?
These
are the only date handling column types that will not be mapped to Ruby
Time
objects in the sqlserver_adapter.

For the record, I’m connecting to SQL Server 2003 through
unixODBC/FreeTDS on Debian but I’m sure the issue is not database
related.

Just fire up irb and try to fit a date after Tue Jan 19 03:14:07 2038
into a Time object. If the underlying OS has the Y2k38 bug (I believe
this is the case with most Linux installs running on IA32 hardware at
this time), you’ll get an ArgumentError.

So what happens here is that, no matter the database driver, whenever
you retrieve a row from a table that contains a date or datetime
column with a date out of the 32-bit POSIX time_t date range, the
operation will fail right when ActiveRecord will attempt to convert
the column value into a Time instance.

This is a really significant issue and I do really hope, the next
release of Ruby will cope with this by switching to another internal
(and probably slower) representation if the date gets out of the
time_t range…

I know we will all most probably use 4096-bit quantum computers built
right into our cortex by 2038 but nonetheless I do really believe we
need a bugfix now! :slight_smile:

I can’t believe no one ever ran into this issue before using
ActiveRecord so please share your experience, I’m thinking about a
bunch of workarounds but they just don’t “feel” right to me…

Cheers,

IMHO, the best solution is definitely to fix in one way or another the
Time implementation. I don’t really like the idea of using another
external representation of time (like YMDHMS strings) because then you
lose all the fancy features provided by Rails’ core type extensions
like 2.minutes.ago, they all use Time.

I wish I had time right now to write a Time class replacement but as
Louis said, that’s some major pain in the a** in sight…

On Tue, 9 May 2006, Xavier wrote:

The issue here is that ActiveRecord’s SQL/Ruby type mapper explicitly
uses Time and the exception is raised in there, not in my application
code…

I knew there was a reason I never use DB date/time fields! I almost
always use char(14), and store YYYYMMDDHHMMSS. They sort right as
strings
or numbers, and I’ve yet to run in to a tool that can’t extract dates
and
times from them.

As has been suggested, the simplest might be not to use a format that AR
knows is a Time and then write some code to parse/format them.

My cheesy workaround aside, could you reimplement Time itself?

If I understand correctly, Ruby classes are open, so you could just
implement the class again, using a different storage mechanism. AR
would
use it, and not mind the bigger numbers any more.

That could be a huge PITA to get right, though, as time is hard. (As
someone who’s had to implement all of this in C, repeatedly, I feel I am
qualified to say that.)

It might be easier to override/replace the piece of ActiveRecord that
decided that particular field type in the db maps to a Time object. I’m
not sure which would be less painful. DateTime looks like it stores
things in a less brittle format, but it might have other limits.

I haven’t heard of anyone else who’s done this already.


Louis Erickson - [email protected] - Lou's Home Page!

“Here at the Phone Company, we serve all kinds of people; from
Presidents and Kings to the scum of the earth …”

You could override native_database_types on the connection adapter used
so that it tells AR to use DateTime objects (which don’t have the same
range restrictions)

Fred

Hello Good Day to all,

Has Anybody here found another work around for this bug aside from
implementing a Time class replacement?

I’m kinda working on something that deals with years further than 2038,
and its not running on 64-bit platform.

Any suggestion will be of great help. Thanks