Javascript: Date() 函数在 Google Chrome 中不能完全工作

Javascript: Date() function does not fully work in Google Chrome

当我使用 Date() 函数转换来自数据库的日期时,转换按预期进行。

这是我的代码:

$.get(masterUri + "/odata/ViewAppointments")
    .done(function (data) {

    clubAppointments = new DevExpress.data.ArrayStore({
            key: "id"
    });
    var start, end;

    for (var x = 0; x < data.value.length; x++) {

        start = new Date(data.value[x].Start_Datetime);
        end = new Date(data.value[x].End_DateTime);

        clubAppointments.insert({
            id: x,
            text: data.value[x].Client_Name,
            SportId: parseInt(data.value[x].Sport_ID_ref),
            Court_ID: parseInt(data.value[x].Court_ID),
            startDate: start,
            endDate: end,
            status: data.value[x].TYPE
        });
    }

    debugger;

});

The clubAppointments variable is just an ArrayStore from DevExtreme JS framework. [NOT IMPORTANT]

如果您注意到,我从名为 "data.value" 的数组中取出每个值并将这些值插入到一个新的 ArrayStore 变量中。

在我这样做之前,我必须将日期转换为 javascript 日期,以便我的 dxScheduler(Dextreme UI 小部件)可以读取它。

Internet Explorer 和 FireFox 运行良好。查看刚刚查看上次约会的结果:

来自数据库 [使用 Visual Studio 调试器]

data.value[11].End_DateTime = "2016-05-24T11:30:00"

转换后 [使用 Visual Studio 调试器]:

clubAppointments._array[11].endDate = Tue May 24 2016 11:30:00 GMT-0400 (SA Western Standard Time)

这在 IE 和 FireFox 上都会发生。

遗憾的是,这个日期转换在我这边的 Google Chrome 中效果不佳。请在这里再次观看结果:

来自数据库[使用 Google Chrome 调试器]:

End_DateTime:"2016-05-24T11:30:00"

转换后 [使用 Google Chrome 调试器]:

endDate:Tue May 24 2016 07:30:00 GMT-0400 (SA Western Standard Time)

请观看以下附件以清楚地了解发生了什么: Image

您应该手动解析日期字符串,不要将其留给 Date 构造函数(或 Date.parse,它们是等价的)。根据 ECMAScript 2015,没有时区的 ISO 8601 格式的日期和时间字符串应被视为本地日期和时间字符串,但是某些浏览器会将其视为 UTC(如您所见)。

唯一 解析日期字符串的可靠方法是手动进行。如果您只有一种格式,那么只需要一个小函数即可。如果你有更多的要求,小图书馆可以提供帮助,有很多可供选择。

例如这是一个根据当前规范解析 ISO 8601 格式日期和时间字符串的函数(尽管我不同意将日期字符串视为 UTC 的方式,这与 ISO 8601 和常识不一致)。

/**
 * Parse an ISO string with or without an offset
 *   e.g. '2014-04-02T20:00:00-0600'
 *        '2014-04-02T20:00:00Z'
 *        '2014-02'
 *
 * Allows decimal seconds if supplied
 *   e.g. '2014-04-02T20:00:00.123-0600'
 *
 * If the string is time and date with no offset, treat as local (per ECMA-262 ed 6)
 * If date only, e.g. '2014-04-02' or '2014-02', treat as UTC date (per ECMA-262 ed 6)
 *
 * All parts after year are optional
 * Don't allow two digit years to be converted to 20th century years
 * @param {string} s - ISO 860 date string
*/
function parseISOString(s) {
  var t = s.split(/\D+/g);
  var hasOffset = /[-+]\d{4}$/.test(s);
  var isZulu = /z$/i.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 offSign;
  var yr  = +t[0],
      mo  = t[1]? --t[1] : 0,
      da  = +t[2] || 1,
      hr  = +t[3] || 0,
      min = +t[4] || 0,
      sec = +t[5] || 0,
      ms  = hasDecimalSeconds? +t[6] : 0,
      
      // Reverse the sign of the offset
      offSign = hasOffset? /-\d{4}$/.test(s)? 1 : -1 : 0,
      offHr   = hasOffset? offset/100 | 0 : 0,
      offMin  = hasOffset? offset%100 : 0;
      
  // Ensure time values are in range, otherwise invalid date.
  // Values can't be -ve as splitting on non-digit character
  if (hr > 24 || min > 59 || sec > 59 || ms > 1000 || offHr > 24 || offMin > 59){
    return NaN;
  }
  
  // Create a date object from date parts, check for validity
  // Avoid two digit years being converted to 20th century
  var d = new Date();
  d.setUTCFullYear(yr, mo, da);
  
  // Check that date values are valid
  if (d.getUTCFullYear() != yr || d.getUTCDate() != da) {
    return NaN;
  }

  // It there's no offset and there are time parts, use local date methods
  if (!hasOffset && !isZulu && t[3] && t[4] && t[5]) {
    d.setHours(hr, min, sec, ms);
    
  // Otherwise, apply offset to minutes to use UTC date methods
  } else {
    min = hasOffset? +min + offSign * (offHr * 60 + offMin) : min;
    d.setUTCHours(hr, min, sec, ms);
  }

  return d;
}

['2016-05-24T11:30:00','2016-05-24T11:30:00Z','2016-05-24T11:30:00+0530',
 '2016-12-04']
 .forEach(function(s) {
   document.write('<br>' + s + '<br>' + parseISOString(s) + '<br>');
 });