Read more

Don't assign time values to date attributes

Arne Hartherz
March 15, 2013Software engineer at makandra GmbH

Do not pass times to date attributes. Always convert times to dates when your application uses time zones.

Background

Illustration online protection

Rails Long Term Support

Rails LTS provides security patches for old versions of Ruby on Rails (2.3, 3.2, 4.2 and 5.2)

  • Prevents you from data breaches and liability risks
  • Upgrade at your own pace
  • Works with modern Rubies
Read more Show archive.org snapshot

A time-zoned Time attribute on a Rails record is converted to UTC using to_s(:db) to be stored, and converted back into the correct time zone when the record is loaded from the database. So when you are not on UTC, time objects will be converted as follows.

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

Problem

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 that whenever you pass a time that is within X hours away from midnight (where X is your +UTC time difference) you will store incorrect dates:

# 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" # This is the correct representation of our time.

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

Note how the date should be 01/01/2050 but is not. This is because of the UTC timestamp string being cut off by the database. After all, it wants to store a date, not a time.

When dealing with dates, remember to always pass dates. So use Date.current, or if you want to say something like 3.days.from_now you must make sure to convert it via 3.days.from_now.to_date.

Posted by Arne Hartherz to makandra dev (2013-03-15 13:42)