Подтвердить что ты не робот

Есть ли какое-либо обходное решение для разбитого синтаксического анализатора v8?

V8 Синтаксический анализатор даты не работает:

> new Date('asd qw 101')
Sat Jan 01 101 00:00:00 GMT+0100 (CET)

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

\d{1,2} (jan|feb|mar|may|jun|jul|aug|sep|oct|nov|dec) \d{1,4}

но он слишком хрупкий. Я не могу полагаться на new Date (проблема в V8), а также момент не может помочь мне, потому что момент избавиться от определения даты (github issue-thread).

есть ли какое-либо временное решение для разбитого синтаксического анализатора v8?

Быть ясным. У нас есть Gecko и V8, оба имеют Date. V8 сломал дату, у Gecko есть рабочий. Мне нужен Date из Gecko (Firefox).

Обновление: его определенно сломанный парсер https://code.google.com/p/v8/issues/detail?id=2602
nope, Status: WorkingAsIntended

4b9b3361

Ответ 1

Date объекты основаны на значении времени, которое составляет миллисекунды с 1 января 1970 года по UTC и имеют следующие конструкторы

new Date();
new Date(value);
new Date(dateString);
new Date(year, month[, day[, hour[, minutes[, seconds[, milliseconds]]]]]);

Из docs,

dateString в new Date(dateString) - это строковое значение, представляющее дату. Строка должна быть в формат, распознаваемый методом Date.parse() (IETF-совместимый RFC 2822 timestamps, а также версию ISO8601).

Теперь посмотрим исходный код v8 в date.js:

function DateConstructor(year, month, date, hours, minutes, seconds, ms) {
  if (!%_IsConstructCall()) {
    // ECMA 262 - 15.9.2
    return (new $Date()).toString();
  }

  // ECMA 262 - 15.9.3
  var argc = %_ArgumentsLength();
  var value;
  if (argc == 0) {
    value = %DateCurrentTime();
    SET_UTC_DATE_VALUE(this, value);
  } else if (argc == 1) {
    if (IS_NUMBER(year)) {
      value = year;
    } else if (IS_STRING(year)) {
      // Probe the Date cache. If we already have a time value for the
      // given time, we re-use that instead of parsing the string again.
      var cache = Date_cache;
      if (cache.string === year) {
        value = cache.time;
      } else {
        value = DateParse(year);               <- DOES NOT RETURN NaN
        if (!NUMBER_IS_NAN(value)) {
          cache.time = value;
          cache.string = year;
        }
      }

    }
...

похоже, что DateParse() не возвращает NaN для строки типа 'asd qw 101' и, следовательно, ошибки. Вы можете перекрестно проверить то же самое с Date.parse('asd qw 101') в Chrome (v8) [который возвращает -58979943000000] и Gecko (Firefox) [который возвращает NaN]. Sat Jan 01 101 00:00:00 появляется при посеве new Date() с отметкой времени -58979943000000 (в обоих браузерах)

есть ли какое-либо временное решение для разбитого синтаксического анализатора v8?

Я бы не сказал, что парсер даты V8 сломан. Он просто пытается удовлетворить строку RFC 2822 standard наилучшим образом, но так же делает gecko и обе break дает разные результаты в определенных случаях.

Попробуйте new Date('Sun Ma 10 2015') в Chrome (V8) и Firefox (Gecko) для другой такой аномалии. Здесь хром не может решить, что погода "Ма" означает "март" или "май" и дает недопустимую дату, пока Firefox не делает.

Обход проблемы:

Вы можете создать свою собственную оболочку вокруг Date(), чтобы отфильтровать те строки, которые не поддерживает собственный парсер V8. Однако подклассификация встроенных модулей ECMA-5 невозможна. В ECMA-6 возможно подклассы встроенных конструкторов (Array, Date и Error) - ссылка

Однако вы можете использовать более надежное регулярное выражение для проверки строк по RFC 2822/ISO 8601

^(?:(?:31(\/|-|\. |\s)(?:0?[13578]|1[02]|(?:Jan|Mar|May|Jul|Aug|Oct|Dec)))\1|(?:(?:29|30)(\/|-|\.|\s)(?:0?[1,3-9]|1[0-2]|(?:Jan|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec))\2))(?:(?:1[6-9]|[2-9]\d)?\d{2})$|^(?:29(\/|-|\.|\s)(?:0?2|(?:Feb))\3(?:(?:(?:1[6-9]|[2-9]\d)?(?:0[48]|[2468][048]|[13579][26])|(?:(?:16|[2468][048]|[3579][26])00))))$|^(?:0?[1-9]|1\d|2[0-8])(\/|-|\.|\s)(?:(?:0?[1-9]|(?:Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep))|(?:1[0-2]|(?:Oct|Nov|Dec)))\4(?:(?:1[6-9]|[2-9]\d)?\d{2})$

Image-regex Изображение, созданное с помощью debuggex

Итак, похоже, что v8 aint сломан, он просто работает по-другому.

Надеюсь, что это поможет!

Ответ 2

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

Вы говорите, что moment.js "избавляется от обнаружения даты", но на самом деле никогда не было этой функции в первую очередь. Люди просто сделали предположение, что он может это сделать, а в некоторых случаях это сработало, а во многих случаях этого не произошло.

Вот пример, иллюстрирующий проблему.

 var s = "01.02.03";

Это дата? Может быть. Возможно, нет. Это может быть заголовок раздела в документе. Даже если бы мы сказали, что это дата, какая дата? Его можно интерпретировать как любое из следующего:

  • 2 января 2003 г.
  • 2 января, 0003
  • 1 февраля 2003 г.
  • 1 февраля, 0003
  • 3 февраля 2001 г.
  • 3 февраля 0001

Единственный способ устранения неоднозначности - это знание текущих настроек даты культуры. Объект Javascript Date делает именно это - это означает, что вы получите другое значение в зависимости от настроек машины, на которой работает код. Тем не менее, moment.js - это стабильность во всех средах. Культурные настройки ясны, используя функциональность локального языка. Опора на настройки культуры браузера приводит к ошибкам в интерпретации.

Лучшее, что нужно сделать, это четко указать формат, с которым вы работаете. Не допускайте случайный вход мусора. Ожидайте ввода в определенном формате и используйте регулярное выражение для проверки этого формата заблаговременно, вместо этого просто пытаемся построить Date и посмотреть, действительно ли это после факта.

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

См. также: Мусор, мусор

Ответ 3

ES5 15.9.4.2 Date.parse:/.../Если строка не соответствует что формат функции может вернуться к любой конкретной реализации эвристики или форматы дат реализации. неузнаваемый Строки или даты, содержащие недопустимые значения элементов в формате Строка должна вызывать Date.parse для возврата NaN.

Итак, все правильно и в соответствии с цитированием выше результата синтаксического анализа даты v8:

  • new Date('asd qw 101'): Сб 01.01 101 00:00:00 GMT + 0100 (CET)
  • new Date('asd qw'): Недействительная дата