为什么 momentjs 转换时区的方式错误?



>我有一个安排事件的表单。表单的一部分是设置事件开始时间。表单具有日期、时间和时区的选择字段。我将此信息与momentJS一起使用来构建一个名为eventTime的dateTime。如果所选的日期时间是过去的,则不应提交表单。所以我写了一些简单的逻辑,说:

timeDiff = moment(eventTime).diff(currentTime).

如果timeDiff小于零,则不提交。(更多内容见下文(这很好,但我遇到了时区问题。所以这就是我要做的:

如果我目前居住在美国东部标准时间并且是下午 2:00,那么如果在给定日期选择美国东部标准时间 1:45,我的表格不应提交。但是,如果我将"时区"下拉列表更改为"中部时间",那么它应该提交。假设我没有想错

1:45 CST = 2:45 EST

因此,由于目前是 2:00 CST,因此表单应该提交,但 momentJS 正在走向另一种方式,它认为时间是 1:45 EST。 根据下面的时刻对象(UTC 时间(,我希望Thu Jun 25 2020 10: 45: 00 GMT"中心区域时刻对象",而不是Thu Jun 25 2020 08: 45: 00 GMT我错过了什么。

谢谢

let date = "2020-06-25";
let time = "13:45";
let timezoneEST = "America/New_York";
let timezoneCST = "America/Chicago";
let currentTime = moment().tz(moment.tz.guess());
let eventTimeEST = moment.tz(moment(date).set({ "hour": time.substring(0, 2), "minute": time.substring(3, 5) }), timezoneEST);
let eventTimeCST = moment.tz(moment(date).set({ "hour": time.substring(0, 2), "minute": time.substring(3, 5) }), timezoneCST);
timeDiff = moment([eventTimeEST or eventTimeCST]).diff(currentTime)
if (timeDiff > 0) {
// allow submit
}

console.log(eventTimeEST)
// Eastern Zone Moment Object
// {
//   _isAMomentObject: true
//   _d: Thu Jun 25 2020 09: 45: 00 GMT - 0400(Eastern Daylight Time)
//   _i: Thu Jun 25 2020 00: 00: 00 GMT - 0400(Eastern Daylight Time)
//   _isAMomentObject: true
//   _isUTC: true
//   _isValid: true
//   _locale: Locale { _calendar: { … }, _longDateFormat: { … }, _invalidDate: "Invalid date", _dayOfMonthOrdinalParse: /d{1,2}(th|st|nd|rd)/, ordinal: ƒ, … }
//   _offset: -240
//   _pf: { empty: false, unusedTokens: Array(0), unusedInput: Array(0), overflow: -2, charsLeftOver: 0, … }
//   _z: Zone { name: "America/New_York", abbrs: Array(236), untils: Array(236), offsets: Array(236), population: 21000000 }
// }
console.log(eventTimeCST)
// Central Zone Moment Object
// {
//   _isAMomentObject: true
//   _d: Thu Jun 25 2020 08: 45: 00 GMT - 0400(Eastern Daylight Time)
//   _i: Thu Jun 25 2020 00: 00: 00 GMT - 0400(Eastern Daylight Time)
//   _isAMomentObject: true
//   _isUTC: true
//   _isValid: true
//   _locale: Locale { _calendar: { … }, _longDateFormat: { … }, _invalidDate: "Invalid date", _dayOfMonthOrdinalParse: /d{1,2}(th|st|nd|rd)/, ordinal: ƒ, … }
//   _offset: -240
//   _pf: { empty: false, unusedTokens: Array(0), unusedInput: Array(0), overflow: -2, charsLeftOver: 0, … }
//   _z: Zone { name: "America/New_York", abbrs: Array(236), untils: Array(236), offsets: Array(236), population: 21000000 }
// }
console.log(currentTime)
// Current Time(EST) Moment Object
// {
//   _d: Thu Jun 25 2020 09: 00:  GMT - 0400(Eastern Daylight Time)
//   _isAMomentObject: true
//   _isUTC: true
//   _isValid: true
//   _locale: Locale { _calendar: { … }, _longDateFormat: { … }, _invalidDate: "Invalid date", _dayOfMonthOrdinalParse: /d{1,2}(th|st|nd|rd)/, ordinal: ƒ, … }
//   _offset: -240
//   _pf: { empty: false, unusedTokens: Array(0), unusedInput: Array(0), overflow: -2, charsLeftOver: 0, … }
//   _z: Zone { name: "America/New_York", abbrs: Array(236), untils: Array(236), offsets: Array(236), population: 21000000 }
//   __proto__: Object
// }

let currentTime = moment().tz(moment.tz.guess());
let eventTimeEST = moment.tz(moment(date).set({ "hour": time.substring(0, 2), "minute": time.substring(3, 5) }), timezoneEST);
let eventTimeCST = moment.tz(moment(date).set({ "hour": time.substring(0, 2), "minute": time.substring(3, 5) }), timezoneCST);

此代码基本上是在当前 TZ 中设置日期,然后将其转换为另一个时区(美国/纽约-美国/芝加哥(。

第二条语句基本上是做EDT到EDT。

第三条声明是将EDT执行到CDT。

这就是为什么它回到一个小时前。因为美国东部时间下午 1:45 是中部夏令时下午 12:45。

但你真正想做的是得到那个时区的时间。

例如,美国中部时间下午 1:45。

您这样做的方法是基本上在该时区设置时间。

let date = "2020-06-25";
let timezoneEDT = "America/New_York";
let timezoneCDT = "America/Chicago";
let notBefore = { hour : 14, minute : 0 };
let clock = { hour : 13, minute : 45 };
let a = moment(date).tz(timezoneEDT).set(notBefore); //14:00 EDT
let b = moment(date).tz(timezoneCDT).set(clock); //13:45 CDT -> 14:45 EDT
let c = moment(date).tz(timezoneEDT).set(clock); //13:45 EDT
console.log(test(a, b)); //14:00 EDT against 14:45 EDT prints valid
console.log(test(a, c)); //13:45 EDT against 14:00 EDT prints invalid
function test(a,b){
return a.diff(b) > 0 ? 'Invalid date' : 'Valid date';
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.27.0/moment.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment-timezone/0.5.31/moment-timezone-with-data-2012-2022.js"></script>

正如预期的那样

let eventTimeCST = moment.tz(moment(date).set({ "hour": time.substring(0, 2), "minute": time.substring(3, 5) }), timezoneCST);

在我的时区 (EST( 中创建一个时刻对象,.tz调整该时区。我需要在CST时区创建一个新的时刻对象,将其与我的时区进行比较。

这可以像这样实现;

let eventTimeCST = moment.tz({'year': 2020, 'month': 06, 'day': 26, 'hour': 9, 'minute': 30}, timezoneCST)

所以我只是解析出datetime并构建了对象。

仅供参考,更换

{'year': 2020, 'month': 06, 'day': 26, 'hour': 9, 'minute': 30}

date + " " time

也有效,但抛出弃用警告

最新更新