什么是JavaScript的有效日期时间字符串?

问题描述 投票:8回答:2

当使用JavaScript中new DateDate.parse,我不能只是通过任意日期格式。根据不同的格式,我得到的比我想甚至Invalid Date而不是一个日期对象的不同日期。有些日期格式在一个浏览器,但不是在别人打工。所以,我应该使用哪个日期时间格式?

其他问题:

  • 是不是所有的浏览器都支持相同的格式?如何Mozilla Firefox浏览器,谷歌Chrome,微软IE浏览器,微软的边缘,和苹果Safari浏览器手柄日期时间字符串?怎么样的Node.js?
  • 它有没有让当地的日期格式考虑吗?例如。如果我住在瑞士和日期格式为二零一八年七月三十零日,我可以使用new Date('30.07.2018')
  • 没有考虑本地时区考虑吗?
  • 我怎样才能从一个日期对象的日期时间字符串?
  • 如何检测无效的日期时间字符串?
  • 如何像Moment.js日期库处理的日期字符串?

如果你没有注意到,我回答我自己的问题(why?)。

javascript string date datetime time
2个回答
22
投票

The Essentials

JavaScript的正式支持ISO 8601扩展格式的简化。格式如下:YYYY-MM-DDTHH:mm:ss.sssZ。信T是日期/时间分离器和Z是时区偏移指定为Z(对于UTC)或任一+-后跟一个时间表达HH:mm。该格式的某些部分(例如,时间)可以省略。

需要注意的是年必须至少有四位数字,月/日/时/分/秒必须恰好包含两个数字,以毫秒为单位正好有三个数字。例如,99-1-1是不是有效的日期字符串。

这些都是有效的日期(时间)的字符串的一些例子:

  • 2018-12-30
  • 2018-12-30T20:59
  • 2018-12-30T20:59:00
  • 2018-12-30T20:59:00.000Z
  • 2018-12-30T20:59:00.000+01:00
  • 2018-12-30T20:59:00.000-01:00

当你省略了时区偏移量,日期时间被解释为用户本地时间。当你完全忽略了时间,日期被解释为UTC。

重要提示:所有现代的和合理的旧的浏览器和实现根据规范支持全长日期时间格式。不过,也有在日期(时间)的字符串的处理差异无时区(见“缺少时区偏移”下面)。你不应该没有时区(状态2018)使用日期时间字符串。而是通过一个unix timestamp in milliseconds or separate arguments for different parts of the dateDate构造。

大多数浏览器也支持一些其他的格式,但没有规定他们,因此并不适用于所有的浏览器相同的方式工作。如果在所有的,你应该只使用日期时间字符串格式如上所述。所有其他格式可能会在其他浏览器,甚至在同一浏览器的其他版本打破。

如果碰上Invalid Date,而不是一个日期对象,你最有可能使用的是无效的日期时间字符串。


现在有一个更详细一点。

Date Time String Format

ECMAScript中已自成立以来支持在new Datespecification)和Date.parsespecification)日期字符串(即JavaScript语言实现规范)。然而,第一个版本实际上并没有指定的日期时间格式。这改变了2009年的时候ES5与日期时间格式的规范出台。

基础

ECMAScript的指定Date Time String Format作为ISO 8601 Extended Format的简化。格式如下:YYYY-MM-DDTHH:mm:ss.sssZ

  • YYYY是一年0000的十进制数字到9999在proleptic公历。
  • -(连字符)从字面上两次出现的字符串中。
  • MM是一年中从01(一月)到12(12月)个月。
  • DD是本月01〜31日。
  • T出现字面上的字符串,来指示时间元素的开始。
  • HH是从午夜开始为两位十进制数从00到24已经过去的完整小时数。
  • :(结肠)字面上两次出现的字符串中。
  • mm是自小时开始为两位十进制数从00到59的完整分钟数。
  • ss是因为分钟为两位十进制数从00到59的开始的完整的秒数。
  • .(点)从字面上出现的字符串中。
  • sss是因为第二开始为三个十进制数字完成的毫秒数。
  • Z是时区偏移指定为“Z”(对于UTC)或任一“+”或“ - ”后随时间表达HH:mm

该规范还mentions,如果“字符串不符合[指定]格式化功能可能回落到任何具体的实施启发式或实现特定的日期格式”,这可能会导致在不同的浏览器不同的日期。

ECMAScript中不采取任何用户本地日期时间格式考虑进去,这意味着你不能使用国家或地区特定的日期时间格式。

短日期(和时间)形式

该规范还包括如下短格式。

此格式包括日期,只有形式:

  • YYYY
  • YYYY-MM
  • YYYY-MM-DD

它也包括“日期时间”形式的包括偏移所附的紧接着的具有可选的时区中的时间如下形式之一在上述日期的唯一形式之一:

  • THH:mm
  • THH:mm:ss
  • THH:mm:ss.sss

故障预置值

[...]如果MMDD字段不存在"01"被用作值。如果HHmm,或ss字段不存在"00"被用作值和一个缺席sss字段的值是"000"。当时间区偏移量不存在,日期只有形式解释为UTC时间和日期时间的形式被解释为本地时间。

