【问题标题】:MomentJS, how to ignore user's local timezone, and useMomentJS,如何忽略用户的本地时区,并使用
【发布时间】:2020-04-27 04:03:32
【问题描述】:

这是场景:

1- 用户打开网站,并使用下拉字段输入上午 07:00,这将给我这个:

// 1578600000000 => 保存到数据库 // 2020 年 1 月 10 日星期五 07:00:00 GMT+1100(澳大利亚东部夏令时间)

用户本人在悉尼,这意味着他的本地时钟在GMT+1100

不过,他希望这次代表亚洲/德黑兰时间,因为那是他明天要去的地方。所以本质上,他希望我完全忽略他的当地时间,并把他看作是在亚洲/德黑兰。所以当他明天在Tehran 时,他可以看到他的日历有07:00am

另一方面,全世界的人都会看到他的空闲时间,比如说来自Australia/Perth

根据momentJS 文档,我认为类似下面的工作,但事实并非如此。

首先,将时区转换为Asia/Tehran,这是用户想要的地方:

const desiredTimeZone = 'Asia/Tehran';
let OriginalDesired = moment.tz(1578600000000,desiredTimeZone);

然后,当向Australia/Perth 中的人表示它时,请确保它在他们的时区中

const PerthTimeZone = 'Australia/Perth`; // this is dynamic, can be anything

OriginalDesired.clone().tz(PerthTimeZone);

我天真地认为这应该可行。但我注意到原始时间戳1578600000000UTC 时间戳,这意味着它不是真正的07:00am,它实际上是20:00pm,因为Javascript
已从用户条目中减去 11 小时,这是原始用户本地时区的偏移量。

我设法通过以一种戏剧性的方式添加和减去偏移量来解决它,但它只适用于一种情况。

const originalTime = 1578600000000;
const LocalAdjustment = moment(originalTime).tz("Australia/Sydney").utcOffset() * 60000;

const DesiredAdjustment = moment(originalTime).tz("Asia/Tehran").utcOffset() * 60000;
const newUTC = originalTime + LocalAdjustment - DesiredAdjustment;

当向Tehran中的用户表示这个时

  moment(newUTC).tz("Asia/Tehran").format('hh:mma'); // 07:00am.

我知道这可能很愚蠢,而且显然只在一种情况下有效,但这是我要走的正确道路吗?还是有更简单的方法?

顺便说一句,所有的计算都在我的服务器上,即“UTC”。

【问题讨论】:

  • 第一个示例的值是存储在数据库中的 1578600000000 还是 1578600000000 + 11 小时? momentjs 以 UTC 存储和操作,并且您希望存储 与当前 UTC 时间的偏移量。尝试使用 OriginalDesired.utcOffset(yourTzOffset, true) 更改内部 UTC 表示以匹配您所需的时区。

标签: javascript timezone momentjs timezone-offset


【解决方案1】:

你说:

1- 用户打开网站,并使用下拉字段输入上午 07:00,这将给我这个:// 1578600000000 ...

你已经输了。如果本地时区不相关,则不要编写假定它的代码。

换句话说,你可能有一些类似的东西:

moment("2020-01-10 07:00")

相反,你应该有类似的东西:

moment.tz("2020-01-10 07:00", "Asia/Tehran")

或者更确切地说,您应该简单地将 "2020-01-10 07:00""Asia/Tehran" 发送到您的数据库,然后在您需要知道代表什么时刻时检索它们并将它们传递到时刻时区。

至于您的其他方法,从时间戳中添加或减去时区偏移通常不是一个好主意。 Unix 时间戳本质上是基于 UTC 的。添加或减去将产生不同的时间点,而不是针对时区进行调整。

考虑到代码返回的偏移量不正确的可能性很小(但并非不可能),因为它们必须在被查找之前被移动。换句话说,德黑兰在相关日期是 UTC+3:30,因此传递的时间戳必须在传递给时刻构造函数之前 调整 3 小时 3 分钟。这导致了循环逻辑,并且难以解决。它将显示转换附近的时间戳(对于 DST 或特定时区标准时间的更改)。

【讨论】:

  • 非常感谢,我成功地完成了这项工作,而无需将整个代码库从时间戳移动到其他选项。不幸的是,我决定在 UI 代码中使用 date-fns,与 Moment.js 相比,它一开始看起来更好,但是,当涉及到 timeZones 时,date-fns 远不是一个可靠的选择。 MomentJS 处理 timzone 转换的方式更简单、更可靠。再次感谢
  • 在旁注中,我现在将实际日期保存为字符串以及数据库中的时间戳,并且在进行查询时,我总是根据当前用户的时区即时调整它们到我的数据库。虽然我会越来越多地阅读以了解,但您认为这有问题吗? DTS 会很快成为问题吗?
  • 哪个数据库?大多数都有正确的日期和时间类型。避免存储为字符串。此外,时刻处于维护模式。你可以试试date-fns-tzLuxon
猜你喜欢
  • 1970-01-01
  • 2019-09-13
  • 2020-08-28
  • 1970-01-01
  • 2012-10-30
  • 1970-01-01
  • 2022-12-16
  • 2018-01-27
  • 2016-12-23
相关资源
最近更新 更多