Я заметил странное поведение Date в Chrome (версия 74.0.3729.131 (официальная сборка) (64-разрядная версия)). Следующий javascript был выполнен в консоли Chrome Dev:
new Date('1894-01-01T00:00:00+01:00')
// result: Mon Jan 01 1894 00:00:00 GMT+0100 (Central European Standard Time)
new Date('1893-01-01T00:00:00+01:00')
// result: Sat Dec 31 1892 23:53:28 GMT+0053 (Central European Standard Time)
Я уже читал о нестандартном анализе даты через Date ctor в разных браузерах, хотя и предоставлял действительные значения ISO8601. Но это более чем странно о_о
В Firefox (Quantum 66.0.3 (64-разрядная версия)) те же вызовы приводят к ожидаемым объектам Date:
new Date('1894-01-01T00:00:00+01:00')
// result: > Date 1892-12-31T23:00:00.000Z
new Date('1893-01-01T00:00:00+01:00')
// result: > Date 1893-12-31T23:00:00.000Z
У меня есть Sun Jan 01 1893 01:02:04 GMT+0202 (Eastern European Standard Time) и Mon Jan 01 1894 01:02:04 GMT+0202 (Eastern European Standard Time). Похоже, что до 1925 года GMT был сдвинут или что-то в этом роде (потому что я получаю четкое смещение по Гринвичу только с 1925 года).
Ну, к вашему сведению, на моем ПК дата взлома 1924-05-01. Полагаю, Хром каким-то образом использует историческую информацию о времени (в 1924 году был первый хроносигнал из Гринвичской обсерватории, так что, возможно, это как-то повлияло на мировое время). Идея сумасшедшая, я знаю :D
Интересно: Chrome добавил некоторые изменения в синтаксический анализ даты в версии 67 из-за некоторых обновлений спецификации сценария ecma, касающихся смещений часового пояса: хром-обзор.googlesource.com/c/v8/v8/+/572148
Возможно релевантные stackoverflow.com/a/56121124/441757 и stackoverflow.com/a/14282490/441757
время такой беспорядок @_@



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


Это может быть тот случай, когда все браузеры следуют своим собственным стандартам кодирования форматов даты (но я не уверен в этом). В любом случае, это просто исправить, применив метод toISOString.
const today = new Date();
console.info(today.toISOString());хорошо, так что для отображения цели это будет делать. Но мне нужно проверить, будут ли вычисления корректно работать с форматом Chrome.
Будем надеяться, что вычисления будут работать нормально, поскольку каждый движок JavaScript преобразует даты в целые числа, а затем обрабатывает их, что приводит к единообразию. @cmxl
Хорошо, похоже, что этого поведения нельзя избежать, поэтому вам следует анализировать даты вручную. Но способ его разбора довольно прост.
Если мы разбираем дату в формате ISO 8601, маска строки даты выглядит так:
<yyyy>-<mm>-<dd>T<hh>:<mm>:<ss>(.<ms>)?(Z|(+|-)<hh>:<mm>)?
T в строке отделяет дату от времени. Итак, мы можем просто разделить строку ISO на T
var isoString = `2019-05-09T13:26:10.979Z`
var [dateString, timeString] = isoString.split("T")
Итак, у нас есть dateString == "2019-05-09". Теперь довольно просто получить эти параметры отдельно
var [year, month, date] = dateString.split("-").map(Number)
Со строкой времени мы должны совершать более сложные действия из-за ее изменчивости.
У нас есть timeString == "13:26:10Z"
Также возможно timeString == "13:26:10" и timeString == "13:26:10+01:00
var clearTimeString = timeString.split(/[Z+-]/)[0]
var [hours, minutes, seconds] = clearTimeString.split(":").map(Number)
var offset = 0 // we will store offset in minutes, but in negation of native JS Date getTimezoneOffset
if (timeString.includes("Z")) {
// then clearTimeString references the UTC time
offset = new Date().getTimezoneOffset() * -1
} else {
var clearOffset = timeString.split(/[+-]/)[1]
if (clearOffset) {
// then we have offset tail
var negation = timeString.includes("+") ? 1 : -1 // detecting is offset positive or negative
var [offsetHours, offsetMinutes] = clearOffset.split(":").map(Number)
offset = (offsetMinutes + offsetHours * 60) * negation
} // otherwise we do nothing because there is no offset marker
}
На данный момент у нас есть представление данных в числовом формате:year, month, date, hours, minutes, seconds и offset в минутах.
Да, мы не можем этого избежать, потому что это слишком круто. JS Date автоматически сопоставляет дату для всех отрицательных и слишком больших значений. Таким образом, мы можем просто передать все параметры в необработанном формате, и конструктор JS Date автоматически создаст для нас правильную дату!
new Date(year, month - 1, date, hours, minutes + offset, seconds)
Вуаля! Вот полностью рабочий пример.
function convertHistoricalDate(isoString) {
var [dateString, timeString] = isoString.split("T")
var [year, month, date] = dateString.split("-").map(Number)
var clearTimeString = timeString.split(/[Z+-]/)[0]
var [hours, minutes, seconds] = clearTimeString.split(":").map(Number)
var offset = 0 // we will store offset in minutes, but in negation of native JS Date getTimezoneOffset
if (timeString.includes("Z")) {
// then clearTimeString references the UTC time
offset = new Date().getTimezoneOffset() * -1
} else {
var clearOffset = timeString.split(/[+-]/)[1]
if (clearOffset) {
// then we have offset tail
var negation = timeString.includes("+") ? 1 : -1 // detecting is offset positive or negative
var [offsetHours, offsetMinutes] = clearOffset.split(":").map(Number)
offset = (offsetMinutes + offsetHours * 60) * negation
} // otherwise we do nothing because there is no offset marker
}
return new Date(year, month - 1, date, hours, minutes + offset, seconds)
}
var testDate1 = convertHistoricalDate("1894-01-01T00:00:00+01:00")
var testDate2 = convertHistoricalDate("1893-01-01T00:00:00+01:00")
var testDate3 = convertHistoricalDate("1894-01-01T00:00:00-01:00")
var testDate4 = convertHistoricalDate("1893-01-01T00:00:00-01:00")
console.info(testDate1.toLocaleDateString(), testDate1.toLocaleTimeString())
console.info(testDate2.toLocaleDateString(), testDate2.toLocaleTimeString())
console.info(testDate3.toLocaleDateString(), testDate3.toLocaleTimeString())
console.info(testDate4.toLocaleDateString(), testDate4.toLocaleTimeString())В этом случае мы получаем экземпляр Date со всеми его собственными значениями (например, .getHours()), равными нормализованный, включая смещение часового пояса. testDate1.toISOString все равно вернет странный результат. Но если вы работаете с этой датой, она, вероятно, на 100% удовлетворит ваши потребности.
Надеюсь, это помогло :)
Спасибо @Лимбо!
Может, в 1893 году были какие-то события, связанные со временем? (по запросу историков ИТТ)