开发者

Why do my time-related unit tests break every day at 4pm?

For a long time I've been having this issue that at a certain time of the day, a TON of my tests break. I have a lot of tests that are doing 开发者_C百科simple date comparisons and everything runs fine from midnight to like 4:00 in the afternoon. Any idea why this is happening? I've set my timezone in my environment file too.

It seems like some of my calls like 5.days.from_now.to_date are adding an extra day.

Edit

For instance, this test fails:

# Widget that creates items for how many days the trip is gone.
def test_should_create_correct_amount_of_days_for_trip
  w = DayWidget.create(:trip => trips(:hawaii))
  assert_equal w.days.size, 5
end

# Code in trip model that calculates amount of days
def number_of_days
  (self.return_date.to_date - self.depart_date.to_date).to_i + 1
end

# Test fixture yaml for Hawaii
hawaii:
  depart_date: <%= Time.now.tomorrow.to_s(:db) %>
  return_date: <%= 5.days.from_now.to_s(:db) %>

After 4:00 pm, the test above fails and says it created 6 days instead of 5. :(


You're probably in the Pacific time zone, 8 hours behind UTC (which is why at 4:00p they start breaking, since that's when it hits midnight UTC).

Without seeing your test/comparison code, all I could say is to make sure you're comparing dates/times with the same location (UTC to UTC or localtime to localtime).

Update: Ok, it looks like Time.now returns a Time object, whereas using XXX.days.from_now returns an ActiveSupport::TimeWithZone object, resulting in different handling of timezones:

ruby-1.9.2-p136 :009 > (Time.now+5.days).to_s(:db)
 => "2011-02-08 19:40:24" 
ruby-1.9.2-p136 :010 > 5.days.from_now.to_s(:db)
 => "2011-02-09 03:40:29" 

My recommendation would be to either call .utc on your times in your fixtures like so:

ruby-1.9.2-p136 :017 > 5.days.from_now.utc.to_s(:db)
 => "2011-02-09 03:42:39" 
ruby-1.9.2-p136 :018 > (Time.now+5.days).utc.to_s(:db)
 => "2011-02-09 03:42:39" 

or to just switch to using 1.day.from_now instead of Time.now.tomorrow to keep the types consistent.


You can also use Time.current instead of Time.now.

Time.current returns ActiveSupport::TimeWithZone just like #ago and #from_now, so you can safely compare dates returned by them.


If you are truly dealing with just dates, be sure to set the hours, minutes and seconds to 0, otherwise you are at the mercy of the time of day you create the dates.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