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
on 2006-05-09 15:46
on 2006-05-09 21:23
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.
on 2006-05-09 21:30
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...
on 2006-05-09 22:17
What database are you using? What is the SQL structure of the table with the field in question?
on 2006-05-09 23:24
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! :) 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,
on 2006-05-09 23:46
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.
on 2006-05-10 00:48
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 - firstname.lastname@example.org - http://www.rdwarf.com/~wwonko/ "Here at the Phone Company, we serve all kinds of people; from Presidents and Kings to the scum of the earth ..."
on 2006-05-10 09:33
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 2007-09-26 05:17
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
on 2007-09-26 17:10
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