我见过JSON日期格式的许多不同标准:
"\"\\/Date(1335205592410)\\/\"" .NET JavaScriptSerializer
"\"\\/Date(1335205592410-0500)\\/\"" .NET DataContractJsonSerializer
"2012-04-23T18:25:43.511Z" JavaScript built-in JSON object
"2012-04-21T18:25:43-05:00" ISO 8601
哪一个是正确的?还是最好的?这方面有什么标准吗?
我认为这确实取决于用例。在许多情况下,使用适当的对象模型(而不是将日期呈现为字符串)可能更为有益,如下所示:
{
"person" :
{
"name" : {
"first": "Tom",
"middle": "M",
...
}
"dob" : {
"year": 2012,
"month": 4,
"day": 23,
"hour": 18,
"minute": 25,
"second": 43,
"timeZone": "America/New_York"
}
}
}
诚然,这比RFC 3339更冗长,但:
它也是人类可读的它实现了一个适当的对象模型(如在OOP中,只要JSON允许)它支持时区(而不仅仅是给定日期和时间的UTC偏移量)它可以支持更小的单位,如毫秒、纳秒。。。或者仅仅是小数秒它不需要单独的解析步骤(解析日期时间字符串),JSON解析器将为您完成一切轻松创建任何日期时间框架或任何语言的实现可以轻松扩展以支持其他日历刻度(希伯来文、中文、伊斯兰…)和时代(公元前、公元前…)10000年是安全的;-)(RFC 3339不是)支持全天日期和浮动时间(Javascript的Date.toJSON()不支持)
我不认为将日期序列化为JSON时真正需要正确的排序(如RFC 3339的funroll所指出的)。同样,这仅适用于具有相同时区偏移的日期时间。
仅供参考,我见过这种格式:
Date.UTC(2017,2,22)
它与$.getJSON()函数支持的JSONP一起工作。我不确定我会推荐这种方法。。。只是把它作为一种可能性,因为人们是这样做的。
FWIW:不要在通信协议中使用从epoch开始的秒数,也不要使用从epoth开始的毫秒数,因为由于闰秒的随机实现,这些都充满了危险(你不知道发送方和接收方是否都正确地实现了UTC闰秒)。
有点讨厌,但许多人认为UTC只是GMT的新名称——错了!如果您的系统没有实现闰秒,那么您使用的是GMT(尽管不正确,但通常称为UTC)。如果你完全实现了闰秒,你真的在使用UTC。未来的闰秒是未知的;IERS在必要时发布它们,并需要不断更新。如果您运行的系统试图实现闰秒,但包含过期的参考表(比您想象的更常见),那么您既没有GMT,也没有UTC,那么您的系统就假装是UTC。
这些日期计数器仅在以分解格式(y、m、d等)表示时才兼容。它们在历元格式中从不兼容。记住这一点。
以下代码对我有效。此代码将以DD-MM-YYYY格式打印日期。
DateValue=DateValue.substring(6,8)+"-"+DateValue.substring(4,6)+"-"+DateValue.substring(0,4);
否则,还可以使用:
DateValue=DateValue.substring(0,4)+"-"+DateValue.substring(4,6)+"-"+DateValue.substring(6,8);
我认为通用互操作性的最佳格式不是ISO-8601字符串,而是EJSON使用的格式:
{“myDateField”:{“$date”:<ms since epoch>}}
如下所述:https://docs.meteor.com/api/ejson.html
福利
解析性能:如果您将日期存储为ISO-8601字符串,那么如果您希望在该特定字段下有一个日期值,那么这是很好的,但是如果您有一个系统必须在没有上下文的情况下确定值类型,那么您将解析每个字符串的日期格式。无需日期验证:您不必担心日期的验证和验证。即使字符串与ISO-8601格式匹配,它也可能不是真正的日期;这绝不会发生在EJSON约会中。明确的类型声明:就通用数据系统而言,如果您希望在一种情况下将ISO字符串存储为字符串,而在另一种情况中存储真实的系统日期,则采用ISO-8601字符串格式的通用系统在机械上不允许这样做(没有转义技巧或类似的糟糕解决方案)。
结论
我知道,人类可读的格式(ISO-8601字符串)对于80%的用例来说是有用的,而且更方便,如果应用程序能够理解的话,确实不应该告诉任何人不要将日期存储为ISO-8601的字符串,但是对于一种普遍接受的传输格式来说,我们怎么能允许歧义和这么多验证的需要?
JSON本身没有日期格式,它不在乎任何人如何存储日期。然而,由于这个问题用javascript标记,我假设您想知道如何在JSON中存储javascript日期。您只需将日期传递给JSON.stringify方法,默认情况下,它将使用date.prototype.toJSON,而date.prototype.toISOString(MDN on date.toJSON):
const json = JSON.stringify(new Date());
const parsed = JSON.parse(json); //2015-10-26T07:46:36.611Z
const date = new Date(parsed); // Back to date object
我还发现每当我读取JSON字符串时,使用JSON.parse(JSON.pase上的MDN)的reviver参数将ISO字符串自动转换回javascript日期非常有用。
const isoDatePattern = new RegExp(/\d{4}-[01]\d-[0-3]\dT[0-2]\d:[0-5]\d:[0-5]\d\.\d+([+-][0-2]\d:[0-5]\d|Z)/);
const obj = {
a: 'foo',
b: new Date(1500000000000) // Fri Jul 14 2017, etc...
}
const json = JSON.stringify(obj);
// Convert back, use reviver function:
const parsed = JSON.parse(json, (key, value) => {
if (typeof value === 'string' && value.match(isoDatePattern)){
return new Date(value); // isostring, so cast to js date
}
return value; // leave any other value as-is
});
console.log(parsed.b); // // Fri Jul 14 2017, etc...
“2014-01-01T23:28:56.782Z”
日期以表示UTC时间(由Z表示)的标准可排序格式表示。ISO 8601还通过将Z替换为时区偏移的+或–值来支持时区:
“2014-02-01T09:28:56.321-10:00”
ISO 8601规范中的时区编码还有其他变体,但–10:00格式是当前JSON解析器支持的唯一TZ格式。一般来说,最好使用基于UTC的格式(Z),除非您特别需要确定生成日期的时区(只有在服务器端生成时才可能)。
NB:
var date = new Date();
console.log(date); // Wed Jan 01 2014 13:28:56 GMT-
1000 (Hawaiian Standard Time)
var json = JSON.stringify(date);
console.log(json); // "2014-01-01T23:28:56.782Z"
告诉你,这是首选方式,尽管JavaScript没有标准格式
// JSON encoded date
var json = "\"2014-01-01T23:28:56.782Z\"";
var dateStr = JSON.parse(json);
console.log(dateStr); // 2014-01-01T23:28:56.782Z