Неверная дата в сафари


155
 alert(new Date('2010-11-29'));

chrome, ff не имеет проблем с этим, но сафари выкрикивает «недопустимая дата». Зачем ?

edit: хорошо, согласно комментариям ниже, я использовал разбор строк и попробовал это:

alert(new Date('11-29-2010')); //doesn't work in safari
alert(new Date('29-11-2010')); //doesn't work in safari
alert(new Date('2010-29-11')); //doesn't work in safari

edit 22 марта 2018 : Похоже, что люди все еще приземляются здесь - Сегодня я бы использовал momentили date-fnsи покончим с этим. Date-fns также очень безболезненный и легкий.


Просто для других, смотрящих на ту же проблему: я в конечном итоге использовал DateJS, который решил мою проблему в целом. См. Принятый ответ для деталей.
Shrinath

2
используйте moment.js для анализа метки времени. Особенно, когда имеешь дело с кроссплатформенной сетью
Ming Yuen

1
Это старый вопрос. Начиная с ECMAScript 2015 строки ISO 8601 только для даты обрабатываются как UTC. Тем не менее, могут существовать старые браузеры, которые либо вообще не будут анализировать его, либо будут рассматривать его как локальный.
RobG

Ответы:


167

Шаблон yyyy-MM-ddне является официально поддерживаемым форматом для Dateконструктора. Firefox, кажется, поддерживает это, но не рассчитывайте на то, что другие браузеры будут делать то же самое.

Вот некоторые поддерживаемые строки:

  • ММ-дд-гггг
  • дд гггг / ММ /
  • ММ / дд / гггг
  • ММММ дд, гггг
  • МММ дд, гггг

DateJS кажется хорошей библиотекой для анализа нестандартных форматов даты.

Изменить : только что проверил стандарт ECMA-262 . Цитата из раздела 15.9.1.15:

Дата Время Формат строки

ECMAScript определяет формат обмена строк для даты и времени на основе упрощения расширенного формата ISO 8601. Формат выглядит следующим образом: ГГГГ-ММ-ДДЧЧ: мм: сс.сссZ Где следующие поля:

  • YYYY - десятичные цифры года в григорианском календаре.
  • «-» (гифон) появляется буквально дважды в строке.
  • MM - месяц года с 01 (январь) до 12 (декабрь).
  • ДД это день месяца с 01 по 31.
  • Буква «Т» появляется буквально в строке, чтобы указать начало элемента времени.
  • ЧЧ - количество полных часов, прошедших с полуночи в виде двух десятичных цифр.
  • ":" (двоеточие) появляется буквально дважды в строке.
  • мм - количество полных минут с начала часа в виде двух десятичных цифр.
  • ss - количество полных секунд с начала минуты в виде двух десятичных цифр.
  • "" (точка) появляется буквально в строке.
  • sss - это число полных миллисекунд с начала секунды в виде трех десятичных цифр. Оба "." и поле миллисекунд может быть опущено.
  • Z - смещение часового пояса, указанное как «Z» (для UTC) или «+» или «-», за которым следует выражение времени чч: мм

Этот формат включает формы только для даты:

  • YYYY
  • YYYY-MM
  • YYYY-MM-DD

Он также включает формы только для времени с добавленным необязательным смещением часового пояса:

  • THH: мм
  • THH: мм: сс
  • THH: мм: СС.ссс

Также включены «дата-время», которые могут представлять собой любую комбинацию из вышеперечисленного.

Итак, похоже, что YYYY-MM-DD включен в стандарт, но по некоторым причинам Safari его не поддерживает.

Обновление : после просмотра документации datejs и ее использования, ваша проблема должна быть решена с помощью следующего кода:

var myDate1 = Date.parseExact("29-11-2010", "dd-MM-yyyy");
var myDate2 = Date.parseExact("11-29-2010", "MM-dd-yyyy");
var myDate3 = Date.parseExact("2010-11-29", "yyyy-MM-dd");
var myDate4 = Date.parseExact("2010-29-11", "yyyy-dd-MM");

