When you set date attributes, you should not pass times

Posted About 11 years ago. Visible to the public. Repeats.

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
Last edit
About 6 years ago
Posted by Arne Hartherz to HouseTrip Deck (2013-03-15 11:05)