请参阅“失踪时区偏移”下面的缺乏浏览器支持的更多信息。

外边界值的

在格式字符串非法值(出界外以及语法错误)表示格式字符串不是这种格式的有效实例。

例如,new Date('2018-01-32')new Date('2018-02-29')将导致Invalid Date

扩展年

ECMAScript中的日期时间格式还指定extended years这六个数字的年份值。这种延长一年字符串格式的例子看起来像+287396-10-12T08:59:00.992Z它表示在今年287396公元扩展几年的日期可以是正的或负。

日期API

ECMAScript中指定了一个宽范围的date object properties的。给定一个有效的日期对象,你可以使用Date.prototype.toISOString()得到有效的日期时间字符串。请注意,时区是UTC始终。

new Date().toISOString() // "2018-08-05T20:19:50.905Z"

另外,也可以检测是否日期对象有效或Invalid Date使用下面的函数。

function isValidDate(d) {
  return d instanceof Date && !isNaN(d);
}

来源及更多信息可以在Detecting an “invalid date” Date instance in JavaScript找到。

例子

Valid Date Time Formats

下面的日期时间格式都是有效的根据规范,并应在每个浏览器,Node.js的或其他实施支持ES2016或更高的工作。

2018
2018-01
2018-01-01
2018-01-01T00:00
2018-01-01T00:00:00
2018-01-01T00:00:00.000
2018-01-01T00:00:00.000Z
2018-01-01T00:00:00.000+01:00
2018-01-01T00:00:00.000-01:00
+002018-01-01T00:00:00.000+01:00

Invalid Date Time Formats

请注意,下面的例子是按照规范无效。然而,这并不意味着没有浏览器或其他执行它们解释为日期。请不要使用任何的下面,因为它们是非标准的日期时间格式,并在某些浏览器或浏览器版本可能会失败。

2018-1-1 // month and date must be two digits
2018-01-01T0:0:0.0 // hour/minute/second must be two digits, millisecond must be three digits
2018-01-01 00:00 // whitespace must be "T" instead
2018-01-01T00 // shortest time part must have format HH:mm
2018-01-01T00:00:00.000+01 // time zone must have format HH:mm

浏览器支持

今天,是与ES5规范于2009年推出。然而every modern and reasonably old browser supports the date time format,即使在今天(状态2018)是日期时间字符串不同的实现没有时区(请参阅“失踪时区偏移”下文)。如果您需要支持旧的浏览器或使用字符串没有一个时区,则不应使用日期时间字符串。相反,通过一个number of milliseconds since January 1, 1970, 00:00:00 UTCtwo or more arguments representing the different date partsDate构造。

Missing Time Zone Offset

ES5.1 incorrectly指出一个不存在时区的偏移值是“Z”与ISO 8601相矛盾这个错误固定在ES6 (ES2015)ES2016延长上(见下面的“更改到ECMAScript的规范”)。由于ES2016的,没有一个时区的日期时间字符串被解析为本地时间,而迄今为止,只有字符串被解析为UTC。

this answer,一些实现从未付诸实施在ES5.1指定的行为。其中一人似乎是Mozilla Firefox浏览器。似乎其他浏览器与ES2016(或更高版本)的规格而兼容是谷歌浏览器65+,微软的Internet Explorer 11和Microsoft边缘。苹果Safari浏览器(11.1.2)的当前版本不兼容,因为它错误地解析日期时间字符串作为没有UTC而不是本地时间的时区(例如2018-01-01T00:00)。

Legacy Date Time Formats

ES5于2009年在此之前推出日期时间字符串的规范,有迹象表明是由所有的浏览器不支持任何特定的格式。其结果是,每个浏览器供应商添加了不同的格式往往没有翻过不同的浏览器(和版本)工作的支持。对于古代历史的一个小例子,看date-formats

大多数浏览器还支持以不打破旧的网站的向后兼容这些传统格式。但它不是安全的依靠那些不规范的格式,因为它们可能会不一致或随时移除。

Date.prototype.toString()Date.prototype.toUTCString()

ES2018首次指定由Date.prototype.toString()Date.prototype.toUTCString()返回的日期格式。早在这之前,ECMA规范要求的Date构造和Date.parse正确解析由这些方法返回(即使它没有2018之前指定的格式)格式。

Date.prototype.toString()的例子返回值可能是这样的:

Sun Feb 03 2019 14:27:49 GMT+0100 (Central European Standard Time)

请注意,括号内的时区的名称是可选的,确切的名称是“依赖于实现”。

Date.prototype.toUTCString()返回一个相似的格式Date.prototype.toString()但具有零区偏移量的日期。一个例子格式可能是这样的:

Sun, 03 Feb 2019 13:27:49 GMT

请注意,有比较,平日和日月反转后一个逗号Date.prototype.toUTCString()

由于这些格式只被在2018年规定,你不应该依赖于他们在不同的实现(特别是旧的浏览器)同样的工作。

Node.js的

