Skip to content

Commit e645262

Browse files
iwalucasauvipy
andauthored
Consider server timezone on _get_timezone_offset instead of django's settings (#886)
* Scheduler shouldnt ignore specific times on crontab * Use aware_now to get server's timezone rather than using django's * Update schedulers.py * Update schedulers.py * Update schedulers.py * Update django_celery_beat/schedulers.py * adding tests --------- Co-authored-by: Asif Saif Uddin <[email protected]>
1 parent 0c5b652 commit e645262

File tree

2 files changed

+55
-2
lines changed

2 files changed

+55
-2
lines changed

django_celery_beat/schedulers.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@
1919
from django.db.models import Case, F, IntegerField, Q, When
2020
from django.db.models.functions import Cast
2121
from django.db.utils import DatabaseError, InterfaceError
22-
from django.utils import timezone
2322
from kombu.utils.encoding import safe_repr, safe_str
2423
from kombu.utils.json import dumps, loads
2524

@@ -364,7 +363,9 @@ def _get_timezone_offset(self, timezone_name):
364363
int: The hour offset
365364
"""
366365
# Get server timezone
367-
server_tz = timezone.get_current_timezone()
366+
server_time = aware_now()
367+
# Use server_time.tzinfo directly if it is already a ZoneInfo instance
368+
server_tz = server_time.tzinfo if isinstance(server_time.tzinfo, ZoneInfo) else ZoneInfo(str(server_time.tzinfo))
368369

369370
if isinstance(timezone_name, ZoneInfo):
370371
timezone_name = timezone_name.key

t/unit/test_schedulers.py

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1453,3 +1453,55 @@ def mock_apply_async(*args, **kwargs):
14531453
ma.run_tasks(self.request, PeriodicTask.objects.filter(id=self.m1.id))
14541454
assert 'periodic_task_name' in self.captured_headers
14551455
assert self.captured_headers['periodic_task_name'] == self.m1.name
1456+
1457+
1458+
1459+
@pytest.mark.django_db
1460+
class test_timezone_offset_handling:
1461+
def setup_method(self):
1462+
self.app = patch("django_celery_beat.schedulers.current_app").start()
1463+
1464+
def teardown_method(self):
1465+
patch.stopall()
1466+
1467+
@patch("django_celery_beat.schedulers.aware_now")
1468+
def test_server_timezone_handling_with_zoneinfo(self, mock_aware_now):
1469+
"""Test handling when server timezone is already a ZoneInfo instance."""
1470+
1471+
# Create a mock scheduler with only the methods we need to test
1472+
class MockScheduler:
1473+
_get_timezone_offset = schedulers.DatabaseScheduler._get_timezone_offset
1474+
1475+
s = MockScheduler()
1476+
1477+
tokyo_tz = ZoneInfo("Asia/Tokyo")
1478+
mock_now = datetime(2023, 1, 1, 12, 0, 0, tzinfo=tokyo_tz)
1479+
mock_aware_now.return_value = mock_now
1480+
1481+
# Test with a different timezone
1482+
new_york_tz = "America/New_York"
1483+
offset = s._get_timezone_offset(new_york_tz) # Pass self explicitly
1484+
1485+
# Tokyo is UTC+9, New York is UTC-5, so difference should be 14 hours
1486+
assert offset == 14
1487+
assert mock_aware_now.called
1488+
1489+
@patch("django_celery_beat.schedulers.aware_now")
1490+
def test_timezone_offset_with_zoneinfo_object_param(self, mock_aware_now):
1491+
"""Test handling when timezone_name parameter is a ZoneInfo object."""
1492+
1493+
class MockScheduler:
1494+
_get_timezone_offset = schedulers.DatabaseScheduler._get_timezone_offset
1495+
1496+
s = MockScheduler()
1497+
1498+
tokyo_tz = ZoneInfo("Asia/Tokyo")
1499+
mock_now = datetime(2023, 1, 1, 12, 0, 0, tzinfo=tokyo_tz)
1500+
mock_aware_now.return_value = mock_now
1501+
1502+
# Test with a ZoneInfo object as parameter
1503+
new_york_tz = ZoneInfo("America/New_York")
1504+
offset = s._get_timezone_offset(new_york_tz) # Pass self explicitly
1505+
1506+
# Tokyo is UTC+9, New York is UTC-5, so difference should be 14 hours
1507+
assert offset == 14

0 commit comments

Comments
 (0)