为什么日期(“2014-04-07”)解析为2014年4月5日17:26:15 GMT-0500(CEST)? [英] Why is Date("2014-04-07") parsed to Sat Apr 05 2014 17:26:15 GMT-0500 (CEST)?

查看:188
本文介绍了为什么日期(“2014-04-07”)解析为2014年4月5日17:26:15 GMT-0500(CEST)?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在创建这样的日期:

  var StartDate = new Date(data.feed.entry [i]。 gd $ when [j] .startTime); 

收到日期字符串时指定日期和时间:

 2014-04-12T20:00:00.000-05:00

Date()解释完美的退回:

  2014年4月12日星期四19:00:00 GMT-0500(CDT)

但是,当收到的日期字符串没有时间信息的形式:

 2014-04-07

然后 Date()将其解释为: / p>

  Sat Apr 05 2014 19:00:00 GMT-0500(CDT)
/ pre>

看起来像 Date()正在以-07为时间,我没有线索在哪里它得到的日期为05.任何想法可能是什么问题?
无论如何, Date()正在解释不同的时区,因为在第一个字符串中,时区是在最后确定的,而在全天事件没有时区的指示。



有没有人发现这个问题?如果是的话,你如何解决?



更新:在进一步研究了这个解析问题之后,我注意到一些非常奇怪的事情:



以下陈述:

 新日期(2014-4-07)

将返回Mon Apr 07 2014 00:00:00 GMT-0500(CDT),这是正确的,但以下一个:

 新日期(2014-04-07)

返回Sun Apr 06 2014 19:00:00 GMT-0500(CDT)是错误的。所以,无论什么原因,似乎填充零点影响解析日期的方式!

解决方案

在ES5之前,解析日期字符串完全依赖于实现。 ES5指定可能支持的 ISO 8601的版本浏览器,但不是全部。指定的格式只支持Z时区(UTC),如果时区丢失,则采用UTC。缺少时区的支持是不一致的,一些实现会将该字符串视为UTC,一些作为本地。



确定,您应该自己解析字符串,例如

  / *解析带有或不带偏移的ISO字符串
** eg '2014-04-02T20:00:00-0600'
**'2014-04-02T20:00:00Z'
**
**提供十进制秒(如果提供)
**例如'2014-04-02T20:00:00.123-0600'
**
**如果没有提供偏移量(或是Z),则视为UTC(根据ECMA-262)
* *
**如果只有日期,例如'2014-04-02',视为UTC日期(按ECMA-262)
* /
函数parseISOString(s){
var t = s.split(/ \D + / G);
var hasOffset = /\d{2}[-+]\d{4}$/.test(s);

//是否存在十进制秒是否更改偏移字段和ms值
var hasDecimalSeconds = / T\d {2}:\d {2}:\d {2 } \.\d + / i.test(s);
var offset = hasDecimalSeconds? t [7]:t [6];
var ms = hasDecimalSeconds? t [6]:0;
var offMin,offSign,min;

//如果有偏移量,请将其应用于几分钟以获取UTC时间值
if(hasOffset){
offMin = 60 * offset / 100 + offset%100;
offSign = /-\d{4}$/.test(s)? -1:1;
}
min = hasOffset? + t [4] - offMin * offSign:(t [4] || 0);

//根据UTC值返回一个日期对象
return new Date(Date.UTC(t [0], - t [1],t [2],t [3 ] || 0,min,t [5] || 0,ms));
}

ISO 8601日期字符串应视为UTC(根据ECMA-262) ,所以如果你是UTC-0500,那么:

  new Date('2014-04-07'); // 2014-04-06T19:00:00-0500 

OP中描述的行为显示主机不符合ECMA-262。进一步鼓励您自己解析字符串。如果您希望将日期视为本地,则:

  //以ISO 8601格式预期字符串
/ / Offset被忽略,Date被创建为本地时间
函数parseLocalISODate(s){
s = s.split(/ \D + / g);
return new Date(s [0], - s [1],s [2],0,0,0,0);
}

在您的函数中,您可以执行以下操作:

  var ds = data.feed.entry [i] .gd $ when [j] .startTime; 
