arrow-py / arrow

🏹 Better dates & times for Python
https://arrow.readthedocs.io
Apache License 2.0
8.63k stars 669 forks source link

incorrect time difference for times before and after DST switch #1136

Open clarsen opened 1 year ago

clarsen commented 1 year ago

Issue Description

The time difference between two localized times isn't the actual difference in seconds, but rather the naive difference.

Example:

import arrow

def test_dst():
    # 1667725199 11/6/2022 1:59:59AM GMT-7 DST
    # 1667725200 11/6/2022 1:00:00AM GMT-8
    before_dst = arrow.get(1667725199, tzinfo='America/Los_Angeles')
    print(before_dst)
    after_dst = arrow.get(1667725200, tzinfo='America/Los_Angeles')
    print(after_dst)
    secs = (after_dst - before_dst).total_seconds()
    print(secs)

test_dst()

results in:

2022-11-06T01:59:59-07:00
2022-11-06T01:00:00-08:00
-3599.0

would expect 1.0 instead.

Workaround use timestamp() instead:

def test_dst_using_epoch():
    # 1667725199 11/6/2022 1:59:59AM GMT-7 DST
    # 1667725200 11/6/2022 1:00:00AM GMT-8
    before_dst = arrow.get(1667725199, tzinfo='America/Los_Angeles')
    print(before_dst)
    after_dst = arrow.get(1667725200, tzinfo='America/Los_Angeles')
    print(after_dst)

    secs = after_dst.timestamp() - before_dst.timestamp()
    print(secs)

test_dst_using_epoch()

results in:

2022-11-06T01:59:59-07:00
2022-11-06T01:00:00-08:00
1.0

System Info

Eric-Jiang1 commented 1 year ago

Hi! I'm interested in working on this bug.

bschick commented 1 year ago

If this gets addressed, it would also make sense to change the shift function to account for DST changes. Its hard to say which approach is 'correct', but I think accounting for DST is more natural and would result in fewer errors in code that uses arrow. The current shift behavior ignores DST change on the resulting time:

>>> t1=arrow.get(datetime(2023, 3, 11, 21), 'US/Pacific')
>>> t1
<Arrow [2023-03-11T21:00:00-08:00]>
>>> t2=t1.shift(hours=12)
>>> t2
<Arrow [2023-03-12T09:00:00-07:00]>

Since t1 is not DST and t2 is within DST (clock has move forward), adding 12 hours to t1 would result in a wall-clock time that is 13 hours ahead. Meaning t2 would be <Arrow [2023-03-12T10:00:00-07:00]>

Either approach might confuse someone, but given that a reason to use arrow is timezone awareness (and a big part of most timezones is DST) I'd prefer both DST aware math operations and more DST aware shift.