06/08 Fix mobile app submission with wrong datetime

This commit is contained in:
2026-06-08 16:22:19 -04:00
parent 790aac36df
commit a517f495fe
+18 -9
View File
@@ -62,24 +62,33 @@ _UUID_RE = re.compile(
def _parse_datetime(value): def _parse_datetime(value):
"""Parse an ISO 8601 datetime string; return None on failure. """Parse an ISO 8601 datetime string; return a naive Eastern datetime.
Handles the formats produced by both the web forms and iOS Handles the formats produced by both the web forms and iOS
ISO8601DateFormatter(), which appends a 'Z' UTC suffix: ISO8601DateFormatter():
2026-05-28T09:41:00 (web form) 2026-05-28T09:41:00 (web form, already Eastern-naive)
2026-05-28T09:41:00.000 (web form with ms) 2026-05-28T09:41:00.000 (web form with ms)
2026-05-28T09:41:00Z (iOS ISO8601DateFormatter) 2026-05-28T09:41:00Z (iOS ISO8601DateFormatter, UTC)
2026-05-28T09:41:00.000000Z (iOS with fractional seconds) 2026-05-28T09:41:00.000000Z (iOS with fractional seconds, UTC)
Values ending with 'Z' are treated as UTC and converted to Eastern.
Values without a timezone suffix are assumed to already be Eastern-local.
""" """
if not value: if not value:
return None return None
from datetime import datetime from datetime import datetime, timezone as _tz
# Strip trailing 'Z' (UTC marker) so strptime can parse it as naive datetime. from app.utils.time_utils import EASTERN
# The system treats all datetimes as Eastern-local; UTC offset is ignored.
is_utc = isinstance(value, str) and value.endswith('Z')
normalised = value.rstrip('Z') if isinstance(value, str) else value normalised = value.rstrip('Z') if isinstance(value, str) else value
for fmt in ('%Y-%m-%dT%H:%M:%S', '%Y-%m-%dT%H:%M:%S.%f', '%Y-%m-%d'): for fmt in ('%Y-%m-%dT%H:%M:%S', '%Y-%m-%dT%H:%M:%S.%f', '%Y-%m-%d'):
try: try:
return datetime.strptime(normalised, fmt) dt = datetime.strptime(normalised, fmt)
if is_utc:
dt = (dt.replace(tzinfo=_tz.utc)
.astimezone(EASTERN)
.replace(tzinfo=None))
return dt
except (ValueError, TypeError): except (ValueError, TypeError):
pass pass
return None return None