-
Notifications
You must be signed in to change notification settings - Fork 269
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
tz_offset and datetime.now(utc) don't interact correctly #348
Comments
Now that I am looking at it, is this commit and test just wrong: 7236d4c The |
Right, that test looks like it's attempting to assert that |
i'm encountered the same issue: When default timezone is UTC with freeze_time('2017-11-24T10:54:36.762+05:00', tz_offset=5):
print(datetime.datetime.now().astimezone())
2017-11-24 10:54:36.762000+00:00 I expect output should be |
In my case of course i should not use Line 355 in 6cfbc48
like this: def now(cls, tz=None):
now = cls._time_to_freeze() or real_datetime.now()
if tz:
result = now.astimezone(tz)
else:
result = now
return datetime_to_fakedatetime(result) May be i wrong and don't know about real |
My final workaround for conftest.py def patched_freezgun_astimezone(self, tz=None):
from freezegun.api import datetime_to_fakedatetime
from freezegun.api import real_datetime
if tz is None:
from freezegun.api import tzlocal
tz = tzlocal()
real = self
if real.tzinfo is None:
# we work with naive UTC date time
# to correct converting make it aware
mytz = datetime.timezone(self._tz_offset())
real = self.replace(tzinfo=mytz)
return datetime_to_fakedatetime(real_datetime.astimezone(real, tz))
freezegun.api.FakeDatetime.astimezone = patched_freezgun_astimezone Works fine with/without tz_offset: System TZ is UTC+5 for tz_offset in (0, 5):
with freeze_time('2017-11-24T10:54:36.762+05:00', tz_offset=tz_offset):
assert datetime.datetime.now().astimezone().isoformat() == '2017-11-24T10:54:36.762000+05:00' System TZ is UTC for tz_offset in (0, 5):
with freeze_time('2017-11-24T10:54:36.762+05:00', tz_offset=tz_offset):
assert datetime.datetime.now().astimezone().isoformat() == '2017-11-24T05:54:36.762000+00:00' |
And we can workaround def patched_freezegun_now(cls, tz=None):
from freezegun.api import datetime_to_fakedatetime
from freezegun.api import real_datetime
now = cls._time_to_freeze() or real_datetime.now()
result = now + cls._tz_offset()
result = datetime_to_fakedatetime(result)
if tz:
result = cls.astimezone(result, tz)
return result
freezegun.api.FakeDatetime.astimezone = patched_freezgun_astimezone # make sure you patch `astimezone`
freezegun.api.FakeDatetime.now = classmethod(patched_freezegun_now) Output:
|
This patch works for me! This is the test case: @pytest.mark.parametrize("tz_offset", [
timedelta(hours=1),
timedelta(hours=0),
timedelta(hours=-2),
# ... and so on. Must work for any offset, actually
])
def test_freezegun_offset(tz_offset):
with freezegun.freeze_time("2015-10-21 07:28", tz_offset=tz_offset):
now = datetime.now()
delta = now.replace(tzinfo=timezone.utc) - now.astimezone(timezone.utc)
assert delta == tz_offset |
@boxed so, we have patch and tests in this Issue, may be it's time to integrate it into main codebase? ;) |
@spumer we do? I can't find a PR? |
Nope. I saw your last activity in commits and offer fix this issue cause here (in this issue) have problematic code example (test suite) and fix (my workaround) |
"utcnow" returns a naive timestamp, which effectively subtracts an hour from the local time, which is what we're trying to represent. datetime.fromtimestamp(datetime.utcnow().timestamp()) datetime.datetime(2022, 4, 24, 8, 8, 29, 576299) datetime.fromtimestamp(datetime.now().timestamp()) datetime.datetime(2022, 4, 24, 9, 9, 5, 365402) Using "now" is correct. Because reasoning about naive times can be so confusing, this also makes all of them timezone-aware e.g. datetime.utcnow().isoformat() '2022-04-26T07:13:24.259928' datetime.now().astimezone().isoformat() '2022-04-26T08:13:58.523714+01:00' Using "astimezone" converts the datetime object to the specified timezone by interpreting it in the implicit local timezone. Tests now set explicit timestamps or zone-aware datetimes to make it clear what actual time is being tested. Unfortunately freeze_gun is not a reliable tool for this [^1][^2] so this commit replaces it. In the case of the Octopus sensor, we are effectively converting a date to a time so we also need to lock the system timezone to ensure test stability. time-machine needs Python 3.9+ to do this [^3]. [^1]: spulec/freezegun#348 [^2]: spulec/freezegun#299 [^3]: https://github.com/adamchainz/time-machine#timezone-mocking
Hello, this has been open for 3 years. Now that python 3.11 has deprecated |
@tamird You might want to try to switch to time-machine. It's much faster and I've found it more solid. |
When debugging logging timestamps inside freezegun, noticed odd behaviour around calling
datetime.now(timezone.utc)
whenfreeze_time
is active with atz_offset
set:Output:
Because of #204, the logtimes are always localtime, which is currently +0100, correctly reflected in 'native'.
My understanding is that 'offset0' (
tz_offset=0
) should be reflecting a frozen time on the UTC timezone, barring existing bugs that attempt to load system timezone, reflected in thetime.time()
line.I believe 'offset1'(
tz_offset=1
) then should be a frozen time on a timezone with the same delta from UTC (+0100), which is correct except for thenow(utc)
line? Which should just be the same line asutcnow()
but with a +0000 timezone attached, as seen on 'native'.Not sure if this is the same as other bugs reflecting that the system timezone leaks into the freeze if unspecified, but I'm specifying an explicit timezone during the freeze, which doesn't seem exactly the same.
The text was updated successfully, but these errors were encountered: