jquery - 如何格式化Microsoft JSON日期?
asp.net ajax (20)
更新
我们有一个内部用户界面库,它必须处理微软的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路由才能使日期在全局就地解析 - 否则您需要在更大的个案基础解析后转换它们。
我正在使用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;
}
该解决方案从回调方法中获得了我的对象,并使用日期格式库正确显示了页面上的日期。
点击此处查看演示
的JavaScript / jQuery的
var = MyDate_String_Value = "/Date(1224043200000)/"
var value = new Date
(
parseInt(MyDate_String_Value.replace(/(^.*\()|([+-].*$)/g, ''))
);
var dat = value.getMonth() +
1 +
"/" +
value.getDate() +
"/" +
value.getFullYear();
结果 - “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进行测试
JSON没有内置的日期类型。 这看起来像某个时代的秒/毫秒数。 如果您知道该时代,您可以通过在适当的时间内添加来创建日期。
下面是解析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;
}
不要过度考虑这一点。 就像我们已经做了几十年一样,从1970年1月1日午夜GMT / UTC /&c开始的实际标准时代,以秒为单位(或毫秒)从这个时代开始传递一个数字偏移量。 JavaScript喜欢它,Java喜欢它,C喜欢它,而互联网喜欢它。
你可以用它从JSON获取日期:
var date = eval(jsonDate.replace(/\/Date\((\d+)\)\//gi, "new Date($1)"));
然后,您可以使用JavaScript日期格式脚本(缩小和压缩后为1.2 KB)来按需要显示它。
使用jQuery UI日期选择器 - 如果你已经包含jQuery UI,那么这种方法才有意义:
$.datepicker.formatDate('MM d, yy', new Date(parseInt('/Date(1224043200000)/'.substr(6))));
输出:
2008年10月15日
在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格式,尽管这样做相对容易添加。
在页面中添加jQuery UI插件:
function DateFormate(dateConvert) {
return $.datepicker.formatDate("dd/MM/yyyy", eval('new ' + dateConvert.slice(1, -1)));
};
如果你用JavaScript说,
var thedate = new Date(1224043200000);
alert(thedate);
你会发现它是正确的日期,并且你可以在任何地方使用任何框架的JavaScript代码。
对于那些使用Newtonsoft Json.NET ,请阅读如何通过IE8中的Native JSON,Firefox 3.5和Json.NET来实现 。
此外,有关更改Json.NET编写日期格式的文档很有用: 使用Json.NET序列化日期
对于那些懒惰的人来说,这里是快速的步骤。 由于JSON具有松散的DateTime实现,因此您需要使用IsoDateTimeConverter()
。 请注意,由于Json.NET 4.5默认的日期格式是ISO,所以下面的代码是不需要的。
string jsonText = JsonConvert.SerializeObject(p, new IsoDateTimeConverter());
JSON将通过
"fieldName": "2009-04-12T20:44:55"
最后,一些JavaScript将ISO日期转换为JavaScript日期:
function isoDateReviver(value) {
if (typeof value === 'string') {
var a = /^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2}(?:\.\d*)?)(?:([\+-])(\d{2})\:(\d{2}))?Z?$/.exec(value);
if (a) {
var utcMilliseconds = Date.UTC(+a[1], +a[2] - 1, +a[3], +a[4], +a[5], +a[6]);
return new Date(utcMilliseconds);
}
}
return value;
}
我是这样使用它的
$("<span />").text(isoDateReviver(item.fieldName).toLocaleString()).appendTo("#" + divName);
您还可以使用JavaScript库http://momentjs.com/ ,它在计划时派上用场,处理不同的本地化格式,并使用日期值执行其他操作:
function getMismatch(id) {
$.getJSON("Main.aspx?Callback=GetMismatch",
{ MismatchId: id },
function (result) {
$("#AuthMerchId").text(result.AuthorizationMerchantId);
$("#SttlMerchId").text(result.SettlementMerchantId);
$("#CreateDate").text(moment(result.AppendDts).format("L"));
$("#ExpireDate").text(moment(result.ExpiresDts).format("L"));
$("#LastUpdate").text(moment(result.LastUpdateDts).format("L"));
$("#LastUpdatedBy").text(result.LastUpdateNt);
$("#ProcessIn").text(result.ProcessIn);
}
);
return false;
}
设置本地化与向项目添加配置文件(在momentjs.com上获得它们)并配置语言一样简单:
moment.lang('de');
我得到这样的日期:
"/Date(1276290000000+0300)/"
在某些示例中,日期格式稍有不同:
"/Date(12762900000000300)/"
"Date(1276290000000-0300)"
等等
所以我想出了以下RegExp:
/\/+Date\(([\d+]+)\)\/+/
最终的代码是:
var myDate = new Date(parseInt(jsonWcfDate.replace(/\/+Date\(([\d+-]+)\)\/+/, '$1')));
希望能帮助到你。
更新:我发现这个来自Microsoft的链接:我如何使用JSON序列化日期?
这看起来就像我们都在寻找的那个。
我还必须寻找解决这个问题的办法,最终我遇到了moment.js这是一个很好的库,可以解析这个日期格式等等。
var d = moment(yourdatestring)
它为我节省了一些头痛,所以我想我会分享给你。 :)
你可以在这里找到更多关于它的信息: http://momentjs.com/ : http://momentjs.com/
最初的例子:
/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)");
评估是没有必要的。 这将工作正常:
var date = new Date(parseInt(jsonDate.substr(6)));
substr函数取出“/ Date(”部分,parseInt函数获取整数并在最后忽略“)/”。 生成的数字被传入Date构造函数。
编辑:我故意省略基数(第二个参数parseInt); 看到我下面的评论 。 另外,我完全同意Rory的评论 :ISO-8601日期比这种旧格式更受欢迎 - 所以这种格式通常不应该用于新开发。 查看卓越的Json.NET库,以获得使用ISO-8601格式序列化日期的绝佳选择。
对于ISO-8601格式化的JSON日期,只需将该字符串传递给Date构造函数:
var date = new Date(jsonDate); //no ugly parsing needed; full timezone support
这些答案的每一个都有一个共同点:它们都将日期存储为单个值(通常是一个字符串)。
另一种选择是利用JSON的固有结构,并将日期表示为数字列表:
{ "name":"Nick",
"birthdate":[1968,6,9] }
当然,你必须确保对话的两端同意格式(年,月,日)以及哪些字段是日期,......但它的优点是完全避免了日期问题字符串转换。 这是所有的数字 - 根本没有任何字符串。 此外,使用顺序:年,月,日也允许按日期进行适当排序。
只是在这里考虑一下 - JSON日期不必存储为字符串。
这样做的另一个好处是,您可以通过利用CouchDB处理数组值的查询的方式轻松(有效地)选择给定年份或月份的所有记录。
这可能也可以帮助你。
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();
}
var newDate = dateFormat(jsonDate, "mm/dd/yyyy");
有没有使用jQuery库的另一种选择?