4
Формат ISO8601 используется в 5-м издании стандарта ECMAScript и пока не получил широкой поддержки. Это самый безопасный способ работы с IMO, анализ даты вручную :(
CMS

1
Это было очень полезно, чувак .. Спасибо .. :) В конце концов, мы использовали datejs для форматирования.
Shrinath

для тех, кто в будущем, обратите внимание, что, хотя datejs является фантастическим во многих отношениях, он не решает все проблемы форматирования даты, особенно с сафари. это PITA, но лучше делать это вручную, если у вас все еще есть проблемы.
totallyNotLizards

@darioo Итак, я попробовал ваш ответ следующим образом: "var start = Date.parseExact (метка времени," ГГГГ-ДД-ММ ЧЧ: мм: СС ");" отметка времени "2016-01-28 00:00:00". Однако теперь я получаю ошибку, что «Date.parseExact не является функцией». Вы знаете, что здесь происходит?
Trexx

5
Моя похожая проблема была вызвана тем, что Safari не знал, как читать часовой пояс в формате часового пояса RFC 822. Мне удалось это исправить с помощью формата ISO 8601. Если у вас есть контроль над форматом даты, я работал с "yyyy-MM-dd'T'HH: mm: ss.sssXXX", который создает ie. "2018-02-06T20: 00: 00,000 + 00: 00". По какой-либо причине Safari не может прочитать «2018-02-06T20: 00: 00.000 + 0000», обратите внимание на отсутствие двоеточия в формате часового пояса.
Ольмстов

224

Для меня реализация новой библиотеки только потому, что Safari не может сделать это правильно, - это слишком много, и регулярное выражение является излишним. Вот Oneliner :

console.log (new Date('2011-04-12'.replace(/-/g, "/")));

Если бы косая черта была только моей проблемой, то я бы «принял» ваш ответ (хотя это была моя единственная цель, когда я задавал этот вопрос). Теперь, когда я нашел dateJS, я внедрил формат MMM DD, YYYY для более удобного использования !!!
Шринат,

13
Эта помощь в одну строку была идеальна для моих нужд! Спасибо!
Кирилл Н.

4
Это было достаточно просто для меня. Не могу поверить, что Safari не нравится - но тот же формат с \\ работает. Спасибо @Elzo и Shrinath за размещение вопроса
Пит

1
Я думаю, что это лучший ответ, который я склонен забывать / - / g вместо '-'
Яцек Пьетал

12
аплодисменты за не реализацию библиотеки.
17

56

Я столкнулся с аналогичной проблемой. Date.Parse("DATESTRING")работал на Chrome (версия 59.0.3071.115), но не на Safari (версия 10.1.1 (11603.2.5))

Сафари:

Date.parse("2017-01-22 11:57:00")
NaN

Хром:

Date.parse("2017-01-22 11:57:00")
1485115020000

Решение, которое работало для меня, состояло в замене пространства в dateString на "T". (Пример: dateString.replace(/ /g,"T"))

Сафари:

Date.parse("2017-01-22T11:57:00")
1485086220000

Хром:

Date.parse("2017-01-22T11:57:00")
1485115020000

Обратите внимание, что ответ от браузера Safari на 8 часов (28800000 мс) меньше, чем ответ браузера Chrome, потому что Safari возвратил ответ в локальной TZ (что на 8 часов позже UTC)

Чтобы получить оба раза в одном и том же TZ

Сафари:

Date.parse("2017-01-22T11:57:00Z")
1485086220000

Хром:

Date.parse("2017-01-22T11:57:00Z")
1485086220000

Или, если вы не хотите, чтобы обе даты были одинаковыми в Safari и Chrome, вы можете использовать new Date(year, month, date, hours, minutes, seconds, milliseconds)конструктор. Разобрать строковую дату в массиве ее компонентов, чтобы использовать эти компоненты в конструкторе. @nizantz было бы здорово, если вы думаете, что такой пример может быть добавлен к вашему ответу.
h3dkandi

