Странное поведение new Date(Date.UTC(...)) при конвертации даты из универсальное глобальное время в пользовательскую местное время
У меня есть временная метка, полученная с сервера, похожего на 2019-02-01 14:28:16, и я пытаюсь безопасно преобразовать эту временную метку в местное время пользователей, чтобы избежать ошибки Недействительная дата.
Но, что удивительно, он преобразует 1 февраля в 5 февраля. Вот сценарий:
const myDate = new Date('2019-02-01 14:28:16');
console.info('Step 1: MyDate: ' + myDate.toString());
const utcFormateOfMyDate = Date.UTC(
myDate.getFullYear(),
myDate.getMonth(),
myDate.getDay(),
myDate.getHours(),
myDate.getMinutes(),
myDate.getSeconds(),
myDate.getMilliseconds()
);
console.info('Step 2: utcFormateOfMyDate: ' + utcFormateOfMyDate.toString()); // 1549376896000
console.info('Step 3.1 => ' + new Date(utcFormateOfMyDate)); // Tue Feb 05 2019 19:28:16 GMT+0500 (Pakistan Standard Time
console.info('Step 3.2 => ' + Date(utcFormateOfMyDate)); // Fri Feb 01 2019 19:43:36 GMT+0500 (Pakistan Standard Time)
Единственное изменение, которое я сделал, просто добавил ключевое слово новый, а преобразованная отметка времени перескочила с 1 февраля на 5 февраля (в будущем); обратитесь к скриншоту
Хотя удаление нового ключевого слова решило проблему, но я не смог найти объяснение этому магическому эффекту. Может ли кто-нибудь помочь мне понять это поведение?
Я получаю дату в нескольких форматах; даже Invalid Dates, поэтому в целях безопасности я сделал преобразование в обход плохих форматов. Но я обнаруживаю это волшебное поведение с new и без ключевого слова ~new~
Проблема в том, что вы звоните getDay() вместо getDate().
Для Date.UTC(utcFormatOfMyDate) это выглядит так, как будто функция просто полностью игнорирует значение года вне допустимого диапазона.
удивительно, ты прав
getDay() означает «день недели» — я часто делаю эту ошибку :)
@Pointy Я думаю, что мы все это делаем. Я не могу вспомнить время, когда мне приходилось выводить день из объекта Date, и меня не смущал этот метод...
Во-первых, вам не следует делать new Date('2019-02-01 14:28:16'); - неясно, является ли это местным временем или UTC, и разные браузеры (версии) ведут себя по-разному. Вместо этого используйте явный new Date('2019-02-01T14:28:16Z'); и не беспокойтесь о каких-либо «конверсиях».
@Bergi хороший момент, но отметка времени не в моей власти; Я получаю разные форматы, такие как (системные мельницы, строка, '2019-02-01T14:28:16Z', даже недопустимые даты :)) проблема была getDay() вместо getDate() в преобразовании UTC



![Безумие обратных вызовов в javascript [JS]](https://i.imgur.com/WsjO6zJb.png)


Как отмечалось в комментариях, проблема заключается в том, что вы сравниваете яблоки и апельсины, случайно передавая значение Date.getDay (вместо Date.getDate) на Date.UTC. и сравнение результата с выходными данными прямого анализа метки времени. Тем не менее, вы не должны полагаться на new Date() или Date() для анализа временной метки, так как реализации браузеров различаются, и вы можете получить противоречивые результаты.
Вместо этого вы можете сделать что-то вроде следующего с форматом метки времени, который вы получаете от сервера:
const timestamp = '2019-02-01 14:28:16';
const [y, m, d, hh, mm, ss] = timestamp.match(/\d+/g);
const date = new Date(Date.UTC(y, m - 1, d, hh, mm, ss));
console.info(JSON.stringify(date));
// date as UTC string
console.info(date.toUTCString());
// date as local string
console.info(date.toString());
Нет необходимости «конвертировать» дату. Внутри это всегда UTC.