2

在 Angular 应用程序中,我有一个表单,我希望用户能够在任何时区创建一个日期。用户输入:

  • 日期:20/09/2021
  • 小时:10:30
  • 时区(选择):Europe/Madrid

我所做的是将时区与其偏移量(Europe/Madrid-> +0200)之间的关系保存在本地文件中,然后使用字符串创建日期,如下所示new Date("2021-09-20T10:30:00+0200")

我的问题是计算夏季时间,现在我使用静态时区,但这是不现实的,因为有些国家/地区每年更改两次时区。我需要一个自动解决方案。

我一直在阅读有关momentmoment-timezone 的信息,但两者都是遗留项目,不鼓励使用它,所以我正在寻找不同的东西。谢谢你。

4

1 回答 1

0

最后我找到了解决方案。

我使用了 IANA 代码(例如)而不是静态时区偏移量,Asia/Kabul因此我可以实时计算其值(GMT+4:30-> +0430)。

1 - 从IANA区域标识符获取时区偏移量

我使用 Intl,一个本地浏览器类来格式化日期。例子:

new Intl.DateTimeFormat("en", {
  timeZone: "Pacific/Palau",
  day: "2-digit",
  month: "2-digit",
  year: "numeric",
  weekday: "long",
  hour: "2-digit",
  minute: "2-digit",
  hour12: false,
  second: "2-digit",
  timeZoneName: "short",
}).format(new Date());

("Thursday, 07/15/2021, 17:19:51 PM GMT+9");

有了这个我可以创建日期,但日期构造函数将使用本地时区偏移量并计算差异,因此所选时区的最终时间将不是指定的时间。

2 - 从字符串中获取时区

从 Intl 返回的日期字符串 ( "Thursday, 07/15/2021, 17:19:51 PM GMT+9") 我得到最后一部分 ( GMT+9),如下所示:

const dateSplit = dateStr.split(" ");
const timezoneAbbr = dateSplit[dateSplit.length - ONE];

3 - 将非标准时区缩写映射到其偏移量

现在,由于某些国家/地区没有标准的时区缩写(如AST),我们需要在创建对象之前将时区缩写映射到 UTC Date(因为Date构造函数对某些时区缩写返回错误)。我使用这样的枚举创建了这种关系:

export enum TimezoneAbbreviation {
  ACDT = '+1030',
  ACST = '+0930',
  ACT = '-0500',
  ADT = '-0300',

4 - 创建日期

yyyy/MM/dd hh:mm ZZ最后创建具有格式(例如:)的日期字符串2021/05/10 10:30 UTC-1并用它调用Date构造函数。

警告

时区缩写没有共识,可能会有所不同(它们使用CLDR 格式)。还有一些令人困惑的数据,例如重复的缩写:

缩写 姓名 UTC 偏移量
AST 阿拉伯标准时间 UTC+03
AST 大西洋标准时间 UTC-04
SST 萨摩亚标准时间 UTC-11
SST 新加坡标准时间 UTC+08
于 2021-07-16T15:07:29.067 回答