我将用jQuery首次尝试Ajax。我正在将数据放到页面上,但对于Date数据类型返回的JSON数据,我遇到了一些问题。基本上,我得到的字符串是这样的:

/Date(1224043200000)/

从一个对JSON完全陌生的人那里——我如何将其格式化为短日期格式?这应该在jQuery代码中的某个地方处理吗?我使用$.datepicker.formatDate()尝试了jQuery.UI.datepicker插件,但没有成功。

仅供参考:以下是我使用以下答案组合得出的解决方案:

function getMismatch(id) {
  $.getJSON("Main.aspx?Callback=GetMismatch",
    { MismatchId: id },

    function (result) {
      $("#AuthMerchId").text(result.AuthorizationMerchantId);
      $("#SttlMerchId").text(result.SettlementMerchantId);
      $("#CreateDate").text(formatJSONDate(Date(result.AppendDts)));
      $("#ExpireDate").text(formatJSONDate(Date(result.ExpiresDts)));
      $("#LastUpdate").text(formatJSONDate(Date(result.LastUpdateDts)));
      $("#LastUpdatedBy").text(result.LastUpdateNt);
      $("#ProcessIn").text(result.ProcessIn);
    }
  );

  return false;
}

function formatJSONDate(jsonDate) {
  var newDate = dateFormat(jsonDate, "mm/dd/yyyy");
  return newDate;
}

这个解决方案从回调方法中获取了我的对象,并使用日期格式库在页面上正确显示了日期。


当前回答

不要想得太多。像我们几十年来所做的那样,从1970年1月1日午夜GMT/UTC/&c这一事实上的标准时间开始,以秒(或毫秒)为单位传递一个数字偏移量。JavaScript喜欢它,Java喜欢它,C喜欢它,互联网喜欢它。

其他回答

eval()不是必需的。这将很好:

var date = new Date(parseInt(jsonDate.substr(6)));

substr()函数取出/Date(部分),parseInt()函数获取整数并忽略结尾处的)/。生成的数字被传递到Date构造函数中。


我故意省略了基数(parseInt的第二个参数);请看我下面的评论。

此外,我完全同意Rory的评论:ISO-8601日期比这种旧格式更可取,因此这种格式通常不应用于新的开发。

对于ISO-8601格式的JSON日期,只需将字符串传递到Date构造函数:

var date = new Date(jsonDate); //no ugly parsing needed; full timezone support

JSON中没有内置日期类型。这看起来像是某个纪元的秒/毫秒数。如果你知道时间,你可以通过添加正确的时间量来创建日期。

如果在JavaScript中,

var thedate = new Date(1224043200000);
alert(thedate);

您将看到这是正确的日期,您可以在JavaScript代码中的任何地方使用它与任何框架。

TLDR:无法可靠地转换仅日期值,请发送字符串。。。

……或者至少这是所有这些答案的开始。

这里出现了许多转换问题。

这是一个没有时间的日期

每个人似乎都缺少的一点是,问题中有多少个尾随的零-它几乎可以肯定是从一个没有时间的日期开始的:

/Date(1224043200000)/

当从javascript控制台将其作为新日期执行时(许多答案的基础)

new Date(1224043200000)

你得到:

最初的询问者可能在EST中,并且有一个带有午夜的纯日期(sql)或DateTime(而不是DateTimeOffset)。

换句话说,这里的意图是时间部分没有意义。但是,如果浏览器在与生成的服务器相同的时区执行此操作,则无所谓,大多数答案都有效。

按时区排序

但是,如果您在不同时区(例如PST)的计算机上执行上述代码:

你会注意到,我们现在在另一个时区落后了一天。这不会通过更改序列化程序来解决(它仍将以iso格式包含时区)

问题

Date(sql)和DateTime(.net)上没有时区,但一旦将它们转换为可以执行的操作(在本例中是通过json推断的javascript),.net中的默认操作就是假定当前时区。

序列化正在创建的数字是自Unix纪元以来的毫秒数,或者:

(DateTimeOffset.Parse("10/15/2008 00:00:00Z") - DateTimeOffset.Parse("1/1/1970 00:00:00Z")).TotalMilliseconds;

javascript中的新Date()将其作为参数。Epoch来自UTC,所以无论您是否想要,现在您都可以在其中获得时区信息。

可能的解决方案:

在序列化对象上创建一个仅表示日期的字符串属性可能会更安全——带有“10/15/2008”的字符串不太可能将其他人与此混淆。尽管即使在那里,您也必须在解析方面小心:https://stackoverflow.com/a/31732581

然而,本着对所提问题提供答案的精神,如下:

