timecop
timecop copied to clipboard
DateTime and Time comparison don't work as expected after freeze.
My tests started to randomly failed and I can pin it down to this:
In a rails project rails c
[1] pry(main)> Time.now < DateTime.now
=> true
[2] pry(main)> Time.now == DateTime.now
=> false
[3] pry(main)> Time.now > DateTime.now
=> false
[4] pry(main)> require 'timecop'
=> true
[5] pry(main)> Time.now < DateTime.now
=> true
[6] pry(main)> Time.now == DateTime.now
=> false
[7] pry(main)> Time.now > DateTime.now
=> false
[8] pry(main)> Timecop.freeze
=> 2013-11-25 10:37:21 +0100
[9] pry(main)> Time.now < DateTime.now
=> true
[10] pry(main)> Time.now == DateTime.now
=> false
[11] pry(main)> Time.now > DateTime.now
=> false
[12] pry(main)> Time.now
=> 2013-11-25 10:37:21 +0100
[13] pry(main)> Time.now.to_f
=> 1385372241.1129415
[14] pry(main)> DateTime.now
=> Mon, 25 Nov 2013 09:37:21 +0000
[15] pry(main)> DateTime.now.to_f
=> 1385372241.1129415
[1] pry(main)> Time.now < DateTime.now
=> true
[2] pry(main)> Time.now == DateTime.now
=> false
[3] pry(main)> Time.now > DateTime.now
=> false
[4] pry(main)> require 'timecop'
=> true
[5] pry(main)> Time.now < DateTime.now
=> true
[6] pry(main)> Time.now == DateTime.now
=> false
[7] pry(main)> Time.now > DateTime.now
=> false
[8] pry(main)> Timecop.freeze
=> 2013-11-25 10:38:05 +0100
[9] pry(main)> Time.now < DateTime.now
=> false
[10] pry(main)> Time.now == DateTime.now
=> false
[11] pry(main)> Time.now > DateTime.now
=> true
[12] pry(main)> Time.now
=> 2013-11-25 10:38:05 +0100
[13] pry(main)> Time.now.to_f
=> 1385372285.204306
[14] pry(main)> DateTime.now
=> Mon, 25 Nov 2013 09:38:05 +0000
[15] pry(main)> DateTime.now.to_f
=> 1385372285.204306
Without freezing time Time.now is called before DateTime.now so it is smaller. When time freeze this behavior becomes random, as you can see with the two test runs. I expected them to equal each other.
rails (4.0.1) timecop (0.6.3) ruby 2.0.0p247
Here is a simple example to reproduce the problem
non-working example: freezing once:
[76] pry(main)> Timecop.return => 2014-10-29 12:29:14 +0100 [77] pry(main)> Timecop.freeze(Time.parse("2014-08-25 18:53:35 +0200")) => 2014-08-25 18:53:35 +0200 [78] pry(main)> DateTime.now.utc => Mon, 25 Aug 2014 17:53:35 +0000 [79] pry(main)> Time.now.utc => 2014-08-25 16:53:35 UTC
=> working example, freezing twice:
[80] pry(main)> Timecop.return => 2014-10-29 12:29:42 +0100 [81] pry(main)> Timecop.freeze(Time.parse("2014-08-25 18:53:35 +0200")) => 2014-08-25 18:53:35 +0200 [82] pry(main)> Timecop.freeze(Time.parse("2014-08-25 18:53:35 +0200")) => 2014-08-25 18:53:35 +0200 [83] pry(main)> DateTime.now.utc => Mon, 25 Aug 2014 16:53:35 +0000 [84] pry(main)> Time.now.utc => 2014-08-25 16:53:35 UTC
I can reproduce this issue. I get random failures on rspec with Timecop.freeze
due to inconsistent time comparison results.
If I freeze twice (literally just call Timecop.freeze
twice with the same arguments), as @TheWudu suggested, the tests pass 100% of the time.
My first impression is that this is a daylight-savings issue; the first freeze appears to be using the current UTC offset, which in this case is wrong because the time we're freezing to is has a different UTC offset than the current time (which explains the one-hour difference), but then the second freeze works because the "current" (read: mocked frozen) time has the same offset as our desired time.
I'll look into the code itself later today when I'm at a computer; would you be willing to share your named timezone (e.g., America/Los_Angeles
or Europe/Paris
), so I can duplicate your environment?
Hi again. My timezone is Europe/Vienna. I also thought it could have something to do with daylight saving time.