feat: Add Berlin date-time formatting for match results processing
All checks were successful
Deploy tt-tagebuch / deploy (push) Successful in 54s

This commit is contained in:
Torsten Schulz (local)
2026-07-24 13:31:49 +02:00
parent e2e8ba0d54
commit 01ca924e3e

View File

@@ -14,6 +14,32 @@ import { devLog } from '../utils/logger.js';
import SeasonService from './seasonService.js';
class AutoFetchMatchResultsService {
getBerlinDateTimeParts(value) {
const formatter = new Intl.DateTimeFormat('en-CA', {
timeZone: 'Europe/Berlin',
year: 'numeric',
month: '2-digit',
day: '2-digit',
hour: '2-digit',
minute: '2-digit',
second: '2-digit',
hourCycle: 'h23',
});
const parts = Object.fromEntries(
formatter.formatToParts(value)
.filter((part) => part.type !== 'literal')
.map((part) => [part.type, part.value])
);
return {
year: Number(parts.year),
month: Number(parts.month),
day: Number(parts.day),
hour: parts.hour,
minute: parts.minute,
second: parts.second,
};
}
parseMatchDateTime(rawValue) {
if (!rawValue) {
return { date: null, time: null };
@@ -23,14 +49,16 @@ class AutoFetchMatchResultsService {
const normalized = rawValue.trim();
const hasExplicitTimezone = /(?:Z|[+-]\d{2}:?\d{2})$/i.test(normalized);
// ISO values with explicit timezone are often UTC timestamps.
// Convert them to local clock time before persisting date/time parts.
// myTischtennis supplies ISO values with an explicit timezone in UTC.
// Match start times are local civil times, therefore never depend on the
// server process timezone (production commonly runs in UTC).
if (hasExplicitTimezone) {
const zoned = new Date(normalized);
if (!Number.isNaN(zoned.getTime())) {
const berlin = this.getBerlinDateTimeParts(zoned);
return {
date: new Date(zoned.getFullYear(), zoned.getMonth(), zoned.getDate(), 0, 0, 0, 0),
time: `${String(zoned.getHours()).padStart(2, '0')}:${String(zoned.getMinutes()).padStart(2, '0')}:${String(zoned.getSeconds()).padStart(2, '0')}`
date: new Date(berlin.year, berlin.month - 1, berlin.day, 0, 0, 0, 0),
time: `${berlin.hour}:${berlin.minute}:${berlin.second}`
};
}
}