From c6cf8b6f24f79c9b5c8a662465ea7b5b66defef1 Mon Sep 17 00:00:00 2001 From: Richard Schreiber Date: Thu, 28 Sep 2023 16:05:03 +0200 Subject: [PATCH] Calender: Always add end date (Z#23131739) (#3622) --- src/pretix/presale/ical.py | 19 ++++++++++++------- src/tests/presale/test_event.py | 7 +++++-- 2 files changed, 17 insertions(+), 9 deletions(-) diff --git a/src/pretix/presale/ical.py b/src/pretix/presale/ical.py index 056fcaf1fb..f9952cbde7 100644 --- a/src/pretix/presale/ical.py +++ b/src/pretix/presale/ical.py @@ -68,13 +68,18 @@ def get_public_ical(events): else: vevent.add('dtstart').value = ev.date_from.astimezone(tz).date() - if event.settings.show_date_to and ev.date_to: - if event.settings.show_times: - vevent.add('dtend').value = ev.date_to.astimezone(tz) - else: - # with full-day events date_to in pretix is included (e.g. last day) - # whereas dtend in vcalendar is non-inclusive => add one day for export - vevent.add('dtend').value = ev.date_to.astimezone(tz).date() + datetime.timedelta(days=1) + # always add dtend as calendar apps otherwise have display issues + use_date_to = event.settings.show_date_to and ev.date_to + dtend = (ev.date_to if use_date_to else ev.date_from).astimezone(tz) + + if not event.settings.show_times: + # with full-day events date_to in pretix is included (e.g. last day) + # whereas dtend in vcalendar is non-inclusive => add one day for export + dtend = dtend.date() + datetime.timedelta(days=1) + elif not use_date_to: + # date_from used as end-date => add 1h as a default duration + dtend = dtend + datetime.timedelta(hours=1) + vevent.add('dtend').value = dtend descr = [] descr.append(_('Tickets: {url}').format(url=url)) diff --git a/src/tests/presale/test_event.py b/src/tests/presale/test_event.py index 974af9b21d..54779ff994 100644 --- a/src/tests/presale/test_event.py +++ b/src/tests/presale/test_event.py @@ -1418,7 +1418,10 @@ class EventIcalDownloadTest(EventTestMixin, SoupTest): (self.event.settings.timezone, self.event.date_from.astimezone(ZoneInfo(self.event.settings.timezone)).strftime(fmt)), ical, 'incorrect start time') - self.assertNotIn('DTEND', ical, 'unexpected end time attribute') + self.assertIn('DTEND;TZID=%s:%s' % + (self.event.settings.timezone, + (self.event.date_from.astimezone(ZoneInfo(self.event.settings.timezone)) + datetime.timedelta(hours=1)).strftime(fmt)), + ical, 'incorrect end time') def test_no_date_to_and_time(self): self.event.settings.show_date_to = False @@ -1426,7 +1429,7 @@ class EventIcalDownloadTest(EventTestMixin, SoupTest): self.event.save() ical = self.client.get('/%s/%s/ical/' % (self.orga.slug, self.event.slug)).content.decode() self.assertIn('DTSTART;VALUE=DATE:%s' % self.event.date_from.strftime('%Y%m%d'), ical, 'incorrect start date') - self.assertNotIn('DTEND', ical, 'unexpected end time attribute') + self.assertIn('DTEND;VALUE=DATE:%s' % (self.event.date_from + datetime.timedelta(days=1)).strftime('%Y%m%d'), ical, 'incorrect start date') def test_local_date_diff_from_utc(self): self.event.date_from = datetime.datetime(2013, 12, 26, 21, 57, 58, tzinfo=datetime.timezone.utc)