Make sure you are not using methods like “1.day.ago” when dealing with a Date column

TL;DR: Read the title ;)

I spent too many hours debugging a feature spec in an application. Turns out I was simply not paying attention to what I was doing!

In a fixture file, I was setting a field the following way:

some_date: <%=1.day.ago.to_s :db%>

I didn’t pay attention to the fact that “some_date” was a Date and not a DateTime. This single line was responsible for some intermittent failures in my test suite.

The technical explanation
The problem is that methods like “days.ago” return ActiveSupport:TimeWithZone objects which contain, well, the time portion along with the current timezone info. Then there is the to_s(:db) part which convert the resulting DateTime in UTC for storage in the DB. It means that if I call “1.day.ago.to_s :db” on september 7th at 8:00 PM (local timezone, which is UTC -4 for me), the result will be “2014-09-07 00:00:00″ UTC time. And since I was storing this in a Date column, the time portion would simply gets discarded… so I ended up with a date of September 7th instead of the expected September 6th in the DB.

Solution
Of course this problem was very easy to fix once I understood what was causing it. I simply changed the fixture file so that it looks like:

some_date: <%=1.day.ago.to_date.to_s :db%>

This works as well:

some_date: <%=Date.yesterday.to_s :db%>

Hoping this will save others some painful debugging!

  • Nick

    I actually like using the Date#advance method for shifting dates.

    Date.current.advance(days: 6)

    You can also go backwards

    Date.current.advance(days: -6)

    You can specify :years, :months, :weeks, :days as the amount to advance.

    Stops you using times to specify dates not matter how many days you need to shift.

  • http://pomapie.blog.com/ http://pomapie.blog.com

    I just like the valuable information you supply to your articles.
    I’ll bookmark your weblog and check once more here regularly.
    I am slightly sure I will learn many new stuff proper here!

    Good luck for the following!