function adjustToLocalMidnight(serverMidnight){ 
  var serverOffset=-240; //injected from model? <-- DateTimeOffset.Now.Offset.TotalMinutes
  var localOffset=-(new Date()).getTimezoneOffset(); 
  return new Date(date.getTime() + (serverOffset-localOffset) * 60 * 1000)
}

var localMidnightDate = adjustToLocalMidnight(new Date(parseInt(jsonDate.substr(6))));

已更新

我们有一个内部UI库,它必须同时处理Microsoft的ASP.NET内置JSON格式,如/Date(msecs)/(最初在这里询问),以及大多数JSON的日期格式(包括JSON.NET),如2014-06-22T00:00:00.0。此外,我们还需要应对旧IE无法处理除小数点后3位以外的任何内容。

我们首先检测我们使用的日期类型,将其解析为一个普通的JavaScriptDate对象,然后将其格式化。

1) 检测Microsoft日期格式

// Handling of Microsoft AJAX Dates, formatted like '/Date(01238329348239)/'
function looksLikeMSDate(s) {
    return /^\/Date\(/.test(s);
}

2) 检测ISO日期格式

var isoDateRegex = /^(\d\d\d\d)-(\d\d)-(\d\d)T(\d\d):(\d\d):(\d\d)(\.\d\d?\d?)?([\+-]\d\d:\d\d|Z)?$/;

function looksLikeIsoDate(s) {
    return isoDateRegex.test(s);
}

3) 分析MS日期格式:

function parseMSDate(s) {
    // Jump forward past the /Date(, parseInt handles the rest
    return new Date(parseInt(s.substr(6)));
}

4) 分析ISO日期格式。

我们至少有一种方法可以确保我们处理的是标准ISO日期或ISO日期修改为总是有三毫秒的位置(见上文),因此代码因环境而异。

4a)分析标准ISO日期格式,处理旧IE的问题:

function parseIsoDate(s) {
    var m = isoDateRegex.exec(s);

    // Is this UTC, offset, or undefined? Treat undefined as UTC.
    if (m.length == 7 ||                // Just the y-m-dTh:m:s, no ms, no tz offset - assume UTC
        (m.length > 7 && (
            !m[7] ||                    // Array came back length 9 with undefined for 7 and 8
            m[7].charAt(0) != '.' ||    // ms portion, no tz offset, or no ms portion, Z
            !m[8] ||                    // ms portion, no tz offset
            m[8] == 'Z'))) {            // ms portion and Z
        // JavaScript's weirdo date handling expects just the months to be 0-based, as in 0-11, not 1-12 - the rest are as you expect in dates.
        var d = new Date(Date.UTC(m[1], m[2]-1, m[3], m[4], m[5], m[6]));
    } else {
        // local
        var d = new Date(m[1], m[2]-1, m[3], m[4], m[5], m[6]);
    }

    return d;
}

4b)使用固定的三毫秒小数位解析ISO格式-更容易:

function parseIsoDate(s) {
    return new Date(s);
}

5) 设置格式:

function hasTime(d) {
    return !!(d.getUTCHours() || d.getUTCMinutes() || d.getUTCSeconds());
}

function zeroFill(n) {
    if ((n + '').length == 1)
        return '0' + n;

    return n;
}

function formatDate(d) {
    if (hasTime(d)) {
        var s = (d.getMonth() + 1) + '/' + d.getDate() + '/' + d.getFullYear();
        s += ' ' + d.getHours() + ':' + zeroFill(d.getMinutes()) + ':' + zeroFill(d.getSeconds());
    } else {
        var s = (d.getMonth() + 1) + '/' + d.getDate() + '/' + d.getFullYear();
    }

    return s;
}

6) 将其联系在一起:

function parseDate(s) {
    var d;
    if (looksLikeMSDate(s))
        d = parseMSDate(s);
    else if (looksLikeIsoDate(s))
        d = parseIsoDate(s);
    else
        return null;

    return formatDate(d);
}

下面的旧答案对于将这个日期格式绑定到jQuery自己的JSON解析中非常有用,这样您就可以得到date对象而不是字符串,或者如果您仍然被jQuery<1.5所困扰。

旧答案

如果将jQuery 1.4的Ajax函数与ASP.NET MVC结合使用,则可以使用以下命令将所有DateTime财产转换为Date对象:

// Once
jQuery.parseJSON = function(d) {return eval('(' + d + ')');};

$.ajax({
    ...
    dataFilter: function(d) {
        return d.replace(/"\\\/(Date\(-?\d+\))\\\/"/g, 'new $1');
    },
    ...
});

在jQuery1.5中,通过在Ajax调用中使用converters选项,可以避免全局重写parseJSON方法。

http://api.jquery.com/jQuery.ajax/

不幸的是,您必须切换到较旧的eval路由,以便将Dates全局解析到位,否则您需要在解析后逐个转换它们。