arrow-py / arrow

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

ceil("day") incorrect on the day before DST switch #1124

Open joekohlsdorf opened 2 years ago

joekohlsdorf commented 2 years ago

When reviewing this, make sure that you have an updated timezone database. The date of the DST switch for this location was moved ~3 weeks ago so if you try with an outdated database you will not see the DST switch occur on this date.

Issue Description

For this timezone there is a DST switch from UTC-4 to UTC-3 occurring on 2022-09-11 00:00 to 2022-09-11 01:00 local time. This makes ceil("day") misbehave on the day prior to the DST switch.

arrow.get(1662790000).to("America/Santiago").ceil("day")
<Arrow [2022-09-11T01:59:59.999999-03:00]>

Expected result:

<Arrow [2022-09-10T23:59:59.999999-04:00]>

System Info

vivekthedev commented 2 years ago

I would like to work on it, can you guide me how should I start?

nik-k11 commented 1 year ago

Hello there.

ceil uses span, which uses shift. shift relies on dateutil_tz.resolve_imaginary, which always moves imaginary dates forward (per its docs and implementation).

This results in behavior like this:

arw = arrow.get(1662868800).to("America/Santiago")
arw
<Arrow [2022-09-11T01:00:00-03:00]>

arw.shift(microseconds=-1)
<Arrow [2022-09-11T01:59:59.999999-03:00]>

It seems like the correct result should be <Arrow [2022-09-10T23:59:59.999999-04:00]>

It would be nice for resolve_imaginary to accept an optional argument (move_backward?) to move it back instead. It should be possible to detect the shift direction by comparing self and current inside the failed datetime_exists check.

And it also seems easier to rewrite and extend resolve_imaginary inside arrow, rather than make a PR for dateutil.