我见过很多不同的 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
哪一个是正确的?还是最好的?这有什么标准吗?
strings
、numbers
、true
、false
、null
、objects
和 arrays
JSON 本身不指定日期应如何表示,但 JavaScript 会。
2012-04-23T18:25:43.511Z
原因如下:
它易于阅读,但也简洁 正确排序 它包括小数秒,可以帮助重新建立年表 它符合 ISO 8601 ISO 8601 在国际上已经建立了十多年 ISO 8601 得到 W3C、RFC3339 和 XKCD 的认可
话虽如此,每个编写的日期库都可以理解“自 1970 年以来的毫秒数”。因此,为了便于携带,ThiefMaster 是正确的。
JSON 对日期一无所知。 .NET 所做的是非标准的 hack/扩展。
我会使用一种在 JavaScript 中可以轻松转换为 Date
对象的格式,即可以传递给 new Date(...)
的格式。最简单且可能最便携的格式是自 1970 年以来包含毫秒的时间戳。
没有正确的格式; JSON specification 没有指定交换日期的格式,这就是为什么有这么多不同的方法可以做到这一点。
最好的格式可以说是用 ISO 8601 format (see Wikipedia) 表示的日期;它是一种众所周知且广泛使用的格式,可以跨多种不同的语言进行处理,因此非常适合互操作性。如果您对生成的 json 有控制权,例如,您以 json 格式向其他系统提供数据,则选择 8601 作为日期交换格式是一个不错的选择。
如果您无法控制生成的 json,例如,您是来自多个不同现有系统的 json 消费者,则处理此问题的最佳方法是使用日期解析实用程序函数来处理预期的不同格式。
从 RFC 7493 (The I-JSON Message Format ):
I-JSON 代表 Internet JSON 或 Interoperable JSON,具体取决于您询问的对象。
协议通常包含旨在包含时间戳或持续时间的数据项。建议将所有此类数据项表示为 ISO 8601 格式的字符串值,如 RFC 3339 中所指定,附加限制是使用大写而不是小写字母,不默认包含时区,以及可选的尾随秒数即使它们的值为“00”,也包括在内。还建议所有包含持续时间的数据项都符合 RFC 3339 附录 A 中的“持续时间”产生式,并具有相同的附加限制。
Date().toISOString()
和 Date().toJSON()
生成的格式,其限制是 Date
不跟踪时区值,因此始终发出 UTC (Z
) 时区的时间戳。可以使用 new Date("...")
和 Date.parseDate
解析该值。
如有疑问,只需按 F12(在 Firefox 中为 Ctrl+Shift+K)进入现代浏览器的 javascript Web 控制台并编写以下内容:
new Date().toISOString()
将输出:
“2019-07-04T13:33:03.969Z”
达达!!
仅供参考,我已经看到使用这种格式:
Date.UTC(2017,2,22)
它适用于 $.getJSON()
函数支持的 JSONP。不确定我是否会推荐这种方法......只是把它作为一种可能性扔出去,因为人们正在这样做。
FWIW:永远不要在通信协议中使用自纪元以来的秒数,也不要使用自纪元以来的毫秒数,因为由于闰秒的随机实现(您不知道发送方和接收方是否都正确实现了 UTC 闰秒),这些都充满了危险。
有点讨厌,但很多人认为 UTC 只是 GMT 的新名称——错了!如果您的系统没有实现闰秒,那么您使用的是 GMT(尽管不正确,但通常称为 UTC)。如果您确实完全实现了闰秒,那么您确实在使用 UTC。未来的闰秒无法得知;它们会在必要时由 IERS 发布,并且需要不断更新。如果您正在运行的系统尝试实现闰秒但包含过期的参考表(比您想象的更常见),那么您既没有 GMT,也没有 UTC,那么您的系统就会伪装成 UTC。
这些日期计数器仅在以分解格式(y、m、d 等)表示时才兼容。它们从不兼容 epoch 格式。记在脑子里。
“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),除非您特别需要确定生成日期的时区(仅在服务器端生成中可能)。
注意:
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
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
(MDN on JSON.parse) 的 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...
首选方法是使用 2018-04-23T18:25:43.511Z
...
下图显示了为什么这是首选方式:
https://i.stack.imgur.com/HhBOj.png
如您所见,Date 有一个本机方法 toJSON
,它是这种格式的 return
,并且可以很容易地再次转换为 Date
...
在 Sharepoint 2013 中,以 JSON 格式获取数据没有将日期转换为仅日期格式的格式,因为该日期应为 ISO 格式
yourDate.substring(0,10)
这可能对你有帮助
我相信通用互操作性的最佳格式不是 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 字符串,如果这是他们的应用程序的话理解,但是对于应该保证某些值肯定是日期的普遍接受的传输格式,我们怎么能允许模棱两可并需要如此多的验证?
解析服务器对我有用
{
"ContractID": "203-17-DC0101-00003-10011",
"Supplier":"Sample Co., Ltd",
"Value":12345.80,
"Curency":"USD",
"StartDate": {
"__type": "Date",
"iso": "2017-08-22T06:11:00.000Z"
}
}
对此只有一个正确答案,而且大多数系统都会出错。自纪元以来的毫秒数,即 64 位整数。时区是一个 UI 问题,在 app 层或 db 层没有业务。为什么你的数据库关心什么是什么时区,当你知道它将把它存储为一个 64 位整数时,然后进行转换计算。
去掉无关的位,将日期视为 UI 上的数字。您可以使用简单的算术运算符来执行查询和逻辑。
以下代码对我有用。此代码将以 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);
我认为这真的取决于用例。在许多情况下,使用适当的对象模型(而不是将日期呈现为字符串)可能更有益,如下所示:
{
"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 解析器将为您做所有事情
使用任何日期时间框架或任何语言的实现轻松创建
可以轻松扩展以支持其他日历刻度(希伯来语、汉语、伊斯兰...)和时代(AD、BC、...)
10000 年是安全的;-)(RFC 3339 不是)
支持全天日期和浮动时间(Javascript 的 Date.toJSON() 不支持)
我不认为正确的排序(如 funroll 对 RFC 3339 所述)是在将日期序列化为 JSON 时真正需要的功能。这也仅适用于具有相同时区偏移的日期时间。
post contains wrong information, is poorly researched, or fails to communicate information
,您应该投反对票。请解释您对这个答案投反对票的原因之一。
JSON.stringify({'now': new Date()}) "{"now":"2013-10-21T13:28:06.419Z"}"
-
出现在ASCII
中的数字之前,它会一直排序到 100,000 年。 ;P