From 939b49ecc2491ef8db0ec031b146d00d838a4d5b Mon Sep 17 00:00:00 2001 From: Helge Jung <hej@c3pb.de> Date: Mon, 23 Dec 2024 15:15:41 +0100 Subject: [PATCH] Conference.days() & ConferenceDay: ensure correct behaviour --- src/core/models/conference.py | 9 ++++--- src/core/tests/conference.py | 46 ++++++++++++++++++++++++++++++++--- 2 files changed, 48 insertions(+), 7 deletions(-) diff --git a/src/core/models/conference.py b/src/core/models/conference.py index 737006da6..b3e84fd1b 100644 --- a/src/core/models/conference.py +++ b/src/core/models/conference.py @@ -433,7 +433,7 @@ class Conference(models.Model): return days end = self.end if self.end is not None else timezone.now().replace(hour=23, minute=59, second=59) for i in range(self.days_count): - date = self.start.date() + timedelta(days=i) + date = self._day0 + timedelta(days=i + 1) days.append(ConferenceDay(i, date, self.timezone)) days[0].start = self.start @@ -677,10 +677,13 @@ class ConferenceDay: start: datetime end: datetime - def __init__(self, i: int, date: date, time_zone: tz): + def __init__(self, i: int, date: date | datetime, time_zone: tz): + if isinstance(date, datetime): + date = date.date() + self.index = i + 1 self.start = datetime.combine(date, time(6, 0)).astimezone(time_zone) - self.end = datetime.combine(date + timedelta(days=1), time(6, 0)).astimezone(time_zone) + self.end = datetime.combine(self.start + timedelta(days=1), time(6, 0), tzinfo=None).astimezone(time_zone) def __eq__(self, value: object) -> bool: if not isinstance(value, ConferenceDay): diff --git a/src/core/tests/conference.py b/src/core/tests/conference.py index 3ed7df0ec..0e44aec38 100644 --- a/src/core/tests/conference.py +++ b/src/core/tests/conference.py @@ -1,12 +1,23 @@ -from datetime import UTC, datetime, timedelta +from datetime import UTC, date, datetime, timedelta from unittest.mock import patch +import pytz + from django.test import TestCase from django.utils import timezone from core.models.conference import Conference, ConferenceDay +class ConferenceDayTests(TestCase): + def test_construction(self): + tz = pytz.timezone('Europe/Berlin') + day = ConferenceDay(0, date(2042, 12, 27), tz) + self.assertEqual(1, day.index) + self.assertEqual(datetime(2042, 12, 27, 6, 0).astimezone(tz), day.start) + self.assertEqual(datetime(2042, 12, 28, 6, 0).astimezone(tz), day.end) + + class ConferenceTests(TestCase): def setUp(self): self.conference = Conference(slug='foo', name='Foo Conference', is_public=True) @@ -25,6 +36,33 @@ class ConferenceTests(TestCase): self.assertEqual(self.conference.get_conference_day(datetime(2042, 12, 31, 5, 30, tzinfo=UTC)), 4) self.assertEqual(self.conference.get_conference_day(datetime(2042, 12, 31, 5, 30, tzinfo=UTC)), 4) + def test_days(self): + self.conference.start = datetime(2042, 12, 27, 9, 00, tzinfo=UTC) + self.conference.end = datetime(2042, 12, 30, 15, 00, tzinfo=UTC) + self.conference.timezone = 'Europe/Berlin' + tz = pytz.timezone('Europe/Berlin') + + expected_days = [ + ConferenceDay(0, date(2042, 12, 27), tz), + ConferenceDay(1, date(2042, 12, 28), tz), + ConferenceDay(2, date(2042, 12, 29), tz), + ConferenceDay(3, date(2042, 12, 30), tz), + ] + expected_days[0].start = self.conference.start.astimezone(tz) + expected_days[-1].end = self.conference.end.astimezone(tz) + + self.assertEqual(len(expected_days), self.conference.days_count) + actual_days = self.conference.days + self.assertEqual(len(expected_days), len(actual_days)) + + with self.subTest('timezones'): + self.assertTrue(all(d.start.tzinfo is not None for d in actual_days)) + self.assertTrue(all(d.end.tzinfo is not None for d in actual_days)) + + for x in range(4): + with self.subTest(f'day {x +1}'): + self.assertEqual(expected_days[x], actual_days[x]) + def test_days_in(self): with patch.object(timezone, 'now', return_value=datetime(2042, 12, 27, 12, 34, 0, 0, tzinfo=UTC)): self.conference.start = timezone.now() - timedelta(days=1) @@ -79,9 +117,9 @@ class ConferenceTests(TestCase): self.assertFalse(self.conference.has_ended) self.assertEqual(self.conference.days_count, 3) days = [ - ConferenceDay(0, self.conference.start.astimezone(self.conference.timezone), self.conference.timezone), - ConferenceDay(1, self.conference.start.astimezone(self.conference.timezone) + timedelta(days=1), self.conference.timezone), - ConferenceDay(2, self.conference.start.astimezone(self.conference.timezone) + timedelta(days=2), self.conference.timezone), + ConferenceDay(0, self.conference.start.date(), self.conference.timezone), + ConferenceDay(1, (self.conference.start + timedelta(days=1)).date(), self.conference.timezone), + ConferenceDay(2, (self.conference.start + timedelta(days=2)).date(), self.conference.timezone), ] # The first day starts whenever the conference starts days[0].start = self.conference.start -- GitLab