Не особенно полезно, поскольку вы получаете дату в UTC, а не по местному времени.
Йонас Эппелгран

1
Эта dateString.replace(/ /g,"T")волшебная строка кода работала от меня. :)
Mazdak Shojaie

заменить (/ - / г, '/')
Джек Ху

11

Я использую момент, чтобы решить проблему. Например

var startDate = moment('2015-07-06 08:00', 'YYYY-MM-DD HH:mm').toDate();

10

Чтобы решение работало в большинстве браузеров, вы должны создать объект date с этим форматом.

(year, month, date, hours, minutes, seconds, ms)

например:

dateObj = new Date(2014, 6, 25); //UTC time / Months are mapped from 0 to 11
alert(dateObj.getTime()); //gives back timestamp in ms

отлично работает с IE, FF, Chrome и Safari. Даже более старые версии.

IE Dev Center: объект Date (JavaScript)

Сеть разработчиков Mozilla: Дата


6

преобразовать строку в дату от fromat (вы должны знать часовой пояс сервера)

new Date('2015-06-16 11:00:00'.replace(/\s+/g, 'T').concat('.000+08:00')).getTime()  

где +08: 00 = часовой пояс с сервера


Это не учитывает DST. Смещение TZ может колебаться, и оно зависит от самой даты (и времени).
Коста

5

У меня была та же проблема. Затем я использовал момент. JS. Проблема исчезла.

При создании момента из строки мы сначала проверяем, соответствует ли строка известным форматам ISO 8601, а затем возвращаемся к новой дате (строка), если известный формат не найден.

Предупреждение. Браузерная поддержка для разбора строк противоречива. Поскольку нет спецификации, какие форматы должны поддерживаться, то, что работает в некоторых браузерах, не будет работать в других браузерах.

Для согласованного анализа результатов, отличных от строк ISO 8601, следует использовать String + Format.

например

var date= moment(String);

3

Хотя вы можете надеяться, что браузеры будут поддерживать ISO 8601 (или только его подмножества дат), это не так. Все известные мне браузеры (по крайней мере, в тех регионах США / Англии, которые я использую) способны анализировать ужасный MM/DD/YYYYформат США .

Если у вас уже есть части даты, вы можете вместо этого попробовать использовать Date.UTC () . Если нет, но вы должны использовать YYYY-MM-DDформат, я предлагаю использовать регулярное выражение, чтобы проанализировать известные вам фрагменты, а затем передать их Date.UTC().


