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 = `
+
+
+
+
+
+
+ `;
+
+ 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 = `
+
+
+
${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 = `
+
+
+
${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', {