freezegun: Faked time shouldn't always be the same.
Excerpt from the docs:
“[…] all calls to datetime.datetime.now(), datetime.datetime.utcnow(), […] will return the time that has been frozen.”
But this is not the behaviour I expect.
Example code:
from datetime import datetime
def test_something():
print('now(): ', datetime.now())
print('utcnow():', datetime.utcnow())
Output without Freezegun (system timezone is “Europe/Berlin”):
now(): 2015-03-10 00:46:40.465879
utcnow(): 2015-03-09 23:46:40.466031
Output with Freezegun (method decorated with @freeze_time('2012-03-11 19:21:23')):
now(): 2012-03-11 19:21:23
utcnow(): 2012-03-11 19:21:23
However, I expected the output with Freezegun to reflect the offset (one hour, in this case) and, thus, to return two different date/time instances.
About this issue
- Original URL
- State: open
- Created 9 years ago
- Reactions: 9
- Comments: 43 (19 by maintainers)
@charettes For me the point of freeze_time is that you create a world where time related things are predictable and portable across machines. Leaving the time zone as is will not satisfy this demand.
I’m all for having a nicer way to freeze but still respect the time zone if that’s what you want though. I’d also like a better way to “freeze” and still respect the local time! This is super useful to initialize the monkey patching just once for your entire test suite for example. We do this at work (and we use my fork that is also an active PR) and it has some pretty dramatic performance advantages if you freeze time a lot.
I’d suggest this:
freeze_time('local', tzinfo='local', tick=True)for respecting time zone, local time and keeping the clock movingfreeze_time('2001-01-02', tzinfo='local')for respecting local time zone but locking the restfreeze_time('2001-01-02')for locking everything…as for tzinfo vs tzoffset I’m all for it. The only problem I see with it is that if you specify a time zone by name that can mean something different at some later point. tzoffset doesn’t have this problem, but it also doesn’t model DST properly, so I think maybe a third option is needed here? In addition to your suggestion that is.
From this thread we can get some test cases on how it should work, and from the other duplicates as well. I guess no one actually did a full summary of the related issues?
I guess I can give this a shot as I need to work around this right now.
So how are we supposed to test code that travels in time in a certain timezone which is not UTC (and has DST)?
Supposing I have a function that returns the Unix timestamp of the beginning of the sixth month from now (1st, 00:00:00), localtime. How would I test it? More specifically, how would I test that it actually takes localtime into account?
This ticket is also in direct conflict with https://github.com/spulec/freezegun/issues/204 as far as I can tell. Users seem to expect the time zone to be locked to UTC by default. I would and so does @azmeuk .
One thing I didn’t realize until now is that our existing support for tz offsets already makes the assumption that we are passing the time for
utcuse. From the README:If we wanted to keep this all working, would the fix be a matter of setting
tz_offsetto default totime.timezone / 3600?Can’t agree more!
The system time zone? Absolutely. I would even consider it a critical bug if it did not (which it doesn’t currently in a bunch of cases). The point of freezegun is to not respect the system time. Time zones are a part of the system time.
You should not be able to accidentally write tests, when using freezegun, that pass on one machine and then does not pass on another.
If you do want to write tests dealing with time zones other than UTC you should freeze to that time zone. I realize that this is currently rather broken, but we should fix that and not break freezegun more.
@charettes You should try my fork! https://github.com/boxed/freezegun/ We freeze time on all tests by default (see also https://medium.com/@boxed/flaky-tests-part-3-freeze-the-world-e4929a0da00e). Our unit test suite took 8 minutes when I introduced this freeze-everything. My fork puts the time back to the ~20 seconds it takes without freezing time at all. Initializing freezegun just once is crucial though since monkey patching back and forth is pretty expensive. That wasn’t the biggest performance issue, but it was one we had to fix too.
I disagree with the premise at the start ofthis ticket. It’s MUCH nicer if freezegun locks timezone to UTC. The entire reason we use freezegun is to make time predictable in tests, so having it freezing the time but not the timezone would be a big mistake. This is a documentation issue.