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

时间:2018-08-31 00:27:28

标签: 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())
)

但是,它包含一个与新西兰的夏时制时间无关的魔术数字(+12或+13)。

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

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

TL; DR从时代开始将UTC毫秒转换为与新西兰夏令时设置兼容的新西兰时间。

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

1 个答案:

答案 0 :(得分:0)

解决了这个问题,尝试使其尽可能地易于阅读,基本上尝试根据当前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.