MomentJS,如何忽略用户的本地时区并使用
MomentJS, how to ignore user's local timezone, and use
场景如下:
1- 用户打开网站,然后使用下拉字段输入 07:00,这将给我以下信息:
// 1578600000000 => 保存到数据库
// 2020 年 1 月 10 日星期五 07:00:00 GMT+1100(澳大利亚东部夏令时间)
用户本人在悉尼,这意味着他的本地时钟是GMT+1100
但是,他想将这个时间表示为 Asia/Tehran 时间,因为那是他明天要去的地方。所以本质上,他想让我完全忽略他的当地时间,把他看成是在Asia/Tehran。所以当他明天在 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);
我天真地认为这应该有效。但是我注意到原来的时间戳 1578600000000
是一个 UTC
时间戳,这意味着它不是真正的 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'。
你说:
1- User opens the website, and enters 07:00 am using a dropdown field, which will give me this : // 1578600000000 ...
你已经输了。如果本地时区不相关,则不要编写假定它是相关的代码。
换句话说,您可能有以下内容:
moment("2020-01-10 07:00")
相反,你应该有这样的东西:
moment.tz("2020-01-10 07:00", "Asia/Tehran")
或者更确切地说,您应该简单地将 "2020-01-10 07:00"
和 "Asia/Tehran"
发送到您的数据库,然后在您需要知道代表什么时刻时检索它们并将它们传递给 moment-timezone。
至于您的其他方法,从时间戳中添加或减去时区偏移通常不是一个好主意。 Unix 时间戳本质上是基于 UTC 的。添加或减去将产生不同的时刻,不调整时区。
考虑到您的代码返回的偏移量不正确的可能性很小(但并非不可能),因为在查找之前必须先移动它们。换句话说,德黑兰在相关日期处于 UTC+3:30,因此传递的时间戳必须在传递给 moment 构造函数之前 调整 3 小时 3 分钟。这导致循环逻辑,并且难以解决。它将显示接近转换的时间戳(无论是夏令时,还是特定时区标准时间的更改)。
场景如下:
1- 用户打开网站,然后使用下拉字段输入 07:00,这将给我以下信息:
// 1578600000000 => 保存到数据库 // 2020 年 1 月 10 日星期五 07:00:00 GMT+1100(澳大利亚东部夏令时间)
用户本人在悉尼,这意味着他的本地时钟是GMT+1100
但是,他想将这个时间表示为 Asia/Tehran 时间,因为那是他明天要去的地方。所以本质上,他想让我完全忽略他的当地时间,把他看成是在Asia/Tehran。所以当他明天在 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);
我天真地认为这应该有效。但是我注意到原来的时间戳 1578600000000
是一个 UTC
时间戳,这意味着它不是真正的 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'。
你说:
1- User opens the website, and enters 07:00 am using a dropdown field, which will give me this : // 1578600000000 ...
你已经输了。如果本地时区不相关,则不要编写假定它是相关的代码。
换句话说,您可能有以下内容:
moment("2020-01-10 07:00")
相反,你应该有这样的东西:
moment.tz("2020-01-10 07:00", "Asia/Tehran")
或者更确切地说,您应该简单地将 "2020-01-10 07:00"
和 "Asia/Tehran"
发送到您的数据库,然后在您需要知道代表什么时刻时检索它们并将它们传递给 moment-timezone。
至于您的其他方法,从时间戳中添加或减去时区偏移通常不是一个好主意。 Unix 时间戳本质上是基于 UTC 的。添加或减去将产生不同的时刻,不调整时区。
考虑到您的代码返回的偏移量不正确的可能性很小(但并非不可能),因为在查找之前必须先移动它们。换句话说,德黑兰在相关日期处于 UTC+3:30,因此传递的时间戳必须在传递给 moment 构造函数之前 调整 3 小时 3 分钟。这导致循环逻辑,并且难以解决。它将显示接近转换的时间戳(无论是夏令时,还是特定时区标准时间的更改)。