taichino / croniter

croniter is a python module to provide iteration for datetime object.
http://github.com/taichino/croniter
387 stars 105 forks source link

get_next starts returning the same timestamps after DST switch in Europe #91

Closed unterwegi closed 4 years ago

unterwegi commented 6 years ago

This example shows the issue:

from croniter.croniter import croniter
from datetime import datetime
import pytz

tz = pytz.timezone('Europe/Vienna')

def test_croniter(start_time, repeat=40):
    start_time = tz.localize(start_time)
    print("-" * 100)
    print(f"start_time = {str(start_time)}")
    print("-" * 100)

    test_cron = croniter('30 * * * *', start_time=start_time)
    for i in range(repeat):
        print(test_cron.get_next(datetime))

    print("-" * 100)

# First test: cron timestamps start repeating after the DST change from 03:00 AM back to 02:00 AM
test_croniter(datetime(2017, 10, 28, 10, 9))

# Second test: It get's even weirder when the start_time is at the same day as the DST change,
# because the timestamps start repeating at around 21:00 (i.e. 09:00 PM)
test_croniter(datetime(2017, 10, 29, 0, 5))

# Third test: Here's another test that shows repeating timestamps after a DST change
# that changes the clock from 02:00 AM to 03:00 AM
test_croniter(datetime(2017, 3, 25, 20, 5))

It just creates some croniter instances with different start_time values that are all around this year's DST changes in Europe and then repeatedly calls get_next on them and prints the returned datetime objects.

Just for background information:

Europe always switches from standard time to DST at 02:00 AM (switching to 03:00 AM) on the last Sunday of March (was the 26th this year). The switch from DST back to standard time then happens at 03:00 AM (back to 02:00 AM) on the last Sunday of October (was the 29th this year).

The first test_croniter call produces output like this:

----------------------------------------------------------------------------------------------------
start_time = 2017-10-28 10:09:00+02:00
----------------------------------------------------------------------------------------------------
2017-10-28 10:30:00+02:00
2017-10-28 11:30:00+02:00
...
2017-10-28 23:30:00+02:00
2017-10-29 00:30:00+02:00
2017-10-29 01:30:00+02:00
2017-10-29 02:30:00+02:00
2017-10-29 01:30:00+01:00
2017-10-29 01:30:00+01:00
2017-10-29 01:30:00+01:00
2017-10-29 01:30:00+01:00
... (stays the same after that)

Here's the second one:

----------------------------------------------------------------------------------------------------
start_time = 2017-10-29 00:05:00+02:00
----------------------------------------------------------------------------------------------------
2017-10-29 00:30:00+02:00
2017-10-29 01:30:00+02:00
2017-10-29 02:30:00+02:00
2017-10-29 02:30:00+01:00
2017-10-29 03:30:00+01:00
2017-10-29 04:30:00+01:00
...
2017-10-29 20:30:00+01:00
2017-10-29 21:30:00+01:00
2017-10-29 21:30:00+01:00
2017-10-29 21:30:00+01:00
2017-10-29 21:30:00+01:00
... (stays the same after that)

And here the third one:

----------------------------------------------------------------------------------------------------
start_time = 2017-03-25 20:05:00+01:00
----------------------------------------------------------------------------------------------------
2017-03-25 20:30:00+01:00
2017-03-25 21:30:00+01:00
2017-03-25 22:30:00+01:00
2017-03-25 23:30:00+01:00
2017-03-26 00:30:00+01:00
2017-03-26 01:30:00+01:00
2017-03-26 02:30:00+02:00
2017-03-26 02:30:00+02:00
2017-03-26 02:30:00+02:00
2017-03-26 02:30:00+02:00
... (stays the same after that)

This is also not limited to the "Europe/Vienna" time zone. The issue also comes up when using "Europe/Kiev", "Europe/Lisbon", "Europe/London", ...

Tested against croniter 0.3.19

kbrose commented 6 years ago

Same with American timezones.

chassing commented 6 years ago

I had similar issue on the last weekend (PST)

kbrose commented 6 years ago

@unterwegi @chassing

If you two want to try out the changeset from https://github.com/taichino/croniter/pull/92 I'd appreciate the extra verification.

kbrose commented 6 years ago

Is this resolved by the new release (https://pypi.python.org/pypi/croniter/0.3.20)? (https://github.com/taichino/croniter/pull/92)

chassing commented 6 years ago

If I'm using @unterwegi test script than I can still see a strange behavior (I'm using "0,30 " as cron line):

test one - in fall started one day before. we should see 2am twice (see test two):

2017-10-29 01:00:00+02:00
2017-10-29 01:30:00+02:00
2017-10-29 02:00:00+02:00
2017-10-29 02:30:00+02:00
2017-10-29 03:00:00+01:00
2017-10-29 03:30:00+01:00
2017-10-29 04:00:00+01:00
2017-10-29 04:30:00+01:00

test two - in fall started on the same day. this one looks correct but different to test one:

2017-10-29 01:00:00+02:00
2017-10-29 01:30:00+02:00
2017-10-29 02:00:00+02:00
2017-10-29 02:30:00+02:00
2017-10-29 02:00:00+01:00
2017-10-29 02:30:00+01:00
2017-10-29 03:00:00+01:00
2017-10-29 03:30:00+01:00
2017-10-29 04:00:00+01:00
2017-10-29 04:30:00+01:00

test three - in spring but day before. looks strange:

2017-03-26 01:00:00+01:00
2017-03-26 01:30:00+01:00
2017-03-26 02:00:00+02:00
2017-03-26 01:30:00+01:00
2017-03-26 03:00:00+02:00
2017-03-26 03:30:00+02:00
2017-03-26 04:00:00+02:00
2017-03-26 04:30:00+02:00
kbrose commented 6 years ago

Hmm, so tests 1 & 2 look correct to me. Am I interpreting that correctly? Test 3 I agree looks strange.

chassing commented 6 years ago

test 1 & 2 should have the same output. 2am must be there twice, once with +02 and once with +01. so the output of test 2 is the correct one

unterwegi commented 6 years ago

Got the same results as @chassing, also with different time zones.

The output from his second test also looks more correct to me.

kiorky commented 6 years ago

96 is dupped isnt it ?

kiorky commented 4 years ago

dup #90