DateTime not fully supported?

It looks like DateTime objects are only marginally supported by the activerecord library.

ActiveRecord::ConnectionAdapters::Column#string_to_time (supposedly correctly) returns datetime values on and after 1970 as Time objects and values prior to 1970 as DateTime objects. But seems like that is where DateTime support stops.

Suppose, I have a legacy MySQL database with the following date stored in a datetime field: "1917-10-25 21:40:00". Simply loading that object and saving it back into the database fails, because ActiveRecord::ConnectionAdapters::Quoting formats that date (loaded as DateTime object) as "1917-10-25T21:40:00Z". MySQL does not like that format (in particular the "T" and the "Z") and save fails.

I will gladly put together a patch for resolving this issue, if the core team gives me a bit of guidance on the topic. What is the right approach? To add a Conversions module similar to ActiveSupport::CoreExtensions::date::Conversions for DateTime?

I will gladly put together a patch for resolving this issue, if the core team gives me a bit of guidance on the topic. What is the right approach? To add a Conversions module similar to ActiveSupport::CoreExtensions::date::Conversions for DateTime?

You should be able to get by with just ensuring that the quoting mechanisms in ActiveRecord know how to format DateTimes for Mysql. I don't imagine you'll need an extension

fedot, this might be of help to you -- I've created a patch that adds correct #to_s conversions for DateTime, most importantly, #to_s(:db), which allows DateTimes to be sent to the db in the correct format -- "%Y-%m-%d %H:%M:%S" -- instead of the parent class Date#to_s(:db) "%Y- %m-%d" format.

I've got this patch sitting in a plugin in my project, and with it I'm able to accurately read + write Ruby DateTimes via a Mysql db datetime field.

This patch requires edge rails, btw -- the latest gem version doesn't include the necessary acts_like? method.

http://dev.rubyonrails.org/ticket/7649

Geoff

I've applied this to trunk, i think the fix is simple enough to merge to stable too, will do that in a bit.

I've created another DateTime-related patch -- this one adding DateTime::Calculations to ActiveSupport::CoreExtensions.

This will allow you to call the same ActiveSupport methods available for Time instances on DateTime instances, like beginning_of_day, months_ago, monday, midnight, since, advance, seconds_since_midnight, etc. Example:

DateTime.now.since(3.hours).to_s(:long)

=> "March 02, 2007 05:56"

Time.now.since(3.hours).to_s(:long)

=> "March 02, 2007 05:56"

http://dev.rubyonrails.org/ticket/7693

Geoff

Geoff, this is exactly what I had in mind. Thank you for putting the patch together. I also added another patch to your ticket for test/ migration_test.rb ensuring that datetime fields falling below DateTime's lower limit get read back in as DateTime objects.

A third patch in the DateTime trilogy -- this one provides fallback behavior on Time::Calculations so that a DateTime is returned if the result is out of the range supported by the Ruby Time class (currently, it just returns "ArgumentError: time out of range".)

If all of these patches were added to the trunk (currently, just the first one is), you could then do something like this:

Time.now.years_since(32).beginning_of_day

...and then save it to the db with the correct date and time.

Would this then make Rails Year-2038-Compliant?

http://dev.rubyonrails.org/ticket/7706

Geoff

Committed. Great work, Geoff.

Thanks,

jeremy

The trilogy is complete: http://dev.rubyonrails.org/changeset/6305

jeremy