Mientras trabajo en varias zonas horarias, tengo un caso en el que creo turnos en varias zonas horarias, ahora los usuarios solicitan esos turnos.
Es muy sensible al tiempo. Ahora, lo que quiero ingresar es la zona horaria en la que se encuentra el cambio (por ejemplo Australia/Sydney ). Solución: ahora, antes de guardarlo en la base de datos, estoy convirtiendo la zona horaria a UTCoffset, lo que significa que, en el ejemplo, la zona horaria de Australia/Sydney estoy configurando la compensación con - ejemplo, la compensación de Australia es 600 y luego -600 configurando la oferta y almacenando en la base de datos.
const getUTCOffset = timezone => Intl.DateTimeFormat([], {timeZone: timezone, timeZoneName: 'shortOffset'}).formatToParts().find(o => o.type === 'timeZoneName').value.match(/\-?\d+/)[0]*60;
(getUTCOffset('Australia/Sydney'))
¿Hay algo que me estoy perdiendo aquí? ¿Cuál podría ser la solución óptima para esto?
Creo que lo que te estás perdiendo es que las compensaciones cambian de vez en cuando debido a cambios históricos y al horario de verano. Es mucho mejor que almacene la ubicación de la IANA y calcule la compensación según sea necesario.
Si desea obtener el desplazamiento de una ubicación en minutos (lo cual es conveniente), considere:
function getOffsetInMinutes(loc, date = new Date()) { let [year, sign, hr, min] = date.toLocaleString('en', { year:'numeric', timeZone:loc, timeZoneName:'longOffset' }).match(/\d+|\+|\-/g); return (sign == '+'? 1 : -1) * (hr*60 + min*1); } ['Asia/Kolkata', 'Australia/Sydney', 'America/New_York' ].forEach( loc => console.log(loc + ': ' + getOffsetInMinutes(loc)) );Para los navegadores que no admiten los valores de la opción timeZoneName más nuevos (como Safari), puede usar una función que use el valor "corto" en su lugar. Lo siguiente devuelve el desplazamiento como ±HH:mm, no es difícil de modificar para devolver los minutos como se indicó anteriormente.
// Return offset on date for loc in ±HH:mm format function getTimezoneOffset(loc, date=new Date()) { // Try English to get offset. If get abbreviation, use French let offset; ['en','fr'].some(lang => { // Get parts - can't get just timeZoneName, must get one other part at least let parts = new Intl.DateTimeFormat(lang, { minute: 'numeric', timeZone: loc, timeZoneName:'short' }).formatToParts(date); // Get offset from parts let tzName = parts.filter(part => part.type == 'timeZoneName' && part.value); // timeZoneName starting with GMT or UTC is offset - keep and stop looping // Otherwise it's an abbreviation, keep looping if (/^(GMT|UTC)/.test(tzName[0].value)) { offset = tzName[0].value.replace(/GMT|UTC/,'') || '+0'; return true; } }); // Format offset as ±HH:mm // Normalise minus sign as ASCII minus (charCode 45) let sign = offset[0] == '\x2b'? '\x2b' : '\x2d'; let [h, m] = offset.substring(1).split(':'); return sign + h.padStart(2, '0') + ':' + (m || '00'); } ['Asia/Kolkata','Australia/Sydney','America/New_York'].forEach( loc => console.log(loc + ': ' + getTimezoneOffset(loc)) );