From d926030bf67719a5cb9fbca9110bd4418573d46a Mon Sep 17 00:00:00 2001 From: luelista Date: Fri, 2 May 2025 10:22:04 +0200 Subject: [PATCH] Event list: fix parsing of date query parameter (#5047) Use the same localization formats as used when generating the value --- src/pretix/control/views/typeahead.py | 20 ++++---------------- src/pretix/helpers/i18n.py | 14 ++++++++++++++ src/pretix/presale/views/organizer.py | 6 ++---- 3 files changed, 20 insertions(+), 20 deletions(-) diff --git a/src/pretix/control/views/typeahead.py b/src/pretix/control/views/typeahead.py index e499f75ac6..4220823d82 100644 --- a/src/pretix/control/views/typeahead.py +++ b/src/pretix/control/views/typeahead.py @@ -42,7 +42,7 @@ from django.db.models.functions import Coalesce, Greatest from django.http import JsonResponse from django.shortcuts import get_object_or_404 from django.urls import reverse -from django.utils.formats import date_format, get_format +from django.utils.formats import date_format from django.utils.timezone import make_aware from django.utils.translation import gettext as _, pgettext @@ -56,7 +56,7 @@ from pretix.control.permissions import ( event_permission_required, organizer_permission_required, ) from pretix.helpers.daterange import daterange -from pretix.helpers.i18n import i18ncomp +from pretix.helpers.i18n import i18ncomp, parse_date_localized def serialize_user(u): @@ -408,13 +408,7 @@ def subevent_select2(request, **kwargs): qf = Q(name__icontains=i18ncomp(query)) | Q(location__icontains=query) tz = request.event.timezone - dt = None - for f in get_format('DATE_INPUT_FORMATS'): - try: - dt = datetime.strptime(query, f) - break - except (ValueError, TypeError): - continue + dt = parse_date_localized(query) if dt: dt_start = make_aware(datetime.combine(dt.date(), time(hour=0, minute=0, second=0)), tz) @@ -458,13 +452,7 @@ def quotas_select2(request, **kwargs): qf = Q(name__icontains=query) | Q(subevent__name__icontains=i18ncomp(query)) tz = request.event.timezone - dt = None - for f in get_format('DATE_INPUT_FORMATS'): - try: - dt = datetime.strptime(query, f) - break - except (ValueError, TypeError): - continue + dt = parse_date_localized(query) if dt and request.event.has_subevents: dt_start = make_aware(datetime.combine(dt.date(), time(hour=0, minute=0, second=0)), tz) diff --git a/src/pretix/helpers/i18n.py b/src/pretix/helpers/i18n.py index 9f4c1071a5..42c91b50e3 100644 --- a/src/pretix/helpers/i18n.py +++ b/src/pretix/helpers/i18n.py @@ -23,7 +23,9 @@ import gettext as gettext_module import json import os import re +from datetime import datetime from functools import lru_cache +from typing import Optional from django.apps import apps from django.conf import settings @@ -222,3 +224,15 @@ def get_language_score(locale): else: score = len(list(catalog.items())) or 1 return score + + +def parse_date_localized(date_str) -> Optional[datetime]: + """Parses a date according to the localized date input formats. Returns None if invalid.""" + dt = None + for f in get_format('DATE_INPUT_FORMATS'): + try: + dt = datetime.strptime(date_str, f) + break + except (ValueError, TypeError): + continue + return dt diff --git a/src/pretix/presale/views/organizer.py b/src/pretix/presale/views/organizer.py index b0098ee6b5..d2005b766d 100644 --- a/src/pretix/presale/views/organizer.py +++ b/src/pretix/presale/views/organizer.py @@ -70,6 +70,7 @@ from pretix.helpers.formats.en.formats import ( SHORT_MONTH_DAY_FORMAT, WEEK_FORMAT, ) from pretix.helpers.http import redirect_to_url +from pretix.helpers.i18n import parse_date_localized from pretix.helpers.thumb import get_thumbnail from pretix.multidomain.urlreverse import build_absolute_uri, eventreverse from pretix.presale.forms.organizer import EventListFilterForm @@ -927,10 +928,7 @@ class DayCalendarView(OrganizerViewMixin, EventListMixin, TemplateView): def _set_date(self): if 'date' in self.request.GET: self.tz = self.request.organizer.timezone - try: - self.date = dateutil.parser.parse(self.request.GET.get('date')).date() - except ValueError: - self.date = now().astimezone(self.tz).date() + self.date = parse_date_localized(self.request.GET.get('date')).date() or now().astimezone(self.tz).date() else: self._set_date_to_next_event()