Created
March 24, 2025 14:14
-
-
Save malko/4f4e6e8891148a0c48decc1052def7ba to your computer and use it in GitHub Desktop.
initDateTimeWithTimezone
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* Return a date object with the specified date and timezone respecting DST | |
* @param {string} dateStr - Date string in 'YYYY-MM-DD' or 'YYYY-MM-DD[T| ]HH:MM:SS' format | |
* @param {string} timezone - IANA timezone string (e.g., 'Europe/Paris') | |
* @returns {Date} - Date object adjusted for the specified timezone | |
*/ | |
function initDateTimeWithTimezone(dateStr, timezone) { | |
let year, month, day, hours = '00', minutes = '00', seconds = '00'; | |
dateStr = dateStr.trim(); | |
// Check if time is included in the date string | |
if (dateStr.includes('T') || dateStr.includes(' ')) { | |
// Parse date with time (YYYY-MM-DDT00:00:00 or YYYY-MM-DD 00:00:00) | |
const parts = dateStr.replace('T', ' ').split(' '); | |
// Parse date components | |
[year, month, day] = parts[0].split('-'); | |
// Parse time components if provided | |
if (parts[1]) { | |
const timeParts = parts[1].split(':'); | |
hours = timeParts[0] || '00'; | |
minutes = timeParts[1] || '00'; | |
seconds = timeParts[2] || '00'; | |
} | |
} else { | |
// Parse date only (YYYY-MM-DD) | |
[year, month, day] = dateStr.split('-'); | |
} | |
// Create ISO string like '2025-03-30T00:00:00' in target timezone format | |
const targetDateISO = `${year}-${month}-${day}T${hours}:${minutes}:${seconds}`; | |
// Use the date with timezone string format | |
const targetTZDate = new Date(`${targetDateISO}Z`); | |
// Create a formatter that will give us the UTC offset for this specific date and timezone | |
const options = { | |
timeZone: timezone, | |
year: 'numeric', | |
month: '2-digit', | |
day: '2-digit', | |
hour: '2-digit', | |
minute: '2-digit', | |
second: '2-digit', | |
hour12: false, | |
timeZoneName: 'short' | |
}; | |
const formatter = new Intl.DateTimeFormat('en-US', options); | |
const dateInTZ = formatter.format(targetTZDate); | |
// Extract timezone offset from the formatted string (like "03/30/2025, 00:00:00 GMT+2") | |
const tzOffsetMatch = dateInTZ.match(/GMT([+-])(\d+)/); | |
console.log('offset', tzOffsetMatch[0]); | |
if (tzOffsetMatch) { | |
const sign = tzOffsetMatch[1] === '+' ? -1 : 1; // If GMT+2, we need to subtract 2 hours from UTC | |
const hours = parseInt(tzOffsetMatch[2], 10); | |
// Calculate the UTC time by adjusting for the timezone offset | |
// For midnight in Paris (GMT+2), the UTC time would be 10 PM (22:00) the previous day | |
const offsetMillis = sign * hours * 60 * 60 * 1000; | |
return new Date(targetTZDate.getTime() + offsetMillis); | |
} | |
// Fallback if we couldn't extract the timezone offset | |
return targetTZDate; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment