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::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::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.
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:
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.