Неправильный расчет даты в Javascript при переходе на летнее время - PullRequest
0 голосов
/ 02 октября 2019

Я делаю следующие вычисления в JavaScript три дня подряд.

Полученные даты различаются в день, когда «дневной свет» вступает в силу в Мельбурне (2019-10-06). Первое и третье правильно показывают дату, когда второе показывает дату как 5 октября.

Может кто-то, пожалуйста, пролить свет на то, где это идет не так.

var apiRes = "2019-10-05";
var tempDate = Date.parse(apiRes);
var dApiRes = new Date(apiRes);
console.log(dApiRes.getTimezoneOffset()); 
tempDate = tempDate + (dApiRes.getTimezoneOffset() * 60000);
var d = new Date(0)
d.setUTCMilliseconds(tempDate);
console.log(d);

var apiRes = "2019-10-06";
var tempDate = Date.parse(apiRes);
var dApiRes = new Date(apiRes);
console.log(dApiRes.getTimezoneOffset()); 
tempDate = tempDate + (dApiRes.getTimezoneOffset() * 60000);
var d = new Date(0)
d.setUTCMilliseconds(tempDate);
console.log(d);

var apiRes = "2019-10-07";
var tempDate = Date.parse(apiRes);
var dApiRes = new Date(apiRes);
console.log(dApiRes.getTimezoneOffset()); 
tempDate = tempDate + (dApiRes.getTimezoneOffset() * 60000);
var d = new Date(0)
d.setUTCMilliseconds(tempDate);
console.log(d);

Ответы [ 2 ]

1 голос
/ 02 октября 2019

Для объяснения проблемы: дата «2019-10-06» - 2019-10-06:T00:00:00Z - что составляет 2019-10-06:11:00:00UTC+11, поскольку к моменту достижения 2019-10-06:T00:00:00Z Летнее время опустилось ниже.

Поэтому вы вычитаете 11 часов, когда вы «учитываете» часовой пояс, а не 10

Но, поскольку в 11:00 в Мельбурне прошло всего 10 часов в день, ваша скорректированная дата становится 2019-10-05:23:00:00UTC+10

Если ваша цель - получить полночь, используя только строку ГГГГ-ММ-ДД, вы можете сделать это несколькими способами.

В UTC и часовых поясах ВОСТОК UTC, просто

d.setHours(0,0);

(вам нужен второй 0 для нечетных часовых поясов, таких как Аделаида)

В часовых поясах к западу от UTC вам потребуется

d.setDate(d.getDate() + 1)

Вы также можете проверить смещение часового поясадо и после того, как вы примените изменения и откорректируете их соответствующим образом - я не потрудился написать код, который

Но, на мой взгляд, самый простой и надежный метод, использующий только методы, указанные в конструкторе Date (то есть "гарантированно" работать кросс-окружающая среда), выглядит следующим образом

Это выглядит немного странно, но знание локального смещения часового пояса совсем не требуется

var apiRes = "2019-10-05";
var d = new Date(...apiRes.split('-').map((n, i) => Number(n) - (i %2)));
console.log(d.toString());

var apiRes = "2019-10-06";
var d = new Date(...apiRes.split('-').map((n, i) => Number(n) - (i %2)));
console.log(d.toString());

var apiRes = "2019-10-07";
var d = new Date(...apiRes.split('-').map((n, i) => Number(n) - (i %2)));
console.log(d.toString());

Объясняя ...apiRes.split('-').map((n, i) => Number(n) - (i %2))

apiRes.split('-') // results in ["2019", "10", "06"]

так что теперь у нас есть ...["2019", "10", "06"].map((n, i) => Number(n) - (i %2))

следующий шаг

.map(n, i) => Number(n) - (i %2))

преобразует каждый элемент в число и вычитает 1, когда индекс равен 1, т. Е. Вычитает единицу за месяц, потому что в конструкторе он равен нулю

теперь мы имеем:

new Date(...[2019, 9, 6])

, что в ES6 +это как

new Date(2019, 9, 6)

, который будет строить дату в полночь на данный год / м / д

1 голос
/ 02 октября 2019

Я обычно использую 12 часов, чтобы не столкнуться с этим - возможно, нам нужно 15:00, чтобы быть уверенным

var apiRes = "2019-10-05 15:00:00";
var tempDate = Date.parse(apiRes);
var dApiRes = new Date(apiRes);
console.log(dApiRes.getTimezoneOffset()); 
tempDate = tempDate + (dApiRes.getTimezoneOffset() * 60000);
var d = new Date(0)
d.setUTCMilliseconds(tempDate);
console.log(d.toString());

var apiRes = "2019-10-06 15:00:00";
var tempDate = Date.parse(apiRes);
var dApiRes = new Date(apiRes);
console.log(dApiRes.getTimezoneOffset()); 
tempDate = tempDate + (dApiRes.getTimezoneOffset() * 60000);
var d = new Date(0)
d.setUTCMilliseconds(tempDate);
console.log(d.toString());

var apiRes = "2019-10-07 15:00:00";
var tempDate = Date.parse(apiRes);
var dApiRes = new Date(apiRes);
console.log(dApiRes.getTimezoneOffset()); 
tempDate = tempDate + (dApiRes.getTimezoneOffset() * 60000);
var d = new Date(0)
d.setUTCMilliseconds(tempDate);
console.log(d.toString());

var apiRes = "2019-10-27 15:00:00"; // EU DST ends
var tempDate = Date.parse(apiRes);
var dApiRes = new Date(apiRes);
console.log(dApiRes.getTimezoneOffset()); 
tempDate = tempDate + (dApiRes.getTimezoneOffset() * 60000);
var d = new Date(0)
d.setUTCMilliseconds(tempDate);
console.log(d.toString());
...