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

Sha*_*son 5 javascript date

我有以下函数,我已编写转换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())
)
Run Code Online (Sandbox Code Playgroud)

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

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

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

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

编辑:也不感兴趣使用Moment或任何其他库来解决此问题,因为捆绑大小成本.

Sha*_*son -1

解决了这个问题,尝试使其尽可能地保持人类可读性,基本上尝试根据当前 UTC 日期时间所在的位置添加 12 或 13,如果通过添加 12 或 13 我们陷入下一个夏令时,我们将添加备用时间。 .. IE 如果通过添加 12 我们落入 +13 区域.... 添加 +13 代替。IE 如果通过添加 +13 我们落入 +12 区域....添加 +12 代替。

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

这就是解决方案......

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.
Run Code Online (Sandbox Code Playgroud)

===编辑====

上面的答案已经变得不那么重要了,因为现在有一种方法可以做到这一点,这是网络标准的一部分。

Date.prototype.toLocaleString AND timeZone: "太平洋/奥克兰"

这是当今最简单的日期转换方法之一,您可以在 MDN 上阅读更多信息:

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