var startDate = ds.length == 10? parseLocalISODate(ds):parseISOString(ds);

另请注意,按大写字母开头的变量按照惯例保留给构造函数,因此 startDate ,而不是 StartDate


I'm creating dates like this:

var StartDate = new Date(data.feed.entry[i].gd$when[j].startTime);

When a date string is received specifying date and time in the form:

"2014-04-12T20:00:00.000-05:00"

Date() interprets this perfectly fine returning:

Sat Apr 12 2014 19:00:00 GMT-0500 (CDT)

However, when the date string is received with no time information in the form:

"2014-04-07" 

then Date() is interpreting it as:

Sat Apr 05 2014 19:00:00 GMT-0500 (CDT)

Looks like Date() is taking the -07 as the time and I have no clue where is it getting the date as 05. Any idea what might be the problem? Could it be, somehow, Date() is interpreting a different time zone because in the first string the time zone is determined at the very end but in the "all day" event there is no indication of the time zone.

Has anybody found this issue? If yes, how did you solve it?

UPDATE: After researching a little bit more this parsing issue I noticed something very weird:

The following statement:

 new Date("2014-4-07")

would return Mon Apr 07 2014 00:00:00 GMT-0500 (CDT) which is correct, but the following one:

  new Date("2014-04-07")

returns Sun Apr 06 2014 19:00:00 GMT-0500 (CDT) which is the wrong one. So, for whatever reason, seems like the padding zeros affect the way the date is parsed!

解决方案

Prior to ES5, parsing of date strings was entirely implementation dependent. ES5 specifies a version of ISO 8601 that is supported by may browsers, but not all. The specified format only supports the Z timezone (UTC) and assumes UTC if the timezone is missing. Support where the timezone is missing is inconsistent, some implementations will treat the string as UTC and some as local.

To be certain, you should parse the string yourself, e.g.

/* Parse an ISO string with or without an offset
**   e.g. '2014-04-02T20:00:00-0600'
**        '2014-04-02T20:00:00Z'
**
** Allows decimal seconds if supplied
**   e.g. '2014-04-02T20:00:00.123-0600'
**
** If no offset is supplied (or it's Z), treat as UTC (per ECMA-262)
**
** If date only, e.g. '2014-04-02', treat as UTC date (per ECMA-262)
*/
function parseISOString(s) {
  var t = s.split(/\D+/g);
  var hasOffset = /\d{2}[-+]\d{4}$/.test(s);

  // Whether decimal seconds are present changes the offset field and ms value
  var hasDecimalSeconds = /T\d{2}:\d{2}:\d{2}\.\d+/i.test(s);
  var offset = hasDecimalSeconds? t[7] : t[6];
  var ms = hasDecimalSeconds? t[6] : 0;
  var offMin, offSign, min;

  // If there's an offset, apply it to minutes to get a UTC time value
  if (hasOffset) {
    offMin = 60 * offset / 100 + offset % 100;
    offSign = /-\d{4}$/.test(s)? -1 : 1;
  }
  min = hasOffset? +t[4] - offMin * offSign : (t[4] || 0);

  // Return a date object based on UTC values
  return new Date(Date.UTC(t[0], --t[1], t[2], t[3]||0, min, t[5]||0, ms));
}

An ISO 8601 date string should be treated as UTC (per ECMA-262), so if you are UTC-0500, then:

new Date('2014-04-07'); // 2014-04-06T19:00:00-0500

The behaviour described in the OP shows the host is not compliant with ECMA-262. Further encouragement to parse the string yourself. If you want the date to be treated as local, then:

// Expect string in ISO 8601 format
// Offset is ignored, Date is created as local time
function parseLocalISODate(s) {
  s = s.split(/\D+/g);
  return new Date(s[0], --s[1], s[2],0,0,0,0);
}

In your function you can do something like:

var ds = data.feed.entry[i].gd$when[j].startTime;
var startDate = ds.length == 10? parseLocalISODate(ds) : parseISOString(ds);

Also note that variables starting with a capital letter are, by convention, reserved for constructors, hence startDate, not StartDate.

这篇关于为什么日期(“2014-04-07”)解析为2014年4月5日17:26:15 GMT-0500(CEST)?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