Angular 中的日期时区

问题描述

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

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

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

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

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

解决方法

我终于找到了解决方案。

我使用 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,17:19:51 PM GMT+9") 我得到最后一部分 (GMT+9),如下所示:

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

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

现在,由于一些国家/地区没有标准的时区缩写(如 AST),我们需要在创建 Date 对象之前将 time zone abbreviations 映射到 UTC(因为 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 构造函数。

警告

There's no consensus on timezone abbreviations 并且可能会有所不同(他们使用 CLDR format)。还有一些令人困惑的数据,如重复的缩写:

缩写 姓名 UTC 偏移量
AST 阿拉伯标准时间 UTC+03
AST 大西洋标准时间 UTC−04
SST 萨摩亚标准时间 UTC−11
SST 新加坡标准时间 UTC+08