Skip to content

Commit

Permalink
Fix: timezone info occasionally removed from cron job execution time (#…
Browse files Browse the repository at this point in the history
…383)

* Expose the bug in tests

* Do not remove timezone when incrementing month in _get_next_dt
  • Loading branch information
iamlikeme authored Apr 1, 2024
1 parent 5769e10 commit 94cd878
Show file tree
Hide file tree
Showing 2 changed files with 71 additions and 21 deletions.
4 changes: 2 additions & 2 deletions arq/cron.py
Original file line number Diff line number Diff line change
Expand Up @@ -67,9 +67,9 @@ def _get_next_dt(dt_: datetime, options: Options) -> Optional[datetime]: # noqa
micro = max(dt_.microsecond - options.microsecond, 0)
if field == 'month':
if dt_.month == 12:
return datetime(dt_.year + 1, 1, 1)
return datetime(dt_.year + 1, 1, 1, tzinfo=dt_.tzinfo)
else:
return datetime(dt_.year, dt_.month + 1, 1)
return datetime(dt_.year, dt_.month + 1, 1, tzinfo=dt_.tzinfo)
elif field in ('day', 'weekday'):
return (
dt_
Expand Down
88 changes: 69 additions & 19 deletions tests/test_cron.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import asyncio
import logging
import re
from datetime import datetime, timedelta
from datetime import datetime, timedelta, timezone
from random import random

import pytest
Expand All @@ -12,37 +12,87 @@
from arq.constants import in_progress_key_prefix
from arq.cron import cron, next_cron

tz = timezone(offset=timedelta(hours=3))


@pytest.mark.parametrize(
'previous,expected,kwargs',
[
(datetime(2016, 6, 1, 12, 10, 10), datetime(2016, 6, 1, 12, 10, 20, microsecond=123_456), dict(second=20)),
(datetime(2016, 6, 1, 12, 10, 10), datetime(2016, 6, 1, 12, 11, 0, microsecond=123_456), dict(minute=11)),
(datetime(2016, 6, 1, 12, 10, 10), datetime(2016, 6, 1, 12, 10, 20), dict(second=20, microsecond=0)),
(datetime(2016, 6, 1, 12, 10, 10), datetime(2016, 6, 1, 12, 11, 0), dict(minute=11, microsecond=0)),
(
datetime(2016, 6, 1, 12, 10, 11),
datetime(2017, 6, 1, 12, 10, 10, microsecond=123_456),
datetime(2016, 6, 1, 12, 10, 10, tzinfo=tz),
datetime(2016, 6, 1, 12, 10, 20, microsecond=123_456, tzinfo=tz),
dict(second=20),
),
(
datetime(2016, 6, 1, 12, 10, 10, tzinfo=tz),
datetime(2016, 6, 1, 12, 11, 0, microsecond=123_456, tzinfo=tz),
dict(minute=11),
),
(
datetime(2016, 6, 1, 12, 10, 10, tzinfo=tz),
datetime(2016, 6, 1, 12, 10, 20, tzinfo=tz),
dict(second=20, microsecond=0),
),
(
datetime(2016, 6, 1, 12, 10, 10, tzinfo=tz),
datetime(2016, 6, 1, 12, 11, 0, tzinfo=tz),
dict(minute=11, microsecond=0),
),
(
datetime(2016, 6, 1, 12, 10, 11, tzinfo=tz),
datetime(2017, 6, 1, 12, 10, 10, microsecond=123_456, tzinfo=tz),
dict(month=6, day=1, hour=12, minute=10, second=10),
),
(
datetime(2016, 6, 1, 12, 10, 10, microsecond=1),
datetime(2016, 7, 1, 12, 10, 10),
datetime(2016, 6, 1, 12, 10, 10, microsecond=1, tzinfo=tz),
datetime(2016, 7, 1, 12, 10, 10, tzinfo=tz),
dict(day=1, hour=12, minute=10, second=10, microsecond=0),
),
(datetime(2032, 1, 31, 0, 0, 0), datetime(2032, 2, 28, 0, 0, 0, microsecond=123_456), dict(day=28)),
(datetime(2032, 1, 1, 0, 5), datetime(2032, 1, 1, 4, 0, microsecond=123_456), dict(hour=4)),
(datetime(2032, 1, 1, 0, 0), datetime(2032, 1, 1, 4, 2, microsecond=123_456), dict(hour=4, minute={2, 4, 6})),
(datetime(2032, 1, 1, 0, 5), datetime(2032, 1, 1, 4, 2, microsecond=123_456), dict(hour=4, minute={2, 4, 6})),
(datetime(2032, 2, 5, 0, 0, 0), datetime(2032, 3, 31, 0, 0, 0, microsecond=123_456), dict(day=31)),
(
datetime(2001, 1, 1, 0, 0, 0), # Monday
datetime(2001, 1, 7, 0, 0, 0, microsecond=123_456),
datetime(2032, 1, 31, 0, 0, 0, tzinfo=tz),
datetime(2032, 2, 28, 0, 0, 0, microsecond=123_456, tzinfo=tz),
dict(day=28),
),
(
datetime(2032, 1, 1, 0, 5, tzinfo=tz),
datetime(2032, 1, 1, 4, 0, microsecond=123_456, tzinfo=tz),
dict(hour=4),
),
(
datetime(2032, 1, 1, 0, 0, tzinfo=tz),
datetime(2032, 1, 1, 4, 2, microsecond=123_456, tzinfo=tz),
dict(hour=4, minute={2, 4, 6}),
),
(
datetime(2032, 1, 1, 0, 5, tzinfo=tz),
datetime(2032, 1, 1, 4, 2, microsecond=123_456, tzinfo=tz),
dict(hour=4, minute={2, 4, 6}),
),
(
datetime(2032, 2, 5, 0, 0, 0, tzinfo=tz),
datetime(2032, 3, 31, 0, 0, 0, microsecond=123_456, tzinfo=tz),
dict(day=31),
),
(
datetime(2001, 1, 1, 0, 0, 0, tzinfo=tz), # Monday
datetime(2001, 1, 7, 0, 0, 0, microsecond=123_456, tzinfo=tz),
dict(weekday='Sun'), # Sunday
),
(datetime(2001, 1, 1, 0, 0, 0), datetime(2001, 1, 7, 0, 0, 0, microsecond=123_456), dict(weekday=6)), # Sunday
(datetime(2001, 1, 1, 0, 0, 0), datetime(2001, 11, 7, 0, 0, 0, microsecond=123_456), dict(month=11, weekday=2)),
(datetime(2001, 1, 1, 0, 0, 0), datetime(2001, 1, 3, 0, 0, 0, microsecond=123_456), dict(weekday='wed')),
(
datetime(2001, 1, 1, 0, 0, 0, tzinfo=tz),
datetime(2001, 1, 7, 0, 0, 0, microsecond=123_456, tzinfo=tz),
dict(weekday=6),
), # Sunday
(
datetime(2001, 1, 1, 0, 0, 0, tzinfo=tz),
datetime(2001, 11, 7, 0, 0, 0, microsecond=123_456, tzinfo=tz),
dict(month=11, weekday=2),
),
(
datetime(2001, 1, 1, 0, 0, 0, tzinfo=tz),
datetime(2001, 1, 3, 0, 0, 0, microsecond=123_456, tzinfo=tz),
dict(weekday='wed'),
),
],
)
def test_next_cron(previous, expected, kwargs):
Expand Down

0 comments on commit 94cd878

Please sign in to comment.