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

标签 javascript string date datetime time

在JavaScript中使用new DateDate.parse时,我不能仅传递任意日期格式。根据格式的不同,我得到的日期可能会不同,甚至会得到Invalid Date而不是日期对象。某些日期格式只能在一种浏览器中使用,而不能在其他浏览器中使用。那么我应该使用哪种日期时间格式?

其他问题:

  • 所有浏览器都支持相同格式吗? Mozilla Firefox,Google Chrome,Microsoft Internet Explorer,Microsoft Edge和Apple Safari如何处理日期时间字符串?那Node.js呢?
  • 是否考虑本地日期格式?例如。如果我居住在瑞士且日期格式为30.07.2018,可以使用new Date('30.07.2018')吗?
  • 是否考虑本地时区?
  • 如何从日期对象获取日期时间字符串?
  • 如何检测无效的日期时间字符串?
  • 如何像Moment.js这样的日期库处理日期字符串?

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

    最佳答案

    要点
    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 date传递给Date构造函数。
    大多数浏览器还支持其他一些格式,但未指定它们,因此不能在所有浏览器中以相同的方式工作。
    如果有的话,您应该只使用上面说明的日期时间字符串格式。
    其他所有格式可能会在其他浏览器甚至同一浏览器的其他版本中损坏。
    如果遇到Invalid Date而不是日期对象,则很可能使用了无效的日期时间字符串。

    现在有更多细节。
    日期时间字符串格式
    自诞生以来,ECMAScript(JavaScript语言实现的规范)一直支持 new Date (specification)和 Date.parse (specification)中的日期字符串。
    但是,第一个版本实际上并未指定日期时间格式。
    在2009年ES5引入了日期时间格式规范后,情况发生了变化。
    基础
    ECMAScript指定Date Time String Format作为ISO 8601 Extended Format的简化。格式如下:YYYY-MM-DDTHH:mm:ss.sssZ
    • YYYY is the decimal digits of the year 0000 to 9999 in the proleptic Gregorian calendar.
    • - (hyphen) appears literally twice in the string.
    • MM is the month of the year from 01 (January) to 12 (December).
    • DD is the day of the month from 01 to 31.
    • T appears literally in the string, to indicate the beginning of the time element.
    • HH is the number of complete hours that have passed since midnight as two decimal digits from 00 to 24.
    • : (colon) appears literally twice in the string.
    • mm is the number of complete minutes since the start of the hour as two decimal digits from 00 to 59.
    • ss is the number of complete seconds since the start of the minute as two decimal digits from 00 to 59.
    • . (dot) appears literally in the string.
    • sss is the number of complete milliseconds since the start of the second as three decimal digits.
    • Z is the time zone offset specified as "Z" (for UTC) or either "+" or "-" followed by a time expression HH:mm

    该规范还表示,如果“字符串不符合[指定的]格式,则该函数可能会退回到任何特定于实现的启发式或特定于实现的日期格式”,这可能导致不同的浏览器中的日期不同。
    ECMAScript不考虑任何用户本地日期时间格式,这意味着您不能使用国家或地区特定的日期时间格式。
    短日期(和时间)表格
    该规范还包括以下较短的格式。

    This format includes date-only forms:

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

    It also includes “date-time” forms that consist of one of the above date-only forms immediately followed by one of the following time forms with an optional time zone offset appended:

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

    后备值

    [...] If the MM or DD fields are absent "01" is used as the value. If the HH, mm, or ss fields are absent "00" is used as the value and the value of an absent sss field is "000". When the time zone offset is absent, date-only forms are interpreted as a UTC time and date-time forms are interpreted as a local time.


    有关缺少浏览器支持的更多信息,请参见下面的“缺少时区偏移”。
    超出界限的值

    Illegal values (out-of-bounds as well as syntax errors) in a format string means that the format string is not a valid instance of this format.


    例如,new Date('2018-01-32')new Date('2018-02-29')将产生Invalid Date
    延长年
    ECMAScript的日期时间格式还指定mentions,它是六位数的年份值。
    这种扩展的年份字符串格式的示例类似于+287396-10-12T08:59:00.992Z,它表示公元287396年的日期。
    延长年份可以是正数或负数。
    日期API
    ECMAScript指定了广泛的extended years
    给定有效的日期对象,可以使用date object properties获取有效的日期时间字符串。
    请注意,时区始终为UTC。
    new Date().toISOString() // "2018-08-05T20:19:50.905Z"
    
    也可以使用以下函数检测日期对象是否有效或Date.prototype.toISOString()
    function isValidDate(d) {
      return d instanceof Date && !isNaN(d);
    }
    
    来源和更多信息可以在 Invalid Date 中找到。
    例子
    有效的日期时间格式
    根据规范,以下日期时间格式均有效,并且应在所有支持ES2016或更高版本的浏览器,Node.js或其他实现中使用。
    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
    
    无效的日期时间格式
    请注意,根据规范,以下示例无效。
    但是,这并不意味着没有浏览器或其他实现会将它们解释为日期。请不要使用以下的任何日期时间格式,因为它们是非标准的,并且在某些浏览器或浏览器版本中可能会失败。
    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
    
    浏览器支持
    今天,Detecting an “invalid date” Date instance in JavaScript随2009年ES5规范一起引入。
    但是,即使在今天(状态2018),对于不带时区的日期时间字符串也有不同的实现方式(请参阅下面的“缺少时区偏移”)。
    如果需要支持较旧的浏览器或使用不带时区的字符串,则不应使用日期时间字符串
    相反,传递every modern and reasonably old browser supports the date time format
    number of milliseconds since January 1, 1970, 00:00:00 UTCDate构造函数。
    缺少时区偏移
    ES5.1 two or more arguments representing the different date parts指出,缺少时区偏移的值为“Z”,与ISO 8601矛盾。
    此错误已在incorrectly中修复,并在ES6 (ES2015)中扩展(请参见下面的“对ECMAScript规范的更改”)。
    从ES2016开始,不带时区的日期时间字符串将解析为本地时间,而仅将日期字符串解析为UTC。
    根据ES2016,某些实现从未实现ES5.1中指定的行为。
    其中之一似乎是Mozilla Firefox。
    其他似乎符合ES2016(及更高版本)规范的浏览器是Google Chrome 65 +,Microsoft Internet Explorer 11和Microsoft Edge。
    当前版本的Apple Safari(11.1.2)不兼容,因为它错误地将不带时区的日期时间字符串(例如2018-01-01T00:00)解析为UTC而不是本地时间。
    旧版日期时间格式
    ES5在2009年引入了日期时间字符串规范。
    在此之前,没有所有浏览器都支持的指定格式。
    结果,每个浏览器供应商都增加了对不同格式的支持,这些格式通常无法在不同浏览器(和版本)上使用。
    有关古代历史的一个小例子,请参见this answer
    大多数浏览器仍支持那些旧格式,以免破坏较旧网站的向后兼容性。
    但是依靠这些非标准格式并不安全,因为它们可能会不一致或随时被删除。Date.prototype.toString()Date.prototype.toUTCString()ES2018首次指定date-formats Date.prototype.toString() 返回的日期格式。
    早在此之前,ECMA规范就要求Date.prototype.toUTCString()构造函数和Date正确解析这些方法返回的格式(即使在2018年之前未指定格式)。Date.parse的示例返回值可能如下所示:
    Sun Feb 03 2019 14:27:49 GMT+0100 (Central European Standard Time)
    
    请注意,方括号中的时区名称是可选的,确切名称是“与实现有关的”。Date.prototype.toString()以类似于Date.prototype.toUTCString()的格式返回日期,但时区偏移为零。示例格式可能如下所示:
    Sun, 03 Feb 2019 13:27:49 GMT
    
    请注意,与Date.prototype.toString()相比,在将工作日和日期月份反转之后,会有一个逗号,
    由于这些格式仅在2018年才指定,因此您不应该依赖它们在不同的实现方式(尤其是较旧的浏览器)中同样有效地工作。
    Node.js
    Node.js在V8 JavaScript引擎上运行,该引擎也在Google Chrome中使用。
    因此,适用于日期时间字符串格式的相同规范。
    由于代码在后端运行,因此用户本地时间不会影响时区,而只会影响服务器上的设置。
    托管Node.js应用程序的大多数平台即服务(PaaS)提供程序都使用UTC作为其默认时区。
    日期时间库
    Moment.js
    Date.prototype.toUTCString() 是一个非常流行的库,可以帮助处理JavaScript中的日期,并且它也是ECMAScript指定的Moment.js
    此外,Moment.js还支持supports more formats
    卢克森
    creating date objects based on a string and a arbitrary format支持ISO 8601,HTTP,RFC2822,SQL和任意格式的Luxon。但只能对不同的日期时间格式使用不同的功能。
    ECMAScript规范的更改
    ECMAScript规范中有关日期时间字符串格式的显着更改的列表。
    parsing 中的更改
    介绍ES2018 Date.prototype.toString() 返回的日期格式的规范。
    Date.prototype.toUTCString() 中的更改
    没有明显的变化。
    ES2017 中的更改

    If the time zone offset is absent, the date-time is interpreted as a local time.

    When the time zone offset is absent, date-only forms are interpreted as a UTC time and date-time forms are interpreted as a local time.


    ES2016 中的更改

    The value of an absent time zone offset is “Z”.

    If the time zone offset is absent, the date-time is interpreted as a local time.


    ES6 (ES2015):

    If a time zone offset is not present, the local time zone is used. Edition 5.1 incorrectly stated that a missing time zone should be interpreted as "z".


    有关该更改的更多详细信息,请参见Corrections and Clarifications in ECMAScript 2015 with Possible Compatibility Impact
    Date Time String Format: default time zone difference from ES5 not web-compatible 中的更改

    If the MM or DD fields are absent “01” is used as the value. If the HH, mm, or ss fields are absent “00” is used as the value and the value of an absent sss field is “000”. The value of an absent time zone offset is “Z”.


    ES5.1 中的更改
    首先将日期时间字符串格式引入ECMAScript规范。

    ECMAScript defines a string interchange format for date-times based upon a simplification of the ISO 8601 Extended Format. The format is as follows: YYYY-MM-DDTHH:mm:ss.sssZ


    还介绍了Date.prototype.toISOString(),它以指定的格式返回日期时间字符串。
    ES5 中的更改
    弃用Date.prototype.toGMTString()并在本节中提到Date.parse(x.toUTCString())可以正确解析这些方法返回的格式,而在本节中将其替换为Date.parse。请注意,Date.parse(x.toUTCString())返回的格式是“与实现有关的”。
    ES3 中的更改
    没有明显的变化。
    初始规范:ES2
    ES1引入了要在new Date(value)Date.parse(value)中使用的日期时间字符串。
    但是,它没有指定实际的日期(时间)格式,甚至指出

    [...] the value produced by Date.parse is implementation dependent [...]


    规范中还提到

    If x is any Date object [...], then all of the following expressions should produce the same numeric value in that implementation [...]:

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

    但是,Date.prototype.toString()Date.prototype.toGMTString()的返回值都被指定为“依赖于实现”。

    关于javascript - JavaScript中有效的日期时间字符串是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51715259/

    相关文章:

    javascript - 遇到错误 : Model is not defined

    ruby - Ruby 是否支持逐字字符串?

    date - 如何使用 Node.js 和 Mongoose 查询日期?

    javascript - 如何从动态添加的(使用 javascript)元素中获取值?

    javascript - 在 JavaScript 中,是否可以保存点击触发器并稍后重新应用?

    c - Arduino(C语言)解析带分隔符的字符串(通过串口输入)

    python - Python 2/3 中的编码/解码有什么区别

    javascript - 什么可以使 Date.parse 返回不同的值?

    sql - 获取 SQL 周数

    javascript - 如何将所有复选框放入一个对象数组中并标记选中的复选框