Самый простой способ конвертировать UTC в новозеландскую дату (учитывая летнее время)? - PullRequest
0 голосов
/ 31 августа 2018

У меня есть следующая функция, которую я написал для преобразования 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).

Моя первая попытка состояла в том, чтобы просто вычислить, было ли это между последним воскресеньем сентября или первым воскресеньем апреля, но потом я понял, что во второй раз я использую конструктор new Date() где-нибудь в коде, в котором он собирается создать относительную дату к их системному времени и сломать математику.

TL; DR. Конвертировать UTC в миллисекунды с начала Новой Зеландии, что соответствует настройкам перехода на летнее время в Новой Зеландии.

РЕДАКТИРОВАТЬ: также не заинтересованы в использовании Moment или любой другой библиотеки для решения этой проблемы из-за размера пакета.

1 Ответ

0 голосов
/ 03 сентября 2018

Решил, попытался сделать его максимально читабельным для человека, в основном пытается добавить 12 или 13 в зависимости от того, где находится текущий UTC DateTime, если, добавляя 12 или 13, мы попадаем в следующий период перехода на летнее время и добавляем альтернативный вместо.... То есть, если при добавлении 12 мы попадаем на территорию +13 .... вместо этого добавляем +13. То есть, если, добавив +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.
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...