I have a date server api that works in Europe/Moscow timezone. The selected date must be sent from the client as a timestamp for the Europe/Moscow timezone.
A client from Canada choosing a date in the calendar, say November 8, 2011 has to send the timestamp in the Europe/Moscow timezone.
I can solve this problem through moment.js, but unfortunately, for certain reasons I can't use third-party libraries in the project.
Basically I need a function that does the same thing as the moment.tz method:
moment.tz('2021-11-08T00:00:00', 'Europe/Moscow');
You can use Intl.DateTimeFormat with suitable options to get a timestamp for any IANA location. The formatToParts method gets the required values, then it's just a matter of formatting them. E.g.
function toLocTimestamp(loc, date = new Date()) {
let {year, month, day, hour, minute, second, timeZoneName} = new Intl.DateTimeFormat('en', {
year: 'numeric',
month: '2-digit',
day: '2-digit',
hour: '2-digit',
minute: '2-digit',
second: '2-digit',
hour12: false,
timeZone: loc,
timeZoneName: 'short'
}).formatToParts().reduce((parts, part) => {
parts[part.type] = part.value;
return parts;
}, Object.create(null));
// Check if timezone not offset and fix
if (!/\d/.test(timeZoneName)) {
timeZoneName = date.toLocaleString('fr',{
hour: 'numeric',
timeZone: loc,
timeZoneName: 'short'
}).match(/\S+$/)[0];
}
// Change timeZoneName to offset
let sign = timeZoneName.substring(3,4);
let offset = timeZoneName.substring(4);
let [offH, offM] = offset.split(':');
// Return timestamp
return `${year}-${month}-${day}T${hour}:${minute}:${second}${sign}${offH.padStart(2,'0')}:${offM || '00'}`;
}
// E.g.
['Europe/Moscow', 'Asia/Kolkata','Australia/Lord_Howe',
'America/St_Johns'].forEach(
loc => console.log(`${loc.padEnd(20,' ')}: ${toLocTimestamp(loc)}`)
);
The timeZoneName fix is required as depending on the language passed to dateTimeFormat and host system language, the offset might be GMT±H[:mm], UTC±H[:mm] or an abbreviation like "ChST" or "CET". If en returns an abbreviation, fr shouldn't.
This will observe DST for various locations. If a fixed offset is required, just adjust the UTC time by the offset, use toISOString to get the timestamp and remove the trailing Z.