Ошибка разбора даты в Javascript - не работает для дат в июне (??) - PullRequest
6 голосов
/ 31 июля 2009

У меня есть некоторый javascript, который анализирует дату ISO-8601. По некоторым причинам, это не подходит для дат в июне. Но даты в июле и мае работают хорошо, что не имеет смысла для меня. Я надеюсь, что новые глаза помогут, потому что я не вижу, что я делаю здесь неправильно.

Определение функции (с ошибкой)

function parseISO8601(timestamp)
{
  var regex = new RegExp("^([\\d]{4})-([\\d]{2})-([\\d]{2})T([\\d]{2}):([\\d]{2}):([\\d]{2})([\\+\\-])([\\d]{2}):([\\d]{2})$");
  var matches = regex.exec(timestamp);
  if(matches != null)
  {
    var offset = parseInt(matches[8], 10) * 60 + parseInt(matches[9], 10);
    if(matches[7] == "-")
      offset = -offset;

    var date = new Date();
    date.setUTCFullYear(parseInt(matches[1], 10));
    date.setUTCMonth(parseInt(matches[2], 10) - 1); //UPDATE - this is wrong
    date.setUTCDate(parseInt(matches[3], 10));
    date.setUTCHours(parseInt(matches[4], 10));
    date.setUTCMinutes(parseInt(matches[5], 10) - offset);
    date.setUTCSeconds(parseInt(matches[6], 10));
    date.setUTCMilliseconds(0);

    return date;
  }
  return null;
}

Тестовый код

alert(parseISO8601('2009-05-09T12:30:00-00:00').toUTCString());
alert(parseISO8601('2009-06-09T12:30:00-00:00').toUTCString());
alert(parseISO8601('2009-07-09T12:30:00-00:00').toUTCString());

выход

  • Суббота, 09 мая 2009 г., 12:30:00 по Гринвичу
  • Чт, 09 Июль 2009 12:30:00 по Гринвичу
  • Чт, 09 июля 2009 12:30:00 по Гринвичу

Обновление

Спасибо за быстрые ответы, проблема заключалась в том, что объект Date изначально был сегодня, что случилось 31 июля. Когда месяц был установлен на июнь, до того как я изменил день, он был временно 31 июня , перенесенный на 1 июля.

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

function parseISO8601(timestamp)
{
  var regex = new RegExp("^([\\d]{4})-([\\d]{2})-([\\d]{2})T([\\d]{2}):([\\d]{2}):([\\d]{2})([\\+\\-])([\\d]{2}):([\\d]{2})$");
  var matches = regex.exec(timestamp);
  if(matches != null)
  {
    var offset = parseInt(matches[8], 10) * 60 + parseInt(matches[9], 10);
    if(matches[7] == "-")
      offset = -offset;

    return new Date(
      Date.UTC(
        parseInt(matches[1], 10),
        parseInt(matches[2], 10) - 1,
        parseInt(matches[3], 10),
        parseInt(matches[4], 10),
        parseInt(matches[5], 10),
        parseInt(matches[6], 10)
      ) - offset*60*1000
    );
  }
  return null;
}

Ответы [ 5 ]

13 голосов
/ 31 июля 2009

Проблема в том, что сегодня 31 июля.

Когда вы установите:

var date = new Date();

Тогда date.getUTCDate() равно 31. Когда вы устанавливаете date.setUTCMonth(5) (для июня), вы устанавливаете date на 31 июня . Поскольку нет 31 июня, объект JavaScript Date превращает его в 1 июля . Так что сразу после установки звонка date.setUTCMonth(5), если вы alert(date.getUTCMonth());, это будет 6.

Это не уникально для июня. Использование вашей функции 31-го числа любого месяца для любого другого месяца, у которого нет 31-го дня, будет иметь ту же проблему. Использование вашей функции 29-го (не високосного года), 30-го или 31-го числа любого месяца февраля также приведет к неверному результату.

Вызов setUTC*() таким образом, что любые опрокидывания перезаписываются на правильное значение, должно исправить это:

var date = new Date();
date.setUTCMilliseconds(0);
date.setUTCSeconds(parseInt(matches[6], 10));
date.setUTCMinutes(parseInt(matches[5], 10) - offset);
date.setUTCHours(parseInt(matches[4], 10));
date.setUTCDate(parseInt(matches[3], 10));
date.setUTCMonth(parseInt(matches[2], 10) - 1);
date.setUTCFullYear(parseInt(matches[1], 10));
5 голосов
/ 31 июля 2009

Объект даты начинается с текущей даты. Это 31-е число сегодня, поэтому настройка 2009-06-09 дает:

var date = new Date();     // Date is 2009-07-31
date.setUTCFullYear(2009); // Date is 2009-07-31
date.setUTCMonth(6 - 1);   // Date is 2009-06-31 = 2009-07-01
date.setUTCDate(9);        // Date is 2009-07-09

Если вы установите дату на 1-е до начала, то вы должны быть в безопасности.

3 голосов
/ 31 июля 2009

Это потому, что сегодня 31 июля. Грант объяснил проблему. Вот что я считаю более простым решением. Инициализируйте дату 1 января.

var date = new Date(2009,0,1,0,0,0);
0 голосов
/ 31 июля 2009

выглядит как ошибка?

C:\Documents and Settings\me>java org.mozilla.javascript.tools.shell.Main
Rhino 1.7 release 2 2009 03 22
js> date = new Date();
Fri Jul 31 2009 15:18:38 GMT-0400 (EDT)
js> date.setUTCMonth(5); date.toUTCString();
Wed, 01 Jul 2009 19:18:38 GMT
js> date.setUTCMonth(5); date.toUTCString();
Mon, 01 Jun 2009 19:18:38 GMT

РЕДАКТИРОВАТЬ: не имеет значения, я думаю. На вопрос уже ответил кто-то более знающий.

0 голосов
/ 31 июля 2009

Это порядок, в котором вы меняете дату. Дата начинается с 31 июля, поэтому набор месяца не выполняется, потому что в июне нет 31. (На самом деле он переносится на июль-1.)

После задания полного года добавьте:

date.setYUTCDate(1);

Это делает его первым месяцем, в котором действует каждый месяц.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...