Skip to content
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

[Bug] tz_offset shifts datetime which is instantiated with tz argument #553

Open
yukihiko-shinoda opened this issue Jul 18, 2024 · 0 comments

Comments

@yukihiko-shinoda
Copy link

Correct specification

In nature, the datetime that is created by datetime.now()will be same timestamp even if we set any different tz argument:

from datetime import datetime, timedelta, timezone
from freezegun import freeze_time
from dateutil.tz import tzlocal


def test_freezegun1() -> None:
    timestamp_utc_fixed = int(datetime.now(tz=timezone(timedelta(hours=0))).timestamp() * 1000)
    timestamp_tzlocal = int(datetime.now(tz=tzlocal()).timestamp() * 1000)
    # - Answer: datetime - Python: Figure out local timezone - Stack Overflow
    #   https://stackoverflow.com/a/39079819/12721873
    timestamp_local_timezone = int(datetime.now(tz=datetime.now(timezone.utc).astimezone().tzinfo).timestamp() * 1000)
    timestamp_no_tz = int(datetime.now().timestamp() * 1000)
    assert timestamp_utc_fixed == timestamp_no_tz
    assert timestamp_tzlocal == timestamp_no_tz
    assert timestamp_local_timezone == timestamp_no_tz

cf: The specification of datetime.datetime.timestamp():
datetime — Basic date and time types — Python 3.12.4 documentation

Bug details

When we use freeze_time() with argument: tz_offset,
the datetime that is created by datetime.now() with the argument: tz was shifted as same as tz_offset
against the datetime that is created by datetime.now() without the argument: tz:

from datetime import datetime, timedelta, timezone
from freezegun import freeze_time
from dateutil.tz import tzlocal


DIFFERENCE_TIMESTAMP_JST = 9 * 60 * 60 * 1000


@freeze_time("2022-08-09 11:26:00.000", tz_offset=-9)
def test_freezegun2() -> None:
    timestamp_utc_fixed = int(datetime.now(tz=timezone(timedelta(hours=0))).timestamp() * 1000)
    timestamp_tzlocal = int(datetime.now(tz=tzlocal()).timestamp() * 1000)
    # - Answer: datetime - Python: Figure out local timezone - Stack Overflow
    #   https://stackoverflow.com/a/39079819/12721873
    timestamp_local_timezone = int(datetime.now(tz=datetime.now(timezone.utc).astimezone().tzinfo).timestamp() * 1000)
    timestamp_no_tz = int(datetime.now().timestamp() * 1000)
    assert timestamp_utc_fixed + DIFFERENCE_TIMESTAMP_JST == timestamp_no_tz  # Wrong!
    assert timestamp_tzlocal + DIFFERENCE_TIMESTAMP_JST == timestamp_no_tz  # Wrong!
    assert timestamp_local_timezone + DIFFERENCE_TIMESTAMP_JST == timestamp_no_tz  # Wrong!

In case when we don't set tz_offset, there wasn't any problems.:

from datetime import datetime, timedelta, timezone
from freezegun import freeze_time
from dateutil.tz import tzlocal


@freeze_time("2022-08-09 11:26:00.000")
def test_freezegun3() -> None:
    timestamp_utc_fixed = int(datetime.now(tz=timezone(timedelta(hours=0))).timestamp() * 1000)
    timestamp_tzlocal = int(datetime.now(tz=tzlocal()).timestamp() * 1000)
    # - Answer: datetime - Python: Figure out local timezone - Stack Overflow
    #   https://stackoverflow.com/a/39079819/12721873
    timestamp_local_timezone = int(datetime.now(tz=datetime.now(timezone.utc).astimezone().tzinfo).timestamp() * 1000)
    timestamp_no_tz = int(datetime.now().timestamp() * 1000)
    assert timestamp_utc_fixed == timestamp_no_tz
    assert timestamp_tzlocal == timestamp_no_tz
    assert timestamp_local_timezone == timestamp_no_tz

these tests seems to work fine with any local timezone.

Tested version:

Python: 3.12.4
freezegun: 1.5.1

Related?:

tay added a commit to tay/electricitymaps-contrib that referenced this issue Oct 27, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant