Strange inconsistency in datetime timestamp calculation

Hi!

The assert in the following code fails for the second call of _something(...) and I don’t understand why. It looks like it should work, but the second time the timestamp is offset by twice the intended amount. I’ve tried running it under CPython 3.9 and 3.11, PyPy3, all on Arch Linux 6.1.59-1-lts x86_64.

from datetime import datetime, timedelta


def _something(dt_s):
    a_dt = datetime.fromisoformat(dt_s)
    b_dt = a_dt + timedelta(seconds=3600)
    a_ts = a_dt.timestamp()
    b_ts = b_dt.timestamp()
    ts_diff = b_ts - a_ts
    assert ts_diff == 3600, "%s %s %s" % (ts_diff, a_ts, b_ts)


_something("2023-10-28 08:22:04.875859")
_something("2023-10-29 02:12:13.364516")

Example output for me:

$ python3.11 /tmp/scratches/scratch_57.py
Traceback (most recent call last):
  File "/tmp/scratches/scratch_57.py", line 14, in <module>
    _something("2023-10-29 02:12:13.364516")
  File "/tmp/scratches/scratch_57.py", line 10, in _something
    assert ts_diff == 3600, "%s %s %s" % (ts_diff, a_ts, b_ts)
           ^^^^^^^^^^^^^^^
AssertionError: 7200.0 1698538333.364516 1698545533.364516

I guess, either I’m missing something simple or this is some crazy quirk of the underling system time library.
Could someone please explain to me, what’s going wrong?

Thanks in advance,

The code you posted works fine for me…are you sure it’s the same version you ran to get this error?

Daylight saving? In your time zone do the clocks change on sunday?
I am guessing you live in the UK.

1 Like

I realized this was the issue just now :joy: that’s a pretty wild “bug” to run into. And it works for me because I’m in the US :upside_down_face:

Yes, here you can see how I run it step-by-step:

[nandor@lgg tmp]$ python3.11 --version
Python 3.11.5
[nandor@lgg tmp]$ cat wat.py
from datetime import datetime, timedelta


def _something(dt_s):
    a_dt = datetime.fromisoformat(dt_s)
    b_dt = a_dt + timedelta(seconds=3600)
    a_ts = a_dt.timestamp()
    b_ts = b_dt.timestamp()
    ts_diff = b_ts - a_ts
    assert ts_diff == 3600, "%s %s %s" % (ts_diff, a_ts, b_ts)


_something("2023-10-28 08:22:04.875859")
_something("2023-10-29 02:12:13.364516")
[nandor@lgg tmp]$ python3.11 wat.py
Traceback (most recent call last):
  File "/tmp/wat.py", line 14, in <module>
    _something("2023-10-29 02:12:13.364516")
  File "/tmp/wat.py", line 10, in _something
    assert ts_diff == 3600, "%s %s %s" % (ts_diff, a_ts, b_ts)
           ^^^^^^^^^^^^^^^
AssertionError: 7200.0 1698538333.364516 1698545533.364516
[nandor@lgg tmp]$ timedatectl 
               Local time: cs 2023-10-26 18:00:19 CEST
           Universal time: cs 2023-10-26 16:00:19 UTC
                 RTC time: cs 2023-10-26 16:00:19
                Time zone: Europe/Budapest (CEST, +0200)
System clock synchronized: yes
              NTP service: active
          RTC in local TZ: no
[nandor@lgg tmp]$

I’ve added the timedatectl call so my tz can be seen as well. I’ve had several headaches with datetime in regards to timezones, but that should not be relevant in this case as far as I can tell…

Alright it was because of the timezone behaviour… again… if I set the tzinfo to utc, it will work as expected:

from datetime import datetime, timedelta, timezone


def _something(dt_s):
    a_dt = datetime.fromisoformat(dt_s).replace(tzinfo=timezone.utc)
    b_dt = a_dt + timedelta(seconds=3600)
    a_ts = a_dt.timestamp()
    b_ts = b_dt.timestamp()
    ts_diff = b_ts - a_ts
    assert ts_diff == 3600, "%s %s %s" % (ts_diff, a_ts, b_ts)


_something("2023-10-28 08:22:04.875859")
_something("2023-10-29 02:12:13.364516")

I can’t believe how many times I have to fall into this trap and still not learn to always make sure the tzinfo is utc.

Thanks for the help and sorry for the noise.

2 Likes