"正确"的JSON日期格式

Kam*_*eri 1071 javascript json

我已经看到了许多不同的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
Run Code Online (Sandbox Code Playgroud)

哪一个是正确的?还是最好的?这有什么标准吗?

fun*_*oll 1733

JSON本身没有指定日期应该如何表示,但JavaScript确实如此.

应该使用由发出的格式DatetoJSON方法:

2012-04-23T18:25:43.511Z

原因如下:

  1. 它具有人类可读性,但也很简洁

  2. 它正确排序

  3. 它包括小数秒,可以帮助重建年表

  4. 它符合ISO 8601

  5. ISO 8601已在国际上建立了十多年

  6. ISO 8601得到W3C,RFC3339XKCD的认可

话虽这么说,每个日期库都可以理解"自1970年以来的毫秒".所以为了便于携带,ThiefMaster是对的.

  • upvote提及和链接xkcd:D @ajorquera我通常使用momentjs.我在这方面也看到了IE的问题 (101认同)
  • 关于第二点,它在10000年之后没有正确排序.虽然我们有近8000年的时间来提出一种新的格式,所以它可能不是问题. (50认同)
  • 这也是根据[ECMA](http://es5.github.io/#x15.12.3)的首选表示:`JSON.stringify({'now':new Date()})"{"now": "2013-10-21T13:28:06.419Z"}"` (28认同)
  • 我会在列表中添加另一个重要原因:它与语言环境无关.如果你有一个像02-03-2014这样的日期,你需要更多信息才能知道它是指2月3日还是2月2日.这取决于是使用美国格式还是其他格式. (10认同)
  • 实际上,@ Erfa,因为`-`出现在`ASCII`中的数字之前,它将排序到100,000年之前就好了.,P (7认同)
  • @ gerard-van-helden与您的陈述相反,unix时间戳定义明确,始终为UTC. (6认同)
  • 你让我"得到XKCD认可":) (4认同)
  • 不幸的是,`JSON.parse()`不会重现日期对象,而是将其保存为字符串:`JSON.parse(JSON.stringify({'now':new Date()}))`赋予`{now:" 2016-03-30T15:49:18.369Z"}`. (3认同)
  • ISO8601 的伟大之处在于它包含多种格式可供选择! (3认同)
  • @DineiRockenbach Unix 时间是“自 1970 年 1 月 1 日星期四 00:00:00 协调世界时 (UTC) 以来经过的秒数,不计算闰秒”-因此它与 UTC 在闰秒上不匹配,但除此之外,它始终是 UTC。现在,不同表示之间的转换完全由您来决定。 (3认同)
  • XKCD 对 ISO 8601 格式的推动特别有趣,悬停提示说 _ISO 8601 于 06/05/88 发布,最近在 12/01/04_ 进行了修订,以突出混淆。 (3认同)
  • 在答案中引用 XKCD 可获得奖励积分。 (3认同)
  • 考虑到某些浏览器不解析ISO8601,例如safari. (2认同)
  • 将日期序列化为 JSON 时,“排序正确”有何相关性? (2认同)
  • 自1970年以来的秒数问题在于它不包括时区.你应该*不*使用它.永远.没有时区的日期总是本地化的,请注意这一点! (2认同)
  • 感谢您提及XKDC认可。让我开心! (2认同)
  • OP的问题是关于日期,而不是关于日期和时间。如何最好地表示没有时间的日期?例如,“出生日期”? (2认同)
  • 将“十多年”改为“半个世纪”。我们所熟知的 ISO 8601 标准于 1971 年首次作为 ISO 建议 2014 发布。 (2认同)

Thi*_*ter 121

JSON对日期一无所知..NET所做的是非标准的黑客/扩展.

