Date-fns возвращает неверную дату в сафари

Я использую date-fns для возврата некоторых значений, как показано ниже:

import { format, formatDistance } from "date-fns";

var date = new Date("2019-03-06 00:00:00");
console.info(format(new Date(date), "dd MMM, y"));

Он отлично работает в Chrome и возвращается We Mar, y

Но возвращает Invalid Date в Safari.

Я полагаю, это потому, что дата ("2019-03-06 00:00:00") не в формате ISO 8601. Но это формат, который я получаю от конечной точки. Есть ли возможность преобразовать это в правильный формат и заставить его работать в Safari?

Почему вы дважды анализируете дату?

T.J. Crowder 12.04.2019 17:46

Возможно: "2019-03-06 00:00:00".split(" ").join("T")

epascarello 12.04.2019 18:01
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
1
2
4 681
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Я вижу две проблемы:

  1. Вы полагаетесь на нестандартный формат ввода при первом анализе даты.

  2. Вы передаете Date конструктору Date, что заставляет его преобразовать дату в строку, а затем проанализировать строку.

Я бы проанализировал его только один раз и использовал стандартный формат даты/времени при вызове new Date в первый раз:

import { format, formatDistance } from "date-fns";

var date = new Date("2019-03-06T00:00:00");
// Note -----------------------^
console.info(format(date, "dd MMM, y"));
// No `new Date`   ^

Обратите внимание, что ваша строка будет проанализирована как местное время (в движках JavaScript, соответствующих спецификациям¹), поскольку она включает в себя временную часть строки. К сожалению, это изменилось после того, как формат был добавлен в ES2015, обновлен в ES2016, но где он закончился:

When the UTC offset representation is absent, date-only forms are interpreted as a UTC time and date-time forms are interpreted as a local time.

Поскольку ваша строка не имеет смещения UTC (без Z или +00:00 или подобных) и имеет время, она анализируется по местному времени. (Опять же, на движках JavaScript, соответствующих спецификациям¹).

Я рекомендую либо не анализировать строки даты с помощью встроенного объекта Date, либо убедиться, что у вас всегда есть индикатор часового пояса в строке, если вы это делаете.


¹ РобГ указал, что Safari анализирует new Date("2019-03-06T00:00:00") как UTC. К сожалению, это Жук в JavaScriptCore, движке JavaScript от Apple. Это влияет не только на Safari, но и на Chrome на iOS (и, возможно, на любой другой браузер iOS; я тестировал Brave, Opera и Dolphin), поскольку Chrome должен использовать JavaScriptCore вместо своего обычного V8 на iOS, потому что приложения не могут выделять исполняемую память, поэтому механизмы JIT нельзя использовать на iOS. Но команда V8 сделала версия V8 только для интерпретатора, поэтому, возможно, Chrome (и Brave) на iOS будет обновлен, чтобы использовать его, если он будет достаточно быстрым.

Есть ли способ преобразовать "2019-03-06 00:00:00" в "2019-03-06T00:00:00", поскольку я не контролирую то, что получаю от API?

user1012181 12.04.2019 17:51

@ user1012181 - Замена строки: theDate = theDate.replace(/ /g, "T");. Вы захотите проверить, предназначено ли то, что предоставляет вам API, для UTC или местного времени. Если это UTC, добавьте Z в конце: theDate = theDate.replace(/ /g, "T") + "Z";.

T.J. Crowder 12.04.2019 17:53

Спасибо, я проверю это

user1012181 12.04.2019 17:54

"… анализируется по местному времени.". Нет, синтаксический анализатор Safari не работает, new Date("2019-03-06T00:00:00") анализируется как UTC. :-(

RobG 12.04.2019 22:55

@RobG - "(в браузерах, соответствующих спецификациям)" :-) (Но я вижу, что у меня этого нет в обоих местах.) Я удивлен, что Safari еще не соответствует спецификации, тьфу. Вот почему я не анализирую даты как строки без часового пояса.

T.J. Crowder 13.04.2019 09:48

@RobG - Тьфу, это еще хуже: это не Сафари как таковой (конечно), это JavaScriptCore, поэтому он влияет на Safari, а также на Chrome на iOS (поскольку Chrome должен использовать АО на iOS, потому что приложения не могут выделять исполняемую память -- но в какой-то момент они могут использовать вместо этого режим только интерпретатора V8). Раздражает В самом деле то, что формат, определяемый спецификацией не (mm/dd/yyyy HH:MM:SS), надежно анализируется как местное время для разных движков (и локалей, несмотря на то, что он специфичен для США): jsfiddle.net/tjcrowder/ojmh3fsv/2Вздох

T.J. Crowder 13.04.2019 11:34

Удивительно, но я не смог найти отчет об ошибке, поэтому я добавил один.

T.J. Crowder 13.04.2019 11:42

Система сообщений об ошибках Safari довольно удручающая. Я сообщил о некоторых ошибках несколько лет назад, насколько я знаю, они не исправлены. Начиная с ECMAScript 2015, при передаче объекта Date конструктор больше не выполняет операцию date -> string -> date, он просто принимает значение времени. :-) Я все еще люблю использовать new Date(+date).

RobG 13.04.2019 23:25

Простым ответом на это может быть преобразование даты в отметку времени и значение и передача ее в format

import { format, formatDistance } from "date-fns";

var date = new Date("2019-03-06").getTime();
console.info(format(new Date(date), "dd MMM, y"));

Другие вопросы по теме