Node.js的是在V8 JavaScript引擎这也是谷歌浏览器使用运行。所以关于日期时间字符串格式相同的规范适用。由于代码在后端运行虽然,用户本地时间不影响时区,但只在服务器上的设置做。大多数平台主机的Node.js应用程序使用UTC作为其默认的时区服务(PaaS)提供商。

日期时间库

Moment.js

Moment.js是一个非常受欢迎的库来帮助在JavaScript日期的处理,同时也supports more formats比ECMAScript的规定。此外,Moment.js还支持creating date objects based on a string and a arbitrary format

世昕

Luxon支持ISO 8601,HTTP,RFC2822,SQL,和任意格式的parsing。但是,只有使用不同的功能不同的日期时间格式。

Changes to the ECMAScript Specifications

在ECMAScript的规范有关日期时间字符串格式的显着变化的列表。

ES2018变化

推出由Date.prototype.toString()Date.prototype.toUTCString()返回的日期格式规范。

ES2017变化

没有明显变化。

ES2016变化

如果时区偏移不存在,日期时间解释为本地时间。

当时间区偏移量不存在,日期只有形式解释为UTC时间和日期时间的形式被解释为本地时间。

ES6 (ES2015)变化

缺席的时区偏移的值是“Z”

如果时区偏移不存在,日期时间解释为本地时间。

Corrections and Clarifications in ECMAScript 2015 with Possible Compatibility Impact

如果一个时区偏移量不存在,则使用本地时区。 5.1版本不正确地指出,缺少时间段应解释为"z"

Date Time String Format: default time zone difference from ES5 not web-compatible对这一变化的更多细节。

ES5.1变化

如果MMDD字段不存在“01”被用作值。如果HHmm,或ss字段不存在“00”被用作值和一个缺席sss字段的值是“000”。缺席的时区偏移的值是“Z”

ES5变化

首先推出的日期时间字符串格式ECMAScript规范的。

ECMAScript中定义了基于ISO 8601扩展格式的简化日期时间的字符串互换格式。格式如下:YYYY-MM-DDTHH:mm:ss.sssZ

还引入了Date.prototype.toISOString()返回在指定格式的日期时间字符串。

ES3变化

不赞成Date.prototype.toGMTString(),并在段提的是,这些方法返回的格式必须是Date.parse(x.toUTCString())的implmentations正确解析的与Date.parse替换它。请注意,由Date.parse(x.toUTCString())返回的格式为“依赖于实现”。

ES2变化

没有明显变化。

初始规格:ES1

ES1介绍new Date(value)Date.parse(value)使用日期时间字符串。然而,它没有指定实际日期(时间)格式,它甚至指出,

[...]通过Date.parse产生的值是依赖于实现的[...]

该规范还提到,

如果x是任何Date对象[...],那么所有的下列表达式应该在执行产生相同的数值[...]

  • [...]
  • Date.parse(x.toString())
  • Date.parse(x.toGMTString())

然而,无论Date.prototype.toString()Date.prototype.toGMTString()的返回值被指定为“实现相关”。


1
投票

所以,我应该使用哪个日期时间格式?

一般的建议是,因为它是不可靠的,不使用内置的分析器所有,所以答案为“应该”是“无”。见Why does Date.parse give incorrect results?

然而,随着海峡说,你可能可以使用ECMA-262带有时区指定的格式:YYYY-MM-DDTHH:mm:ss.sssZYYYY-MM-DDTHH:mm:ss.sss±HH:mm,不信任任何其他格式。

是不是所有的浏览器都支持相同的格式?

没有。

如何Mozilla Firefox浏览器,谷歌Chrome,微软IE浏览器,微软的边缘,和苹果Safari浏览器手柄日期时间字符串?

不同。比ECMA-262格式的任何其他依赖于实现,并且有在解析的ECMA-262格式错误。

怎么样的Node.js?

可能不同了,见上面。

它有没有让当地的日期格式考虑吗?例如。如果我住在瑞士和日期格式为二○一八年七月三十○日,我可以使用新的日期('30 .07.2018' )?

也许。因为它不是标准的格式,解析与实现有关,所以也许,也许不是。

没有考虑本地时区考虑吗?

它使用主机时区偏移,其中字符串被解析为地方和生成字符串中使用本地时间显示。否则,它使用UTC(和内部时间值是UTC)。

我怎样才能从一个日期对象的日期时间字符串?

Date.parse.toString,或见Where can I find documentation on formatting a date in JavaScript?

如何检测无效的日期时间字符串?

其中第3个回答here应该回答的。

如何像Moment.js日期库处理的日期字符串?

他们分析他们基于无论是默认或提供的格式。读出的源(例如fecha.js是一个简单的解析器和格式化器具有良好写的,容易跟随代码)。

解析器并不难写,但试图猜测输入格式(如内置解析器倾向于做)是误人子弟,不可靠的,不同实现不一致。所以解析器应要求格式提供,除非输入字符串是解析器的默认格式。

PS

有变化的字符串的格式实现必须在ECMAScript中2019(目前草案)的解析和格式化支持,但我觉得一般的建议,以避免内置解析器将站在一段时间未定。

© www.soinside.com 2019 - 2024. All rights reserved.