arrow icon indicating copy to clipboard operation
arrow copied to clipboard

Strange Timezone offset

Open hasandiwan opened this issue 11 months ago • 7 comments

Issue Description

In [28]:divmod((Arrow.utcnow() - Arrow.now()).days, 1)[0] < Out[28]:-1

$ echo TZ < America/Los_Angeles

  • 🐍 Python version:

3.11

  • 🏹 Arrow version: In [3]: arrow.version Out[3]: '1.3.0'

hasandiwan avatar Jan 19 '25 21:01 hasandiwan

@hasandiwan The difference you're experiencing is due to a very minor delta between when the utcnow and now objects are created

For example, if you print both timestamps, you'll notice a small difference (around 59 milliseconds) between them.

print(f"{arrow.utcnow()} and {arrow.now('America/Los_Angeles')}") 2025-01-20T17:48:51.138943+00:00 and 2025-01-20T09:48:51.198620-08:00

satveerbrar avatar Jan 20 '25 17:01 satveerbrar

The difference in days between utcnow and now, given that I'm in PST8PDT, should not be -1.

hasandiwan avatar Jan 20 '25 18:01 hasandiwan

The reason you're getting such a strange result is probably due to the quirk of how timedelta stores negative durations:

>>> timedelta(seconds=-1)
datetime.timedelta(days=-1, seconds=86399)

the .days property only gets the days component, to get the actual "total" value you need to call total_seconds()

ariebovenberg avatar Jan 20 '25 18:01 ariebovenberg

In [3]: (Arrow.utcnow() - Arrow.now()).total_seconds() Out[3]: -5.2e-05

Seems unlikely that an 8 hour time difference would be less than a second.

hasandiwan avatar Jan 20 '25 19:01 hasandiwan

It's always frustrating when code does something unexpected. Try running each part of the code one-by-one to see where the surprising result comes from 🙂. ~~It looks like your system timezone may be set to UTC.~~

edit: the result of both the statements is aware, and thus the result is measured in absolute terms. So a few milliseconds seems likely

ariebovenberg avatar Jan 20 '25 19:01 ariebovenberg

% env TZ=PST8PDT ~/.virtualenvs/data/bin/ipython Python 3.12.8 (main, Dec 3 2024, 18:42:41) [Clang 16.0.0 (clang-1600.0.26.4)] Type 'copyright', 'credits' or 'license' for more information IPython 8.20.0 -- An enhanced Interactive Python. Type '?' for help.

In [1]: from arrow import Arrow

In [2]: (Arrow.utcnow()-Arrow.now()).total_seconds() Out[2]: -4.7e-05

hasandiwan avatar Jan 20 '25 19:01 hasandiwan

Note: if you want the UTC offset of the local timezone at the current moment, just do:

>>> arrow.now().utcoffset().total_seconds()

Now on to why your earlier result isn't expected.

>>> a = arrow.utcnow()
<Arrow [2025-01-20T20:45:18.461830+00:00]>
>>> b = arrow.now()
<Arrow [2025-01-20T21:45:20.316133+01:00]>

The subtraction operator determines the difference in absolute terms—i.e. as if both datetimes were normalized to UTC.

If you want to compare datetimes "naively", use the naive attribute:

(a.naive - b.naive).total_seconds()

ariebovenberg avatar Jan 20 '25 20:01 ariebovenberg