【问题标题】:Javascript date parsing bug - fails for dates in June (??)Javascript 日期解析错误 - 六月日期失败 (??)
【发布时间】:2009-07-31 18:55:46
【问题描述】:

我有一些 javascript 可以解析 ISO-8601 日期。出于某种原因,它在六月的日期失败了。但是七月和五月的日期工作正常,这对我来说没有意义。我希望新的眼光会有所帮助,因为我看不出我在这里做错了什么。

函数定义(有bug)

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());

输出

  • 格林威治标准时间 2009 年 5 月 9 日星期六 12:30:00
  • 2009 年 7 月 9 日星期四 12:30:00 GMT
  • 格林威治标准时间 2009 年 7 月 9 日星期四 12:30:00

更新

感谢快速解答,问题是Date对象最初是今天,恰好是7月31日。当月份设置为6月时,在我更改日期之前,暂时是6月31日,前滚至 7 月 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;
}

【问题讨论】:

    标签: javascript parsing date


    【解决方案1】:

    问题是今天是 7 月 31 日。

    当你设置时:

    var date = new Date();
    

    那么 date.getUTCDate() 是 31。当您设置 date.setUTCMonth(5)(六月)时,您将 date 设置为 六月 31。因为没有 6 月 31 日,所以 JavaScript Date 对象将其变为 7 月 1 日。因此,在设置调用 date.setUTCMonth(5) 后,如果你是 alert(date.getUTCMonth());,它将立即是 6

    这不是六月独有的。对于没有 31 天的任何其他月份,在任何一个月的 31 日使用您的函数都会出现同样的问题。在 2 月的任何一个月的 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));
    

    【讨论】:

    • 另外,如果我将日期初始化为new Date(0),则可以(因为那是'1970-01-01T00:00:00-00:00')
    • @Kip:是的,使用new Date(0) 也应该可以解决问题,因为没有任何意外的月末翻转风险。
    【解决方案2】:

    日期对象从当前日期开始。 今天是第 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】:

      因为今天是 7 月 31 日。格兰特解释了这个问题。这是我认为更简单的解决方案。将您的日期初始化为 1 月 1 日。

      var date = new Date(2009,0,1,0,0,0);
      

      【讨论】:

        【解决方案4】:

        这是您更改日期的顺序。 日期从 7 月 31 日开始,因此月份的设置失败,因为 6 月没有 31。 (实际上是滚动到 7 月 1 日。)

        设置全年后,添加:

        date.setYUTCDate(1);
        

        它使它成为每月有效的月份的第一天。

        【讨论】:

          【解决方案5】:

          看起来像一个错误?

          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
          

          编辑:没关系,我猜。问题已经由更有知识的人回答了。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多