Thursday 31 January 2008

Rails gotchas: 1.months.ago isn't

A colleague caught this bug when we were running rake test today (Jan 31st). Suddenly the quota-calculation tests were acting weird. All our tests ran fine yesterday, so we were both pretty perplexed by why they'd suddenly stopped working today.

Quota is calculated based on a calendar month... so he delved into the fixtures looking for dates. What he came up with was a short script/console session showing the results below:

>> Time.now
=> Thu Jan 31 03:11:55 +0000 2008
>> 1.months.ago
=> Tue Jan 01 03:12:02 +0000 2008

Clearly "months ago" really isn't - it's actually "30 days ago". This means that our tests will be working again fine tomorrow, just as they have been all month... and only failed because (like so *few* other months in the year), we have 31 days in January, and this is it.

The fixtures in question had something similar to "save these quota-eating things as happening one month ago and check they don't eat into this month's quota too". And yet today, "one month ago" was being evaluated as Jan 1st... :P

With experimentation, the following does work correctly, even across funky boundaries:

>> Time.now.months_ago 1
=> Mon Dec 31 03:12:09 +0000 2007
>> date = Time::parse "March 31 2008"
=> Mon Mar 31 00:00:00 +0000 2008
>> date.months_ago 1
=> Fri Feb 29 00:00:00 +0000 2008