Я думаю, что разбор строк это путь :(
Shrinath

1

Используйте приведенный ниже формат, он будет работать на всех браузерах

var year = 2016;
var month = 02;           // month varies from 0-11 (Jan-Dec)
var day = 23;

month = month<10?"0"+month:month;        // to ensure YYYY-MM-DD format
day = day<10?"0"+day:day;

dateObj = new Date(year+"-"+month+"-"+day);

alert(dateObj); 

// Ваш вывод будет выглядеть так: «Ср 23 марта 2016 00:00:00 GMT + 0530 (IST)»

// Обратите внимание, что это будет в текущем часовом поясе, в данном случае, обозначенном IST, чтобы преобразовать в часовой пояс UTC, который вы можете включить

alert(dateObj.toUTCSting);

// Ваш вывод будет выглядеть так: «Вт, 22 марта 2016 г., 18:30:00 по Гринвичу»

Обратите внимание, что теперь dateObj показывает время в формате GMT, также обратите внимание, что дата и время были изменены соответственно.

Функция «toUTCSting» извлекает соответствующее время на гринвичском меридиане. Это достигается путем установления разницы во времени между вашим текущим часовым поясом и часовым поясом Гринвичского меридиана.

В приведенном выше случае время до преобразования составляло 00:00 часов и минут 23 марта 2016 года. А после преобразования из GMT + 0530 (IST) часов в GMT (в основном это вычитает 5,30 часов из данной отметки времени в этом случай) время отражает 18.30 часов 22 марта 2016 года (ровно 5.30 часов после первого раза).

Далее для преобразования любого объекта даты в метку времени вы можете использовать

alert(dateObj.getTime());

// вывод будет выглядеть примерно так: "1458671400000"

Это даст вам уникальную метку времени



1

Лучший способ сделать это - использовать следующий формат:

new Date(year, month, day, hours, minutes, seconds, milliseconds)
var d = new Date(2018, 11, 24, 10, 33, 30, 0);

Это поддерживается во всех браузерах и не доставит вам никаких проблем. Обратите внимание, что месяцы написаны от 0 до 11.


Хорошо работает на Safari и Chrome, но все еще имеет проблемы с Firefox. Safari: переменная дата = новая дата (2018,06,08,19,17) вс 08 июля 2018 19:17 GMT + 0800 (+08) Chrome: переменная дата = новая дата (2018,06,08,19, 17) Солнце июль 08 2018 19:17:00 GMT + 0800 (время Малайзии) Firefox: var date = new Дата (2018,06,08,19,17) Дата 2018-07-08T11: 17: 00.000Z
Биранчи,

0

Та же самая проблема, с которой сталкиваются в Safari, и была решена путем вставки этого в веб-страницу

 <script src="https://cdn.polyfill.io/v2/polyfill.min.js?features=Intl.~locale.en"></script> 

Надеюсь, это будет работать и ваш случай тоже

Спасибо


Как вы думаете, почему это сработает? Я посмотрел на сценарий, и он, кажется, не переопределяет методы в объекте Date. Я пошел сюда: polyfill.io/v3/url-builder и, похоже, ничего не разбирается в разборе дат.
Коста

0

Как ранее упоминалось @nizantz, использование Date.parse () не помогло мне в Safari. После небольшого исследования я узнал, что свойство lastDateModified для объекта File устарело и больше не поддерживается Safari. Использование свойства lastModified объекта File решило мои проблемы. Конечно, не нравится, когда плохая информация найдена в Интернете.

Спасибо всем, кто внес вклад в этот пост, который помог мне пойти по пути, который мне нужен, чтобы узнать о моей проблеме. Если бы не эта информация, я бы, наверное, не разобрался в своей основной проблеме. Может быть, это поможет кому-то еще в моей аналогичной ситуации.


0

Я также сталкиваюсь с той же проблемой в браузере Safari

var date = new Date("2011-02-07");
console.log(date) // IE you get ‘NaN’ returned and in Safari you get ‘Invalid Date’

Вот решение:

var d = new Date(2011, 01, 07); // yyyy, mm-1, dd  
var d = new Date(2011, 01, 07, 11, 05, 00); // yyyy, mm-1, dd, hh, mm, ss  
var d = new Date("02/07/2011"); // "mm/dd/yyyy"  
var d = new Date("02/07/2011 11:05:00"); // "mm/dd/yyyy hh:mm:ss"  
var d = new Date(1297076700000); // milliseconds  
var d = new Date("Mon Feb 07 2011 11:05:00 GMT"); // ""Day Mon dd yyyy hh:mm:ss GMT/UTC 

0

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

function safeDate(dateString = "") {
  let date = new Date();
  try {
    if (Date.parse(dateString)) {
      date = new Date(Date.parse(dateString))
    }
  } catch (error) {
    // do nothing.
  }
  return date;
}

Я бы посоветовал, чтобы ваш сервер отправлял даты ISO.


При всем уважении, когда вы имеете в виду, что пользователи должны использовать браузер, для которого вы написали код, это выглядит плохо в общем смысле. Это также зависит от наших сценариев использования и целевой аудитории - если бы сайт создавался для массового потребления, мы бы, по крайней мере, поддержали бы и IE10. Я уверен, что кто-то в MS думал так же, когда они разрабатывали / кодировали для Internet Explorer. Мы все знаем, как об этом говорят сейчас.
Shrinath

-1

используйте формат «мм / дд / гггг». Например: - новая дата ('02 / 28/2015 '). Хорошо работает во всех браузерах.

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.