我会使用一种格式,可以很容易地转换为DateJavaScript中的对象,即可以传递给它的对象new Date(...).最简单且可能最便携的格式是自1970年以来包含毫秒的时间戳.

  • 如果你走这条路,确保你不需要处理1970年以前的日期! (9认同)
  • 正如@BenDolman所说,这个"解决方案"没有适当地处理1970年1月1日(大纪元)之前的日期.此外,首先存在ISO8601的原因.在地球上,我们有称为"时区"的东西.那是几毫秒?JSON可能没有日期标准,但日期存在于JSON之外,并且__是一个标准.funroll的答案是正确的(另见:http://xkcd.com/1179/). (8认同)
  • 也许还值得一提的是,1970年以来的(毫秒)时间是不可预测的,因为我们有[闰秒](https://en.wikipedia.org/wiki/Leap_second).所以我不会使用if进行进程间通信和数据存储.然而,在程序内部使用它是很好的,因为它可以存储在一个整数中,从而为您带来一些性能优势. (5认同)
  • http://stackoverflow.com/questions/10286385/why-does-json-stringify-accept-date-objects - 让我们看看有人知道为什么FF表现得那样. (3认同)
  • Unix时间戳总是UTC,您在生成时间戳之前从本地时区转换,然后再返回到显示的本地时区,那里没有歧义. (3认同)
  • 这些评论中的每一条都说20世纪70年代以前的日期或未来的日期无法表现,这是对时代的误解.所有时间都是相对的,并且一旦你达到/低于1年,日期字符串将会真正地分解.无论你的时间是什么源时钟,它几乎肯定是基于时间段的代表性,所以你不是在制作它通过避免纪元时间更准确. (3认同)
  • 呃,我希望有一个错误...但至少firefox确实将它字符串化......好吧,它不是JSON标准的一部分所以我不会将Date对象提供给JSON序列化程序 - 它可能无法全部工作浏览器.显然,JSON序列化程序使用`toJSON()`函数(如果它存在于未知对象上)是一个常见的想法.至少Firefox会为Date对象执行此操作,而Date对象确实有这样的方法. (2认同)
  • 有些应用程序/库支持负时间戳。 (2认同)
  • 1970 年之前的日期可以通过负数字时间戳来处理。舍入时,需要注意舍入到负无穷大而不是零。以数字时间戳形式返回日期/时间的 Windows、Unix 和 Javascript API 会忽略闰秒(即每天有 86400 秒),因此如果通信协议规定所有日期都有 86400 秒,则有关其可预测性的争论不适用。如果应用程序/协议*确实*需要处理闰秒,则由于上述注释中已经说明的原因,不能使用数字时间戳。 (2认同)

Rus*_*Cam 40

没有正确的格式 ; 的JSON规范不以交换日期这就是为什么有这么多不同的方式来做到这一点指定的格式.

最好的格式可以说是ISO 8601格式的日期(见维基百科); 它是一种众所周知且广泛使用的格式,可以跨多种语言处理,非常适合互操作性.例如,如果您可以控制生成的json,则以json格式向其他系统提供数据,选择8601作为日期交换格式是一个不错的选择.

例如,如果您无法控制生成的json,那么您是来自几个不同现有系统的json的使用者,处理此问题的最佳方法是使用日期解析实用程序函数来处理预期的不同格式.

  • @ gnasher729你有链接吗? (3认同)
  • @mlissner,但这是一个最好的*观点*。ISO-8601是一个标准,但不是* JSON的标准*(即使我倾向于使用它);例如,Microsoft决定不使用它(http://msdn.microsoft.com/zh-cn/library/bb299886.aspx#intro_to_json_sidebarb)。最佳做法是坚持一项(明智的)约定,无论如何。正如我在回答中所述,处理此问题的最佳方法是定义一个可以处理预期格式的日期解析实用程序功能。如果您与使用不同格式的系统集成,则该功能应处理各种情况。 (2认同)
  • @RussCam,我们可以来回切换,但是如果有人问以 JSON 编码日期的最佳方法,他们会问在制作 JSON 时如何格式化日期(答案通常是 ISO-8601)。您正在回答相反的问题:如何在 JSON 日期制作完成后使用它们(尽管您的建议是合理的)。 (2认同)

Bry*_*sen 24

来自RFC 7493(I-JSON消息格式):

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`来解析该值. (2认同)

Mad*_*eka 22

“2014-01-01T23:28:56.782Z”

\n

日期以标准且可排序的格式表示,表示 UTC 时间(由 Z 表示)。ISO 8601 还通过将 Z 替换为时区偏移量的 + 或 \xe2\x80\x93 值来支持时区:

\n

“2014-02-01T09:28:56.321-10:00”

\n

ISO 8601 规范中的时区编码还有其他变体,但 \xe2\x80\x9310:00 格式是当前 JSON 解析器支持的唯一 TZ 格式。一般来说,\xe2\x80\x99 最好使用基于 UTC 的格式 (Z),除非您有特定需要确定生成日期的时区(仅在服务器端生成中可能)。

\n

注意:

\n
    var date = new Date();\n    console.log(date); // Wed Jan 01 2014 13:28:56 GMT- \n    1000 (Hawaiian Standard Time) \n        \n    var json = JSON.stringify(date);\n    console.log(json);  // "2014-01-01T23:28:56.782Z"\n
Run Code Online (Sandbox Code Playgroud)\n

告诉你这是首选方式,即使 JavaScript 没有标准格式

\n
// JSON encoded date\nvar json = "\\"2014-01-01T23:28:56.782Z\\"";\n\nvar dateStr = JSON.parse(json);  \nconsole.log(dateStr); // 2014-01-01T23:28:56.782Z\n
Run Code Online (Sandbox Code Playgroud)\n


小智 14

仅供参考我见过这种格式:

Date.UTC(2017,2,22)
Run Code Online (Sandbox Code Playgroud)

它适用于函数支持的JSONP$.getJSON().我不确定我是否会推荐这种方法......只是把它扔出去作为一种可能性,因为人们这样做.

FWIW:永远不要在通信协议中使用秒数,也不要使用自纪元以来的毫秒数,因为随着闰秒的随机实施,这些都充满了危险(你不知道发送方和接收方是否都能正确实现UTC闰秒).

一种宠物讨厌,但很多人认为UTC只是GMT的新名称 - 错!如果您的系统没有实现闰秒,那么您使用GMT(尽管不正确,通常称为UTC).如果您完全实现闰秒,那么您确实使用的是UTC.未来的闰秒无法知晓; 它们在必要时由IERS发布,需要不断更新.如果您正在运行一个试图实现闰秒但包含和过时的引用表(比您想象的更常见)的系统,那么您既没有GMT,也没有UTC,您有一个假装是UTC的不稳定系统.

这些日期计数器仅在以细分格式(y,m,d等)表示时才兼容.它们永远不会兼容时代格式.记在脑子里.

  • 我不会使用那种格式,但你提供的其他信息非常有用,谢谢! (4认同)

Ali*_*eza 6

首选的方法是使用2018-04-23T18:25:43.511Z...

下图显示了为什么这是首选方式:

JSON 日期

因此,正如您所看到的 Date 有一个本机 Method toJSON,它return采用这种格式,并且可以轻松地Date再次转换为......

  • 正确的!JSON 数据交换语法未指定标准:http://www.ecma-international.org/publications/files/ECMA-ST/ECMA-404.pdf 但实际上,ISO 8601 兼容格式更适合跨平台,包括JavaScript 运行时。 (2认同)

Jus*_*ijn 6

JSON 本身没有日期格式,它不关心任何人如何存储日期。但是,由于这个问题是用 javascript 标记的,我假设您想知道如何在 JSON 中存储 javascript 日期。您可以只向该JSON.stringify方法传递一个日期,它会Date.prototype.toJSON默认使用,它依次使用Date.prototype.toISOStringDate.toJSON 上的 MDN):

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
Run Code Online (Sandbox Code Playgroud)

我还发现,每当我读取 JSON 字符串时,使用(JSON.parse 上的 MDN)的reviver参数将 ISO 字符串自动转换回 javascript 日期很有用。JSON.parse

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...
Run Code Online (Sandbox Code Playgroud)


Sha*_*mad 5

如有疑问,只需按F12键(在Firefox中为Ctrl + K),然后转到现代浏览器的javascript Web控制台,然后编写以下代码:

new Date().toISOString()
Run Code Online (Sandbox Code Playgroud)

将输出:

“ 2019-07-04T13:33:03.969Z”

-

  • 所以,再一次,我的评论不是关于这是否是一个好的格式,而是关于**这个答案的文本中缺少什么**。如果有人对这种格式一无所知,并阅读了您的答案,他们*仍然*不会了解这种格式;他们甚至不知道它的名字。我的问题是提示应编辑到答案中的信息。 (9认同)