创建一个特定时区的日期对象,并在JavaScript中将其转换为UTC



我的应用程序当前以以下格式存储特定事件的日期和时间:

date: 2022-05-06
time: 00:00 // (12:00 AM)

每个事件的时间还包含与之关联的TimeZone。如果组织活动的人来自新加坡,那么时区亚洲/新加坡.

当我向与会者发送此事件的日历邀请时,我希望以UTC时间发送,以便在接收者端,它将在他们的时区。(注意:我使用ics包来创建日历事件)。

所以,我想要的是在新加坡时区(根据上面的例子)中创建一个具有time = 2022-05-06 00:00的日期对象,然后将其转换为UTC,这应该给出2022-05-05 16:00(因为亚洲/新加坡是UTC+8)。我怎样才能做到这一点呢?

提前感谢。

一种可能的方法必须建立在一些先决条件之上

  • 传递的日期-时间字符串需要是一个可解析的字符串,它代表目标时区的本地日期,因此它不包括可解析的时区偏移数据。
  • 时区以符合IANA时区数据库的名称提供。

则实现如下

  • 从可解析的日期代表(数字或字符串值)创建Date实例。

    • 注意…这个日期对象已经携带了自己的时区偏移量,这是由脚本运行的客户端/环境决定的。
  • 为了生成以后易于解析的符合utc的自定义字符串格式,该方法利用了ECMAScript国际化API的Intl.DateTimeFormatformat方法。

    • 注意options参数的配置设置的唯一目标是返回自定义的UTC日期时间字符串格式,这样可以很容易地解析日期时区偏移(不是提供的时区名称,而是以'+hh:mm'形式的数值)。or'-hh:mm')
  • 时区偏移的小时和分钟是通过正则表达式检索的…/([+-]d{2}):(d{2})$/它匹配字符串末尾的模式,并捕获offsetHoursoffsetMinutes子字符串。

  • 两个字符串值都被解析为基于分钟的总数值。

  • 现在提供的时区名称相对于date对象的本地/客户端时间的分钟偏移量需要通过date对象自己的时区偏移量

    进行补偿
  • 最后一步是创建一个新的日期,并根据所提供的时区名称与UTC的时区偏移量进行校正,这是以毫秒为单位,通过日期的getTime值和前分钟为单位,以毫秒为单位。

    • 现在可以选择将日期返回为toUTCString或通过Intl.DateTimeFormat.format再次返回为自定义UTC符合字符串,其中可以选择例如'lt'(立陶宛语)作为locales字符串参数,因为立陶宛语支持日期格式'YYYY-MM-DD'

function createCustomUTCDateStringFromLocalDateAndTimeZoneName(
parsableDateWithoutTimeZoneOffset,
ianaTimeZoneName,
) {
const formatConfig = {
year: 'numeric',
month: '2-digit',
day: '2-digit',
hour12: false,
hour: '2-digit',
minute: '2-digit',
timeZone: 'UTC',
};
const date = new Date(parsableDateWithoutTimeZoneOffset);
const format = new Intl.DateTimeFormat('en', {
...formatConfig,
weekday: 'short',
month: 'long',
second: '2-digit',
timeZone: ianaTimeZoneName,
timeZoneName: 'longOffset',
}).format(date);
let [_, offsetHours = 0, offsetMinutes = 0] = format
.match(/([+-]d{2}):(d{2})$/) ?? [];
offsetMinutes = (parseInt(offsetHours, 10) * 60)
+ parseInt(offsetMinutes, 10)
+ date.getTimezoneOffset();
// return new Date(
//   date.getTime() - (offsetMinutes * 60000)
// )
// .toUTCString();
return new Intl.DateTimeFormat('lt', formatConfig)
.format(date.getTime() - (offsetMinutes * 60000));
}
console.log(`createCustomUTCDateStringFromLocalDateAndTimeZoneName(
'2022-05-06T00:00', 'Asia/Singapore'
) ...`, createCustomUTCDateStringFromLocalDateAndTimeZoneName(
'2022-05-06T00:00', 'Asia/Singapore'
));
console.log(`createCustomUTCDateStringFromLocalDateAndTimeZoneName(
'2022-05-06T00:00', 'Asia/Kabul'
) ...`, createCustomUTCDateStringFromLocalDateAndTimeZoneName(
'2022-05-06T00:00', 'Asia/Kabul'
));
console.log(`createCustomUTCDateStringFromLocalDateAndTimeZoneName(
'2022-05-06T00:00', 'Asia/Istanbul'
) ...`, createCustomUTCDateStringFromLocalDateAndTimeZoneName(
'2022-05-06T00:00', 'Asia/Istanbul'
));
console.log(`createCustomUTCDateStringFromLocalDateAndTimeZoneName(
'2022-05-06T00:00', 'Europe/Amsterdam'
) ...`, createCustomUTCDateStringFromLocalDateAndTimeZoneName(
'2022-05-06T00:00', 'Europe/Amsterdam'
));
console.log(`createCustomUTCDateStringFromLocalDateAndTimeZoneName(
'2022-05-06T00:00', 'UTC'
) ...`, createCustomUTCDateStringFromLocalDateAndTimeZoneName(
'2022-05-06T00:00', 'UTC'
));
console.log(`createCustomUTCDateStringFromLocalDateAndTimeZoneName(
'2022-05-06T00:00', 'America/Jamaica'
) ...`, createCustomUTCDateStringFromLocalDateAndTimeZoneName(
'2022-05-06T00:00', 'America/Jamaica'
));
console.log(`createCustomUTCDateStringFromLocalDateAndTimeZoneName(
'2022-05-06T00:00', 'America/Anchorage'
) ...`, createCustomUTCDateStringFromLocalDateAndTimeZoneName(
'2022-05-06T00:00', 'America/Anchorage'
));
console.log(`createCustomUTCDateStringFromLocalDateAndTimeZoneName(
'2022-05-06T00:00', 'Pacific/Marquesas'
) ...`, createCustomUTCDateStringFromLocalDateAndTimeZoneName(
'2022-05-06T00:00', 'Pacific/Marquesas'
));
console.log(`createCustomUTCDateStringFromLocalDateAndTimeZoneName(
'2022-05-06T00:00', 'Pacific/Honolulu'
) ...`, createCustomUTCDateStringFromLocalDateAndTimeZoneName(
'2022-05-06T00:00', 'Pacific/Honolulu'
));
console.log(`createCustomUTCDateStringFromLocalDateAndTimeZoneName(
'2022-05-06T00:00', 'Pacific/Chatham'
) ...`, createCustomUTCDateStringFromLocalDateAndTimeZoneName(
'2022-05-06T00:00', 'Pacific/Chatham'
));
.as-console-wrapper { min-height: 100%!important; top: 0; }

const date = new Date('2020-04-13T00:00:00.000Z').toLocaleString('en-SG').split('T')
console.log(date)

最新更新