import type { NameValue, TypeAndName } from './base.ts'; export interface TimezoneInfo { readonly displayName: string; readonly timezoneName: string; } export interface LocalizedTimezoneInfo { readonly name: string; readonly utcOffset: string; readonly utcOffsetMinutes: number; readonly displayName: string; readonly displayNameWithUtcOffset: string; } export class KnownDateTimezoneFormat implements NameValue { private static readonly allInstances: KnownDateTimezoneFormat[] = []; private static readonly allInstancesByValue: Record = {}; public static readonly HHColonMM = new KnownDateTimezoneFormat('±HH:mm', 'Z', /^[+-]?([0-1][0-9]|2[0-3]):[0-5][0-9]$/); public static readonly HHMM = new KnownDateTimezoneFormat('±HHmm', 'ZZ', /^[+-]?([0-1][0-9]|2[0-3])[0-5][0-9]$/); public readonly name: string; public readonly value: string; private readonly regex: RegExp; private constructor(name: string, value: string, regex: RegExp) { this.name = name; this.value = value; this.regex = regex; KnownDateTimezoneFormat.allInstances.push(this); KnownDateTimezoneFormat.allInstancesByValue[value] = this; } public isValid(dateTime: string): boolean { return this.regex.test(dateTime); } public static values(): KnownDateTimezoneFormat[] { return KnownDateTimezoneFormat.allInstances; } public static valueOf(value: string): KnownDateTimezoneFormat | undefined { return KnownDateTimezoneFormat.allInstancesByValue[value]; } public static detect(dateTime: string): KnownDateTimezoneFormat[] | undefined { const result: KnownDateTimezoneFormat[] = []; for (const format of KnownDateTimezoneFormat.allInstances) { if (format.isValid(dateTime)) { result.push(format); } } return result.length > 0 ? result : undefined; } public static detectMulti(dateTimes: string[]): KnownDateTimezoneFormat[] | undefined { const detectedCounts: Record = {}; for (const dateTime of dateTimes) { const detectedFormats = KnownDateTimezoneFormat.detect(dateTime); if (detectedFormats) { for (const format of detectedFormats) { detectedCounts[format.value] = (detectedCounts[format.value] || 0) + 1; } } else { return undefined; } } const result: KnownDateTimezoneFormat[] = []; for (const format of KnownDateTimezoneFormat.allInstances) { if (detectedCounts[format.value] === dateTimes.length) { result.push(format); } } return result.length > 0 ? result : undefined; } } export class TimezoneTypeForStatistics implements TypeAndName { public static readonly ApplicationTimezone = new TimezoneTypeForStatistics(0, 'Application Timezone'); public static readonly TransactionTimezone = new TimezoneTypeForStatistics(1, 'Transaction Timezone'); public static readonly Default = TimezoneTypeForStatistics.ApplicationTimezone; public readonly type: number; public readonly name: string; private constructor(type: number, name: string) { this.type = type; this.name = name; } }