[jquery] 如何格式化Microsoft JSON日期?


Answers

你可以用它从JSON获取日期:

var date = eval(jsonDate.replace(/\/Date\((\d+)\)\//gi, "new Date($1)"));

然后,您可以使用JavaScript日期格式脚本(缩小和压缩后为1.2 KB)来按需要显示它。

Question

我正在使用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;
}

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




更新

我们有一个内部用户界面库,它必须处理微软的ASP.NET内置JSON格式,如/Date(msecs)/ ,最初问到这里,以及大多数JSON的日期格式,包括JSON.NET,如2014-06-22T00:00:00.0 。 另外,我们需要处理oldIE无法处理除小数点后三位的任何事情 。

我们首先检测我们正在使用的日期类型,将其解析为正常的JavaScript Date对象,然后将其格式化。

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日期格式,应对oldIE的问题:

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中。

旧答案

如果您在ASP.NET MVC中使用jQuery 1.4的Ajax函数,则可以将所有DateTime属性转换为Date对象:

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

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

在jQuery 1.5中,您可以避免使用Ajax调用中的转换器选项来全局覆盖parseJSON方法。

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

不幸的是,您必须切换到较旧的eval路由才能使日期在全局就地解析 - 否则您需要在更大的个案基础解析后转换它们。




只是在这里添加另一种方法,如果您没有特别小心,例如here和其他地方所描述的, WCF采用的“滴答方式”很容易出现时区问题。 所以我现在使用的是ISO 8601格式,.NET和JavaScript正式支持包括时区偏移。 以下是详细信息:

在WCF / .NET中:

CreationDate是一个System.DateTime; ToString(“o”)使用.NET的往返格式说明符来生成符合ISO 8601标准的日期字符串

new MyInfo {
    CreationDate = r.CreationDate.ToString("o"),
};

在JavaScript中

在检索JSON后,我使用Date构造函数将日期修改为JavaSript Date对象,该构造函数接受ISO 8601日期字符串...

$.getJSON(
    "MyRestService.svc/myinfo",
    function (data) {
        $.each(data.myinfos, function (r) {
            this.CreatedOn = new Date(this.CreationDate);
        });
        // Now each myinfo object in the myinfos collection has a CreatedOn field that is a real JavaScript date (with timezone intact).
       alert(data.myinfos[0].CreationDate.toLocaleString());
    }
)

一旦你有一个JavaScript日期,你可以使用所有方便可靠的日期方法,如toDateStringtoLocaleString等。




使用jQuery UI日期选择器 - 如果你已经包含jQuery UI,那么这种方法才有意义:

$.datepicker.formatDate('MM d, yy', new Date(parseInt('/Date(1224043200000)/'.substr(6)))); 

输出:

2008年10月15日




Mootools解决方案:

new Date(Date(result.AppendDts)).format('%x')

需要mootools-more。 在Firefox 3.6.3和IE 7.0.5730.13上使用mootools-1.2.3.1-more进行测试




在jQuery 1.5中,只要您使用json2.js来覆盖较旧的浏览器,您可以反序列化来自Ajax的所有日期,如下所示:

(function () {
    var DATE_START = "/Date(";
    var DATE_START_LENGTH = DATE_START.length;

    function isDateString(x) {
        return typeof x === "string" && x.startsWith(DATE_START);
    }

    function deserializeDateString(dateString) {
        var dateOffsetByLocalTime = new Date(parseInt(dateString.substr(DATE_START_LENGTH)));
        var utcDate = new Date(dateOffsetByLocalTime.getTime() - dateOffsetByLocalTime.getTimezoneOffset() * 60 * 1000);
        return utcDate;
    }

    function convertJSONDates(key, value) {
      if (isDateString(value)) {
        return deserializeDateString(value);
      }
      return value;
    }

    window.jQuery.ajaxSetup({
      converters: {
        "text json": function(data) {
          return window.JSON.parse(data, convertJSONDates);
        }
      }
    });
}());

我包含的逻辑假设您将所有日期从服务器发送为UTC(您应该); 然后消费者获取具有适当滴答值的JavaScript Date对象来反映这一点。 也就是说,在日期中调用getUTCHours()等将返回与服务器上相同的值,并且调用getHours()将返回用户本地时区中由其浏览器确定的值。

这不考虑带时区偏移的WCF格式,尽管这样做相对容易添加。




张贴在真棒线程:

var d = new Date(parseInt('/Date(1224043200000)/'.slice(6, -2)));
alert('' + (1 + d.getMonth()) + '/' + d.getDate() + '/' + d.getFullYear().toString().slice(-2));



仅供参考,对于在服务器端使用Python的任何人:datetime.datetime()。ctime()返回一个字符串,可以通过“new Date()”本地解析。 也就是说,如果您创建了一个新的datetime.datetime实例(例如datetime.datetime.now),则该字符串可以包含在JSON字符串中,然后可以将该字符串作为第一个参数传递给Date构造函数。 我还没有发现任何异常,但我还没有太严格地测试过它。




这令人沮丧。 我的解决方案是从ASP.NET的JavaScriptSerializer生成的值中解析出“/和/”,这样虽然JSON可能没有日期字面量,但它仍然被浏览器解释为日期,这就是我所知道的want: {"myDate":Date(123456789)}

为DateTime定制JavaScriptConverter?

我必须强调Roy Tinker的评论的准确性。 这不是合法的JSON。 这是一个肮脏,肮脏的黑客攻击服务器上的问题,以解决问题之前,它成为一个JavaScript问题。 它会阻塞JSON解析器。 我用它来起飞,但我不再使用它。 不过,我仍然觉得最好的答案在于改变服务器如何格式化日期,例如,如其他地方提到的ISO。




我最终将“字符添加到Panos的正则表达式中,以便在将对象写入内联脚本时摆脱由Microsoft序列化程序生成的字符:

所以如果你在你的C# code-behind有一个属性,就像是

protected string JsonObject { get { return jsSerialiser.Serialize(_myObject); }}

在你的aspx中你有

<script type="text/javascript">
    var myObject = '<%= JsonObject %>';
</script>

你会得到类似的东西

var myObject = '{"StartDate":"\/Date(1255131630400)\/"}';

注意双引号。

为了将这个转化为eval将正确反序列化的表单,我使用了:

myObject = myObject.replace(/"\/Date\((\d+)\)\/"/g, 'new Date($1)');

我使用Prototype并使用它,我补充说

String.prototype.evalJSONWithDates = function() {
    var jsonWithDates = this.replace(/"\/Date\((\d+)\)\/"/g, 'new Date($1)');
    return jsonWithDates.evalJSON(true);
}



检查日期ISO标准; 有点像这样:

yyyy.MM.ddThh:mm

它变成2008.11.20T22:18




下面是解析JSON日期的一个非常简单的解决方案。 根据您的要求使用以下功能。 你只需要将JSON格式的Date作为参数传递给下面的函数:

function JSONDate(dateStr) {
    var m, day;
    jsonDate = dateStr;
    var d = new Date(parseInt(jsonDate.substr(6)));
    m = d.getMonth() + 1;
    if (m < 10)
        m = '0' + m
    if (d.getDate() < 10)
        day = '0' + d.getDate()
    else
        day = d.getDate();
    return (m + '/' + day + '/' + d.getFullYear())
}

function JSONDateWithTime(dateStr) {
    jsonDate = dateStr;
    var d = new Date(parseInt(jsonDate.substr(6)));
    var m, day;
    m = d.getMonth() + 1;
    if (m < 10)
        m = '0' + m
    if (d.getDate() < 10)
        day = '0' + d.getDate()
    else
        day = d.getDate();
    var formattedDate = m + "/" + day + "/" + d.getFullYear();
    var hours = (d.getHours() < 10) ? "0" + d.getHours() : d.getHours();
    var minutes = (d.getMinutes() < 10) ? "0" + d.getMinutes() : d.getMinutes();
    var formattedTime = hours + ":" + minutes + ":" + d.getSeconds();
    formattedDate = formattedDate + " " + formattedTime;
    return formattedDate;
}



这可能也可以帮助你。

 function ToJavaScriptDate(value) { //To Parse Date from the Returned Parsed Date
        var pattern = /Date\(([^)]+)\)/;
        var results = pattern.exec(value);
        var dt = new Date(parseFloat(results[1]));
        return (dt.getMonth() + 1) + "/" + dt.getDate() + "/" + dt.getFullYear();
    }



