将 UTC 转换为新西兰日期的最简单方法(考虑夏令时)?



我有以下函数,我编写了以下函数,用于将msSinceEpoch转换为新西兰日期(IE11兼容(...

const MAGICNUMBER = 13;
const toNewZealand = (msSinceEpoch) => {
const [day, month, year, time] = new Date(msSinceEpoch).toLocaleString("en-NZ", {
hour12: false, timeZone: "UTC"
}).split(/[/,]/); // timeZone UTC is the only format support on IE11
const [hours, minutes, seconds] = time.trim().split(":");
return new Date(~~year, ~~month - 1, ~~day, ~~hours + MAGICNUMBER, ~~minutes, ~~seconds)
};
// usage....
console.log(
toNewZealand(new Date().getTime())
)

但是,这包含一个与新西兰夏令时(+12或+13(无关的幻数。

所以这里变得复杂了,我如何获得相对于新西兰夏令时的正确数字(+12 或 +13(。

我最初的尝试只是计算它是在 9 月的最后一个星期日还是 4 月的第一个星期日之间,但后来我意识到,当我在代码中的任何位置使用new Date()构造函数时,它将创建一个相对于其系统时间的日期并破坏数学。

TL;DR 将 UTC 自纪元以来的毫秒数转换为新西兰时间,适用于新西兰的夏令时设置。

编辑:由于捆绑包大小成本,对使用Moment或任何其他库来解决此问题也不感兴趣。

TL;DR 转换 UTC 自纪元到新西兰时间的毫秒数...

我认为OP对什么是时间转换有误解。MS 自纪元以来始终采用 UTC。时间对话会更改时间的显示格式,不应更改msSinceEpoch

您可以使用toLocalString()并传递所需的时区(太平洋/奥克兰(来转换DateTime的显示格式:

const date = new Date();
console.log(
date.toLocaleString('en-NZ', {
timeZone: 'Pacific/Auckland',
}),
);

解决了它,试图使其尽可能人性化,基本上尝试根据当前 UTC DateTime 的位置添加 12 或 13,如果通过添加 12 或 13,我们进入下一个夏令时,我们添加替代...... IE 如果通过添加 12 我们落入 +13 区域....改为添加 +13。 IE 如果通过添加 +13,我们属于 +12 区域....改为添加 +12。

新西兰的夏令时在 9 月的最后一个星期日和 4 月的第一个星期日发生变化。

这就是解决方案。

const UTCFromMS = (ms) => {
return new Date(new Date(ms).toUTCString().replace(" GMT", ""))
};
const addHours = (dte, hrs) => {
return new Date(
dte.getFullYear(),
dte.getMonth(),
dte.getDate(),
dte.getHours() + hrs,
dte.getMinutes(),
dte.getMilliseconds()
);
};
const toNewZealand = (ms) => {
return addNewZealandDaylightSavings(UTCFromMS(ms));
};
const getPreviousSunday = (dte) => {
return new Date(
dte.getFullYear(),
dte.getMonth(),
dte.getDate() - dte.getDay(),
1,
0,
0
);
};
const getNextSunday = (dte) => {
return new Date(
dte.getFullYear(),
dte.getMonth(),
dte.getDay() === 0 ? dte.getDate() : dte.getDate() + (7 - dte.getDay()),
1,
0,
0
)
};
const standardHours = 12;
const daylightHours = 13;
const addNewZealandDaylightSavings = (dte) => {
const lastSundaySeptember = getPreviousSunday(
new Date(dte.getFullYear(), 8, 30)
);
const firstSundayApril = getNextSunday(
new Date(dte.getFullYear(), 3, 1)
);
// If its before firstSundayApril, add 13, if we went over 1am, add 12.
if(dte <= firstSundayApril) {
const daylightNz = addHours(dte, daylightHours);
if(daylightNz >= firstSundayApril) {
return addHours(dte, standardHours);
}
return daylightNz
}
// if its before lastSundaySeptember, add 12 if we went over 1am add 13.
if(dte <= lastSundaySeptember) {
const standardNz = addHours(dte, standardHours);
if(standardNz >= lastSundaySeptember) {
return addHours(dte, daylightHours);
}
return standardNz;
}
return addHours(dte, daylightHours);
};
console.log(toNewZealand(new Date().getTime()).toString());
// the above line should always output the current DateTime in New Zealand, replace the argument with any epoch milliseconds and it should still always give you the correct time.

===编辑====

从那以后,上面的答案变得不那么相关了,因为现在有办法做到这一点,这是 Web 标准的一部分。

Date.prototype.toLocaleString AND timeZone: "Pacific/Auckland">

是今天转换日期的最简单方法之一,您可以在此处阅读有关MDN的更多信息:

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/toLocaleString

相关内容

最新更新