From e195214a1f6abcc86f0b8b499f231a01ca759c28 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 10 Aug 2025 04:03:33 +0000 Subject: [PATCH 1/7] Initial plan From 172131f19333f198b06a88e7fbeed6b6939b5a06 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 10 Aug 2025 04:30:11 +0000 Subject: [PATCH 2/7] Fix DST timezone selection issues - add "+" buttons to search results and expand modal behavior Co-authored-by: tsmarvin <57049894+tsmarvin@users.noreply.github.com> --- src/scripts/index.ts | 104 ++++++++++++++++++++++++++++-- src/styles/styles.css | 144 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 243 insertions(+), 5 deletions(-) diff --git a/src/scripts/index.ts b/src/scripts/index.ts index eb399a8..1bdae43 100644 --- a/src/scripts/index.ts +++ b/src/scripts/index.ts @@ -2226,11 +2226,8 @@ export class TimezoneModal { if (plusBtn && group.alternate) { plusBtn.addEventListener('click', e => { e.stopPropagation(); - // Select the alternate timezone directly and mark as off-cycle - if (this.onTimezoneSelectedCallback && group.alternate) { - this.onTimezoneSelectedCallback(group.alternate, true); // Mark alternate as off-cycle - } - this.close(); + // Expand to show both timezone options instead of directly adding alternate + this.showTimezoneOptions(group); }); } @@ -2293,13 +2290,30 @@ export class TimezoneModal { ? `${timezone.cityName} (${timezone.abbreviation})` : `${timezone.cityName} (${timezone.abbreviation} ${offsetStr})`; + // Check if this timezone has an alternate available (for DST support in search results) + const matchingGroup = this.groupedTimezonesLookup.get(timezone.iana); + const hasAlternate = matchingGroup && matchingGroup.alternate; + item.innerHTML = `
${displayText} + ${hasAlternate ? '+' : ''}
${timezone.displayName}
`; + // Handle plus button clicks (for search results) + if (hasAlternate) { + const plusBtn = item.querySelector('.timezone-plus-btn'); + if (plusBtn && matchingGroup && matchingGroup.alternate) { + plusBtn.addEventListener('click', e => { + e.stopPropagation(); + // Expand to show both timezone options instead of directly adding alternate + this.showTimezoneOptions(matchingGroup); + }); + } + } + // Click handler item.addEventListener('click', () => { if (!isCenter) { @@ -2369,6 +2383,86 @@ export class TimezoneModal { document.body.style.overflow = ''; } + /** + * Show expanded view with both timezone options for selection + */ + private showTimezoneOptions(group: GroupedTimezone): void { + // Clear wheel and show both timezone options + this.wheel.innerHTML = ''; + + const optionsContainer = document.createElement('div'); + optionsContainer.className = 'timezone-options-container'; + optionsContainer.innerHTML = ` +
+

Select ${group.location} Timezone

+
Choose your preferred time offset
+
+
+
+
+ +
+ `; + + const optionsList = optionsContainer.querySelector('.timezone-options-list') as HTMLElement; + + // Add current timezone option + const currentOption = document.createElement('div'); + currentOption.className = 'timezone-option current-option'; + currentOption.innerHTML = ` +
+
${group.current.cityName} (${group.current.abbreviation})
+
Current
+
+
+
${formatOffset(group.current.offset)}
+
${group.current.displayName}
+
+ `; + + currentOption.addEventListener('click', () => { + if (this.onTimezoneSelectedCallback) { + this.onTimezoneSelectedCallback(group.current); + } + this.close(); + }); + + optionsList.appendChild(currentOption); + + // Add alternate timezone option if available + if (group.alternate) { + const alternateOption = document.createElement('div'); + alternateOption.className = 'timezone-option alternate-option'; + alternateOption.innerHTML = ` +
+
${group.alternate.cityName} (${group.alternate.abbreviation})
+
Alternate
+
+
+
${formatOffset(group.alternate.offset)}
+
${group.alternate.displayName}
+
+ `; + + alternateOption.addEventListener('click', () => { + if (this.onTimezoneSelectedCallback && group.alternate) { + this.onTimezoneSelectedCallback(group.alternate, true); // Mark alternate as off-cycle + } + this.close(); + }); + + optionsList.appendChild(alternateOption); + } + + // Back button functionality + const backButton = optionsContainer.querySelector('.timezone-option-back') as HTMLElement; + backButton.addEventListener('click', () => { + this.renderWheel(); + }); + + this.wheel.appendChild(optionsContainer); + } + /** * Show custom timezone creation option when offset query has no matches */ diff --git a/src/styles/styles.css b/src/styles/styles.css index 2c9455f..69a525d 100644 --- a/src/styles/styles.css +++ b/src/styles/styles.css @@ -1296,6 +1296,150 @@ p { min-width: 80px; } +/* Timezone Options Display Styles */ +.timezone-options-container { + background: var(--color-surface); + border-radius: var(--border-radius); + padding: var(--space-lg); + margin: var(--space-sm); + border: 1px solid var(--color-border); + min-width: 350px; + max-width: 450px; +} + +.timezone-options-header { + text-align: center; + margin-bottom: var(--space-lg); +} + +.timezone-options-header h3 { + margin: 0 0 var(--space-xs) 0; + font-size: var(--text-xl); + font-weight: var(--font-weight-semibold); + color: var(--color-text); +} + +.timezone-options-subtitle { + font-size: var(--text-sm); + color: var(--color-text-secondary); + margin-top: var(--space-xs); +} + +.timezone-options-list { + display: flex; + flex-direction: column; + gap: var(--space-sm); + margin-bottom: var(--space-lg); +} + +.timezone-option { + background: var(--color-surface-variant); + border: 2px solid var(--color-border); + border-radius: var(--border-radius); + padding: var(--space-md); + cursor: pointer; + transition: var(--transition); + position: relative; +} + +.timezone-option:hover { + border-color: var(--color-primary); + background: var(--color-surface); + transform: translateY(-1px); + box-shadow: 0 2px 8px var(--color-shadow); +} + +.timezone-option.current-option { + border-color: var(--color-primary); + background: var(--color-primary-alpha); +} + +.timezone-option.alternate-option { + border-color: var(--color-secondary); +} + +.timezone-option.alternate-option:hover { + border-color: var(--color-secondary-hover); + background: var(--color-secondary-alpha); +} + +.timezone-option-header { + display: flex; + justify-content: space-between; + align-items: center; + margin-bottom: var(--space-xs); +} + +.timezone-option-name { + font-size: var(--text-base); + font-weight: var(--font-weight-semibold); + color: var(--color-text); +} + +.timezone-option-badge { + font-size: var(--text-xs); + padding: 2px var(--space-xs); + border-radius: var(--border-radius); + font-weight: var(--font-weight-medium); + text-transform: uppercase; + letter-spacing: 0.5px; +} + +.current-option .timezone-option-badge { + background: var(--color-primary); + color: white; +} + +.alternate-option .timezone-option-badge { + background: var(--color-secondary); + color: white; +} + +.timezone-option-details { + display: flex; + justify-content: space-between; + align-items: flex-end; + gap: var(--space-sm); +} + +.timezone-option-offset { + font-family: monospace; + font-size: var(--text-lg); + font-weight: var(--font-weight-bold); + color: var(--color-text); +} + +.timezone-option-display { + font-size: var(--text-sm); + color: var(--color-text-secondary); + text-align: right; + line-height: 1.3; + flex: 1; +} + +.timezone-options-actions { + display: flex; + justify-content: center; + gap: var(--space-sm); +} + +.timezone-option-back { + padding: var(--space-xs) var(--space-md); + border: 1px solid var(--color-border); + border-radius: var(--border-radius); + background: var(--color-surface-variant); + color: var(--color-text); + font-size: var(--text-sm); + cursor: pointer; + transition: var(--transition); + min-width: 120px; +} + +.timezone-option-back:hover { + background: var(--color-surface); + border-color: var(--color-primary); +} + .modal-footer { padding: var(--space-xs); border-top: 1px solid var(--color-border); From 88c5e14fdf2de41709ec0cb3f42aa548439acd64 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 10 Aug 2025 04:45:26 +0000 Subject: [PATCH 3/7] refactor: replace legacy Date methods with Temporal API for DST/timezone calculations Update core timezone calculation functions to use Temporal polyfill instead of legacy Date methods: - Replace new Date() with Temporal.Now.instant().epochMilliseconds in default parameters - Update getTimezoneVariations() to use Temporal.PlainDate for creating test dates - Modernize initializeTimezoneData() to use Temporal for June/December dates - Convert getUserTimezone(), getAllTimezonesOrdered(), getGroupedTimezones() to use Temporal - Update generateTimelineHours() and other timezone functions to use Temporal - Maintain backward compatibility by converting Temporal dates to Date objects for Intl.DateTimeFormat All DST timezone selection features continue to work properly with the new temporal-based calculations. Co-authored-by: tsmarvin <57049894+tsmarvin@users.noreply.github.com> --- src/scripts/index.ts | 39 +++++++++++++++++++++------------------ 1 file changed, 21 insertions(+), 18 deletions(-) diff --git a/src/scripts/index.ts b/src/scripts/index.ts index 1bdae43..cd3343f 100644 --- a/src/scripts/index.ts +++ b/src/scripts/index.ts @@ -85,7 +85,7 @@ export function getUserTimezone(date?: Date): TimeZone { // Get user's timezone ID using Temporal (polyfill ensures availability) const userTimezone = Temporal.Now.timeZoneId(); - const now = date || new Date(); + const now = date || new Date(Temporal.Now.instant().epochMilliseconds); // Use Intl for offset calculation (proven compatibility) const formatter = new Intl.DateTimeFormat('en', { @@ -421,7 +421,7 @@ function getTimezoneAbbreviation(displayName: string, iana: string, date?: Date) }); // Format the provided date (or current date) and extract the timezone abbreviation - const parts = formatter.formatToParts(date || new Date()); + const parts = formatter.formatToParts(date || new Date(Temporal.Now.instant().epochMilliseconds)); const timeZonePart = parts.find(part => part.type === 'timeZoneName'); if (timeZonePart && timeZonePart.value && timeZonePart.value.length <= 5) { @@ -469,7 +469,7 @@ function createTimezoneDisplayName(iana: string, offset: number, date?: Date): s }); // Get the timezone name from the provided date (or current date) - const parts = formatter.formatToParts(date || new Date()); + const parts = formatter.formatToParts(date || new Date(Temporal.Now.instant().epochMilliseconds)); const timeZonePart = parts.find(part => part.type === 'timeZoneName'); if (timeZonePart && timeZonePart.value) { @@ -513,7 +513,7 @@ function formatOffset(offset: number): string { * @returns Array of timeline hours with daylight information and date transitions */ export function generateTimelineHours(numHours: number, timezone: TimeZone, baseDate?: Date): TimelineHour[] { - const now = baseDate || new Date(); + const now = baseDate || new Date(Temporal.Now.instant().epochMilliseconds); const userTz = getUserTimezone(); // Get current hour in user's timezone and round down @@ -924,7 +924,7 @@ export class TimelineManager { private modal: TimezoneModal; private dateTimeModal: DateTimeModal; private selectedTimezones: TimeZone[] = []; - private selectedDate: Date = new Date(); // Default to today + private selectedDate: Date = new Date(Temporal.Now.instant().epochMilliseconds); // Default to today constructor() { this.container = document.getElementById('timeline-container') as HTMLElement; @@ -1323,15 +1323,15 @@ function saveTimezoneCache(): void { * Initialize timezone data by processing all browser timezones for June and December * This expensive operation should only be done once on page load */ -function initializeTimezoneData(year: number = new Date().getFullYear()): ProcessedTimezoneData { +function initializeTimezoneData(year: number = Temporal.Now.plainDateISO().year): ProcessedTimezoneData { const userTimezone = Temporal.Now.timeZoneId(); // Get all supported timezones (comprehensive list) const allTimezones = Intl.supportedValuesOf('timeZone'); - // Create dates for June 1st and December 31st to capture DST variations - const juneDate = new Date(year, 5, 1); // June 1st - const decemberDate = new Date(year, 11, 31); // December 31st + // Create dates for June 1st and December 31st to capture DST variations using Temporal + const juneDate = new Date(Temporal.PlainDate.from({ year, month: 6, day: 1 }).year, 5, 1); // June 1st + const decemberDate = new Date(Temporal.PlainDate.from({ year, month: 12, day: 31 }).year, 11, 31); // December 31st console.log(`Processing ${allTimezones.length} timezones for June and December variants...`); @@ -1464,7 +1464,7 @@ function getTimezoneSetForDate(date: Date, processedData: ProcessedTimezoneData) * @returns Array of timezone objects ordered from user's timezone around the globe */ export function getAllTimezonesOrdered(date?: Date): TimeZone[] { - const now = date || new Date(); + const now = date || new Date(Temporal.Now.instant().epochMilliseconds); const currentYear = now.getFullYear(); // Load cache from localStorage on first call @@ -1496,14 +1496,17 @@ export function getAllTimezonesOrdered(date?: Date): TimeZone[] { * Get timezone variations for a given IANA identifier using fixed dates * Returns both summer (June 1st) and winter (December 31st) variations */ -function getTimezoneVariations(iana: string, year: number = new Date().getFullYear()): TimeZone[] { +function getTimezoneVariations(iana: string, year: number = Temporal.Now.plainDateISO().year): TimeZone[] { const variations: TimeZone[] = []; - // Use June 1st for summer time and December 31st for winter time - const summerDate = new Date(year, 5, 1); // June 1st - const winterDate = new Date(year, 11, 31); // December 31st + // Use June 1st for summer time and December 31st for winter time using Temporal + const summerDate = Temporal.PlainDate.from({ year, month: 6, day: 1 }); // June 1st + const winterDate = Temporal.PlainDate.from({ year, month: 12, day: 31 }); // December 31st + + for (const plainDate of [summerDate, winterDate]) { + // Convert Temporal.PlainDate to Date for Intl.DateTimeFormat compatibility + const date = new Date(plainDate.year, plainDate.month - 1, plainDate.day); - for (const date of [summerDate, winterDate]) { const formatter = new Intl.DateTimeFormat('en', { timeZone: iana, timeZoneName: 'longOffset', @@ -1574,7 +1577,7 @@ function extractRegion(iana: string): string { * Get grouped timezones with DST/Standard variations, prioritized by selected date */ export function getGroupedTimezones(selectedDate?: Date): GroupedTimezone[] { - const date = selectedDate || new Date(); + const date = selectedDate || new Date(Temporal.Now.instant().epochMilliseconds); const allTimezones = Intl.supportedValuesOf('timeZone'); const locationGroups = new Map(); @@ -1809,7 +1812,7 @@ export class TimezoneModal { private selectedDate: Date; // Date to use for timezone calculations constructor(onTimezoneSelected?: (timezone: TimeZone, isOffCycle?: boolean) => void, selectedDate?: Date) { - this.selectedDate = selectedDate || new Date(); + this.selectedDate = selectedDate || new Date(Temporal.Now.instant().epochMilliseconds); this.modal = document.getElementById('timezone-modal') as HTMLElement; this.overlay = document.getElementById('timezone-modal-overlay') as HTMLElement; this.input = document.getElementById('timezone-input') as HTMLInputElement; @@ -2700,7 +2703,7 @@ export class DateTimeModal { // Set current datetime as default if no value is set if (!this.input.value) { - const now = new Date(); + const now = new Date(Temporal.Now.instant().epochMilliseconds); // Format to datetime-local format (YYYY-MM-DDTHH:MM) const year = now.getFullYear(); const month = String(now.getMonth() + 1).padStart(2, '0'); From ab8d79b0c1f2ceed4d5398c74c89c5fc788bf057 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 10 Aug 2025 05:01:15 +0000 Subject: [PATCH 4/7] refactor: simplify Date creation patterns and eliminate redundant Temporal.PlainDate usage Co-authored-by: tsmarvin <57049894+tsmarvin@users.noreply.github.com> --- src/scripts/index.ts | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/src/scripts/index.ts b/src/scripts/index.ts index cd3343f..2639176 100644 --- a/src/scripts/index.ts +++ b/src/scripts/index.ts @@ -1329,9 +1329,9 @@ function initializeTimezoneData(year: number = Temporal.Now.plainDateISO().year) // Get all supported timezones (comprehensive list) const allTimezones = Intl.supportedValuesOf('timeZone'); - // Create dates for June 1st and December 31st to capture DST variations using Temporal - const juneDate = new Date(Temporal.PlainDate.from({ year, month: 6, day: 1 }).year, 5, 1); // June 1st - const decemberDate = new Date(Temporal.PlainDate.from({ year, month: 12, day: 31 }).year, 11, 31); // December 31st + // Create dates for June 1st and December 31st to capture DST variations + const juneDate = new Date(year, 5, 1); // June 1st + const decemberDate = new Date(year, 11, 31); // December 31st console.log(`Processing ${allTimezones.length} timezones for June and December variants...`); @@ -1499,14 +1499,11 @@ export function getAllTimezonesOrdered(date?: Date): TimeZone[] { function getTimezoneVariations(iana: string, year: number = Temporal.Now.plainDateISO().year): TimeZone[] { const variations: TimeZone[] = []; - // Use June 1st for summer time and December 31st for winter time using Temporal - const summerDate = Temporal.PlainDate.from({ year, month: 6, day: 1 }); // June 1st - const winterDate = Temporal.PlainDate.from({ year, month: 12, day: 31 }); // December 31st - - for (const plainDate of [summerDate, winterDate]) { - // Convert Temporal.PlainDate to Date for Intl.DateTimeFormat compatibility - const date = new Date(plainDate.year, plainDate.month - 1, plainDate.day); + // Use June 1st for summer time and December 31st for winter time + const summerDate = new Date(year, 5, 1); // June 1st + const winterDate = new Date(year, 11, 31); // December 31st + for (const date of [summerDate, winterDate]) { const formatter = new Intl.DateTimeFormat('en', { timeZone: iana, timeZoneName: 'longOffset', From 42a0a9f9de0ceccbebb51d3d2fb986dd69fd7e55 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 10 Aug 2025 05:13:59 +0000 Subject: [PATCH 5/7] refactor: replace legacy Date usage with proper Temporal API implementation Co-authored-by: tsmarvin <57049894+tsmarvin@users.noreply.github.com> --- src/scripts/index.ts | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/src/scripts/index.ts b/src/scripts/index.ts index 2639176..d0c0dfa 100644 --- a/src/scripts/index.ts +++ b/src/scripts/index.ts @@ -1329,9 +1329,11 @@ function initializeTimezoneData(year: number = Temporal.Now.plainDateISO().year) // Get all supported timezones (comprehensive list) const allTimezones = Intl.supportedValuesOf('timeZone'); - // Create dates for June 1st and December 31st to capture DST variations - const juneDate = new Date(year, 5, 1); // June 1st - const decemberDate = new Date(year, 11, 31); // December 31st + // Create dates for June 1st and December 31st to capture DST variations using Temporal + const junePlainDate = Temporal.PlainDate.from({ year, month: 6, day: 1 }); + const decemberPlainDate = Temporal.PlainDate.from({ year, month: 12, day: 31 }); + const juneDate = new Date(junePlainDate.toZonedDateTime(Temporal.Now.timeZoneId()).epochMilliseconds); + const decemberDate = new Date(decemberPlainDate.toZonedDateTime(Temporal.Now.timeZoneId()).epochMilliseconds); console.log(`Processing ${allTimezones.length} timezones for June and December variants...`); @@ -1499,9 +1501,13 @@ export function getAllTimezonesOrdered(date?: Date): TimeZone[] { function getTimezoneVariations(iana: string, year: number = Temporal.Now.plainDateISO().year): TimeZone[] { const variations: TimeZone[] = []; - // Use June 1st for summer time and December 31st for winter time - const summerDate = new Date(year, 5, 1); // June 1st - const winterDate = new Date(year, 11, 31); // December 31st + // Use June 1st for summer time and December 31st for winter time using Temporal + const summerPlainDate = Temporal.PlainDate.from({ year, month: 6, day: 1 }); + const winterPlainDate = Temporal.PlainDate.from({ year, month: 12, day: 31 }); + + // Convert to Date objects for Intl.DateTimeFormat compatibility + const summerDate = new Date(summerPlainDate.toZonedDateTime(Temporal.Now.timeZoneId()).epochMilliseconds); + const winterDate = new Date(winterPlainDate.toZonedDateTime(Temporal.Now.timeZoneId()).epochMilliseconds); for (const date of [summerDate, winterDate]) { const formatter = new Intl.DateTimeFormat('en', { From 982a7501b267f5664c61136a0af99066e19e473e Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 10 Aug 2025 05:31:29 +0000 Subject: [PATCH 6/7] fix: correct Temporal API usage for DST calculations using proper timezone parameters Co-authored-by: tsmarvin <57049894+tsmarvin@users.noreply.github.com> --- src/scripts/index.ts | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/scripts/index.ts b/src/scripts/index.ts index d0c0dfa..531425d 100644 --- a/src/scripts/index.ts +++ b/src/scripts/index.ts @@ -1332,8 +1332,8 @@ function initializeTimezoneData(year: number = Temporal.Now.plainDateISO().year) // Create dates for June 1st and December 31st to capture DST variations using Temporal const junePlainDate = Temporal.PlainDate.from({ year, month: 6, day: 1 }); const decemberPlainDate = Temporal.PlainDate.from({ year, month: 12, day: 31 }); - const juneDate = new Date(junePlainDate.toZonedDateTime(Temporal.Now.timeZoneId()).epochMilliseconds); - const decemberDate = new Date(decemberPlainDate.toZonedDateTime(Temporal.Now.timeZoneId()).epochMilliseconds); + const juneDate = new Date(junePlainDate.toZonedDateTime('UTC').epochMilliseconds); + const decemberDate = new Date(decemberPlainDate.toZonedDateTime('UTC').epochMilliseconds); console.log(`Processing ${allTimezones.length} timezones for June and December variants...`); @@ -1505,9 +1505,9 @@ function getTimezoneVariations(iana: string, year: number = Temporal.Now.plainDa const summerPlainDate = Temporal.PlainDate.from({ year, month: 6, day: 1 }); const winterPlainDate = Temporal.PlainDate.from({ year, month: 12, day: 31 }); - // Convert to Date objects for Intl.DateTimeFormat compatibility - const summerDate = new Date(summerPlainDate.toZonedDateTime(Temporal.Now.timeZoneId()).epochMilliseconds); - const winterDate = new Date(winterPlainDate.toZonedDateTime(Temporal.Now.timeZoneId()).epochMilliseconds); + // Convert to Date objects for Intl.DateTimeFormat compatibility using the target timezone + const summerDate = new Date(summerPlainDate.toZonedDateTime(iana).epochMilliseconds); + const winterDate = new Date(winterPlainDate.toZonedDateTime(iana).epochMilliseconds); for (const date of [summerDate, winterDate]) { const formatter = new Intl.DateTimeFormat('en', { From 4adb0db5c26db469262be00b24c3727a9563e1aa Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 10 Aug 2025 05:48:30 +0000 Subject: [PATCH 7/7] fix: eliminate Date object creation with timezone-specific milliseconds to prevent incorrect offset calculations Co-authored-by: tsmarvin <57049894+tsmarvin@users.noreply.github.com> --- src/scripts/index.ts | 20 ++++++++------------ 1 file changed, 8 insertions(+), 12 deletions(-) diff --git a/src/scripts/index.ts b/src/scripts/index.ts index 531425d..def95e6 100644 --- a/src/scripts/index.ts +++ b/src/scripts/index.ts @@ -1329,11 +1329,10 @@ function initializeTimezoneData(year: number = Temporal.Now.plainDateISO().year) // Get all supported timezones (comprehensive list) const allTimezones = Intl.supportedValuesOf('timeZone'); - // Create dates for June 1st and December 31st to capture DST variations using Temporal - const junePlainDate = Temporal.PlainDate.from({ year, month: 6, day: 1 }); - const decemberPlainDate = Temporal.PlainDate.from({ year, month: 12, day: 31 }); - const juneDate = new Date(junePlainDate.toZonedDateTime('UTC').epochMilliseconds); - const decemberDate = new Date(decemberPlainDate.toZonedDateTime('UTC').epochMilliseconds); + // Create neutral dates for June 1st and December 31st to capture DST variations + // Using UTC to avoid local timezone interpretation issues + const juneDate = new Date(Date.UTC(year, 5, 1)); // June 1st in UTC + const decemberDate = new Date(Date.UTC(year, 11, 31)); // December 31st in UTC console.log(`Processing ${allTimezones.length} timezones for June and December variants...`); @@ -1501,13 +1500,10 @@ export function getAllTimezonesOrdered(date?: Date): TimeZone[] { function getTimezoneVariations(iana: string, year: number = Temporal.Now.plainDateISO().year): TimeZone[] { const variations: TimeZone[] = []; - // Use June 1st for summer time and December 31st for winter time using Temporal - const summerPlainDate = Temporal.PlainDate.from({ year, month: 6, day: 1 }); - const winterPlainDate = Temporal.PlainDate.from({ year, month: 12, day: 31 }); - - // Convert to Date objects for Intl.DateTimeFormat compatibility using the target timezone - const summerDate = new Date(summerPlainDate.toZonedDateTime(iana).epochMilliseconds); - const winterDate = new Date(winterPlainDate.toZonedDateTime(iana).epochMilliseconds); + // Use June 1st for summer time and December 31st for winter time + // Create neutral UTC dates and let Intl.DateTimeFormat handle timezone conversion + const summerDate = new Date(Date.UTC(year, 5, 1)); // June 1st in UTC + const winterDate = new Date(Date.UTC(year, 11, 31)); // December 31st in UTC for (const date of [summerDate, winterDate]) { const formatter = new Intl.DateTimeFormat('en', {