如果你用JavaScript说,

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

你会发现它是正确的日期,并且你可以在任何地方使用任何框架的JavaScript代码。




最初的例子:

/Date(1224043200000)/  

并不反映WCF在使用内置的JSON序列化通过WCF REST发送日期时使用的格式。 (至少在.NET 3.5 SP1上)

我发现这里的答案很有帮助,但需要对正则表达式进行轻微的修改,因为看起来GMT时间偏移量被附加到WCF JSON中返回的数字(自1970年以来)。

在WCF服务中,我有:

[OperationContract]
[WebInvoke(
    RequestFormat = WebMessageFormat.Json,
    ResponseFormat = WebMessageFormat.Json,
    BodyStyle = WebMessageBodyStyle.WrappedRequest
    )]
ApptVisitLinkInfo GetCurrentLinkInfo( int appointmentsId );

ApptVisitLinkInfo的定义很简单:

public class ApptVisitLinkInfo {
    string Field1 { get; set; }
    DateTime Field2 { get; set; }
    ...
}

当“Field2”从服务返回为Json时,值为:

/Date(1224043200000-0600)/

注意包含的时区偏移量作为值的一部分。

修改后的正则表达式:

/\/Date\((.*?)\)\//gi

它稍微更热切,并且抓住了所有人之间的一切,而不仅仅是第一个数字。 结果1970年的时间,再加上时区偏移量都可以输入到eval中以获取日期对象。

用于替换的JavaScript结果行是:

replace(/\/Date\((.*?)\)\//gi, "new Date($1)");



Related