Ruby Date Shifts

I was tracking down a failing test last night for a date related calculation. I know this test was passing and I haven’t touched the code, so I strongly suspected it was a time zone related failure. The confusing part was that these were Date objects, not DateTime objects, so they didn’t need to be time zone adjusted.

Consider this snippet of rspec:

days_to_finish = 7
some_object.started_on = days_to_finish.ago.to_date
some_object.do_some_finish_action
some_object.days_to_finish.should == days_to_finish

That was the gist of the code that was failing, and the failure was “expecting 7, got 6″. I puzzled over it for a bit, then I recreated it in console and found my issue. The problem was that I was using the Fixnum#ago helper that rails adds. That generates a DateTime object, but in UTC.

So here is what triggered it for me in console.

ruby-1.9.2-p290 :001 > Time.now
=> Mon, 10 Oct 2011 23:22:51 EST +04:00
ruby-1.9.2-p290 :001 > 7.days.ago
=> Tue, 04 Oct 2011 03:22:51 UTC +00:00

Since Time.now produces a time zone adjusted object, and Fixnum#days_ago produces UTC. Running to_date on the objects just strips the time portion out, so converting both of these does in fact give you dates that are only 6 days apart instead of the expected 7. With that knowledge, the fix was easy. I changed:

days_to_finish = 7
some_object.started_on = days_to_finish.ago.to_date

to

days_to_finish = 7
some_object.started_on = Date.today - days_to_finish.days

and my specs were green again. Nothing major, but sometimes time zone issues can crop up where you least expect them.