When you set date attributes, you should not pass times

As you know, time zones make stuff a bit more difficult but are necessary.

A time-zoned record is converted to UTC using to_s(:db) to be stored, and put back into the correct time zone when loaded. So when you are not on UTC, the following will happen:

>> Time.current
=> Fri, 15 Mar 2013 11:56:03 CET +01:00
>> Time.current.to_s(:db)
=> "2013-03-15 10:56:03" # This is now UTC

That will blow up in your face when you send times to attributes that expect dates, just because those times will also be converted using to_s(:db) and sent to MySQL. The database itself does not care about the (longer) value and just stores the date part.

This means it fails every time you are doing the above with timestamps that are within X hours away from midnight, where X is your +UTC time difference:

# Just like above, but we're close to midnight:
>> Time.current
=> Sat, 01 Jan 2050 00:15:00 CET +01:00 
>> Time.current.to_s(:db)
=> "2049-12-31 23:15:00"

# Now let's create stuff:
>> SomeRecord.create! :my_date => Time.current
=> ...
>> SomeRecord.last.start_date
=> Fri, 31 Dec 2049 # Boom.

Please remember to always use dates for this. So use Date.current, or if you want to say something like 3.days.from_now you must make sure to say 3.days.from_now.to_date.

Arne Hartherz over 8 years ago
This website uses short-lived cookies to improve usability.
Accept or learn more