我的场景是这样的:
我有一个接受用户输入的日期选择器,它假设选择的日期/时间是当地时间。我似乎无法改变这种行为。用户实际上应该选择欧洲/伦敦时间的日期/时间,因为他们当时正在伦敦预订服务。
假设他们预订了早上 5 点从伦敦出发的航班。
所以我有用户选择的这个日期(来自新西兰):
2019-08-01T05:00:00+12:00 (NZ time)
我需要将其更改为:
2019-08-01T05:00:00+01:00 (Europe/London time)
之后我将发送到服务器并存储为 UTC。
如果有帮助,我正在使用 momentjs。
编辑: 最新尝试: 我只需要弄清楚如何从用户输入的确切时间获取时区偏移量,这样我就可以使用夏令时了。 例如下面我得到了前一天的英国抵消,所以可能有 DST 问题
const moment = require('moment-timezone');
const nzd = '2019-08-01T05:00:00+12:00'; // This is the date my user entered via the datepicker
const ukTempString = moment(new Date(nzd.slice(0, -6))).tz('Europe/London').format('YYYY-MM-DDTHH:mm:ssZ'); // 2019-07-31T18:00:00+01:00
const ukOffset = ukTempString.substr(ukTempString.length - 6); // +01:00
const ukString = nzd.slice(0, -6) + ukOffset; // 2019-08-01T05:00:00+01:00
const ukDate = new Date(ukString); // I can then this to the backend
编辑:
当前解决方案:
英国没有 DST 例子:
let nzd = moment('2019-10-27T05:00:00+13:00'); // This is the date my user entered via the datepicker
let nzString = nzd.format('YYYY-MM-DDTHH:mm:ssZ');
let ukd = moment().tz('Europe/London');
ukd.set(nzd.toObject());
console.log(ukd.format('YYYY-MM-DDTHH:mm:ssZ')); // 2019-10-27T05:00:00+00:00
let ukDate = new Date(ukd.format('YYYY-MM-DDTHH:mm:ssZ')); // I can then this to the backend
console.log(ukDate.toUTCString()); // Sun, 27 Oct 2019 05:00:00 GMT
在英国示例中有 DST(相同代码):
nzd = moment('2019-10-27T00:30:00+13:00'); // This is the date my user entered via the datepicker
nzString = nzd.format('YYYY-MM-DDTHH:mm:ssZ');
ukd = moment().tz('Europe/London');
ukd.set(nzd.toObject());
console.log(ukd.format('YYYY-MM-DDTHH:mm:ssZ')); // 2019-10-27T00:30:00+01:00
ukDate = new Date(ukd.format('YYYY-MM-DDTHH:mm:ssZ')); // I can then this to the backend
console.log(ukDate.toUTCString()); // Sat, 26 Oct 2019 23:30:00 GMT
var nzd = '2019-08-01T05:00:00+12:00'
var ukd = nzd.slice(0, -6) + '+01:00'
console.log(ukd) // outputs 2019-08-01T05:00:00+01:00
const moment = require('moment-timezone')
var nz = moment('2019-08-01T05:00:00+12:00')
var uk = nz.tz('Europe/London').format()
console.log(uk) // outputs 2019-07-31T18:00:00+01:00
let ukd = "2019-10-27T01:59:00".split('T')
let finalDate = moment.tz(ukd[0] + "T" + ukd[1], "YYYY-MM-DDTHH:mm:ss", true, "Europe/London").tz('Europe/London').format('Z');
console.log(finalDate) // last minute still in DST, outputs +01:00
ukd = "2019-10-27T02:01:00".split('T')
finalDate = moment.tz(ukd[0] + "T" + ukd[1], "YYYY-MM-DDTHH:mm:ss", true, "Europe/London").tz('Europe/London').format('Z');
console.log(finalDate) // first minute after DST, outputs +00:00
这似乎是 hacky 和不干净的代码,但这是由于时区中的一个 bug 解析为 UTC 日期而不是时区日期。
这里有一个更简单的解决方案:
moment("2019-08-01T05:00:00+12:00")
.parseZone()
.tz("Europe/London", true)
.toISOString(true) // => "2019-08-01T05:00:00.000+01:00"
解释一下:
parseZone
撤消该转换,以便我们的日期根据原始字符串将自己视为 +12tz
将时间转换为伦敦时间,但使用 keepTime
的第二个参数(称为 true
),这意味着“与其保持时间相同并更改本地时间,不如更改现在的时间保持当地时间相同。keepOffset
)告诉它在显示之前不要转换为 UTC所以,这行得通,但也许最好将时间选择器更改为伦敦时间,以便他们选择的时间已经在您想要的区域?
编辑,等效的 Luxon 代码更易读,如果这有助于解释它:
DateTime.fromISO("2019-08-01T05:00:00+12:00", { setZone: true })
.setZone("Europe/London", { keepLocalTime: true} )
.toISO()
如何创建新的
Date
并将时区设置为 UTC,但值直接从原始 Date
传递,如下所示:
function changeTimezoneToUtc(date: Date): Date {
return new Date(Date.UTC(date.getFullYear(), date.getMonth(),
date.getDate(), date.getHours(),
date.getMinutes(), date.getSeconds(), date.getMilliseconds()));
}
以上是打字稿,当然可以省略类型。