2024年PHP日本大会

支持的日期和时间格式

本节以类似BNF的格式描述了DateTimeImmutableDateTimedate_create_immutable()date_create()date_parse()strtotime()解析器理解的所有不同格式。这些格式按部分分组。在大多数情况下,来自不同部分的格式(由空格、逗号或点分隔)可以在同一个日期/时间字符串中使用。对于每个支持的格式,都给出了一个或多个示例,以及该格式的描述。格式中单引号内的字符不区分大小写('t'可以是tT),双引号内的字符区分大小写("T"只能是T)。

要格式化DateTimeImmutableDateTime对象,请参考DateTimeInterface::format()方法的文档。

应该考虑一组通用的规则。

  1. 解析器允许每个单位(年、月、日、时、分、秒)使用全范围的值。对于年份,只有4位数字;对于月份,为0-12;对于日期,为0-31;对于小时,为0-24;对于分钟,为0-59。
  2. 秒允许60,因为有时带有闰秒的日期字符串确实会出现。但是PHP实现了Unix时间,其中“60”不是有效的秒数,因此会溢出。
  3. strtotime()如果任何数字超出范围,则返回false,而DateTimeImmutable::__construct()则抛出异常。
  4. 如果字符串包含日期,则所有时间元素都重置为0。
  5. 如果给定字符串中存在任何部分时间,则所有较低位的时间元素都将重置为0。
  6. 解析器很简单,不会进行任何检查以使其更快(更通用)。
  7. 除了单个时间元素的规则外,解析器还理解更具体的复合格式,例如解析Unix时间戳(@1690388256)和ISO周日期(2008-W28-3)。
  8. 如果提供了无效日期,则会进行额外的检查

    <?php
    $res
    = date_parse("2015-09-31");
    var_dump($res["warnings"]);
    ?>

    上面的例子将输出

    array(1) {
      [11] =>
      string(27) "The parsed date was invalid"
    }
    

  9. 现在已经可以处理极端情况,但是必须使用DateTimeImmutable::createFromFormat()并提供正确的格式。

    <?php
    $res
    = DateTimeImmutable::createFromFormat("Y-m-d", "2015-09-34");
    var_dump($res);

    上面的例子将输出

    object(DateTimeImmutable)#1 (3) {
      ["date"]=>
      string(26) "2015-10-04 17:24:43.000000"
      ["timezone_type"]=>
      int(3)
      ["timezone"]=>
      string(13) "Europe/London"
    }
    

时间格式

此页面以类似BNF的语法描述了DateTimeImmutableDateTimedate_create()date_create_immutable()strtotime()解析器理解的不同日期/时间格式。

要格式化DateTimeImmutableDateTime对象,请参考DateTimeInterface::format()方法的文档。

使用的符号
描述 格式 示例
frac . [0-9]+ ".21342", ".85"
hh "0"?[1-9] | "1"[0-2] "04", "7", "12"
HH [01][0-9] | "2"[0-4] "04", "07", "19"
meridian [AaPp] .? [Mm] .? [\0\t ] "A.m.", "pM", "am."
MM [0-5][0-9] "00", "12", "59"
II [0-5][0-9] "00", "12", "59"
space [ \t]  
tz "("? [A-Za-z]{1,6} ")"? | [A-Z][a-z]+([_/][A-Z][a-z]+)+ "CEST", "Europe/Amsterdam", "America/Indiana/Knox"
tzcorrection "GMT"? [+-] hh ":"? MM? "+0400", "GMT-07:00", "-07:00"
12小时制
描述 格式 示例
仅小时,带经度 hh space? meridian "4 am", "5PM"
小时和分钟,带经度 hh [.:] MM space? meridian "4:08 am", "7:19P.M."
小时、分钟和秒,带经度 hh [.:] MM [.:] II space? meridian "4:08:37 am", "7:19:19P.M."
MS SQL(小时、分钟、秒和带经度的分数) hh ":" MM ":" II [.:] [0-9]+ meridian "4:08:39:12313am"
24小时制
描述 格式 示例
小时和分钟 't'? HH [.:] MM "04:08", "19.19", "T23:43"
小时和分钟,无冒号 't'? HH MM "0408", "t1919", "T2343"
小时、分钟和秒 't'? HH [.:] MM [.:] II "04.08.37", "t19:19:19"
小时、分钟和秒,无冒号 't'? HH MM II "040837", "T191919"
小时、分钟、秒和时区 't'? HH [.:] MM [.:] II space? ( tzcorrection | tz ) "040837CEST", "T191919-0700"
小时、分钟、秒和分数 't'? HH [.:] MM [.:] II frac "04.08.37.81412", "19:19:19.532453"
时区信息 tz | tzcorrection "CEST", "Europe/Amsterdam", "+0430", "GMT-06:00"

日期格式

此页面以类似BNF的语法描述了DateTimeImmutableDateTimedate_create()date_create_immutable()strtotime()解析器理解的不同日期格式。

要格式化DateTimeImmutableDateTime对象,请参考DateTimeInterface::format()方法的文档。

使用的符号
描述 格式 示例
daysuf "st" | "nd" | "rd" | "th"  
dd ([0-2]?[0-9] | "3"[01]) daysuf? "7th", "22nd", "31"
DD "0" [0-9] | [1-2][0-9] | "3" [01] "07", "31"
m ‘january’ | ‘february’ | ‘march’ | ‘april’ | ‘may’ | ‘june’ | ‘july’ | ‘august’ | ‘september’ | ‘october’ | ‘november’ | ‘december’ | ‘jan’ | ‘feb’ | ‘mar’ | ‘apr’ | ‘may’ | ‘jun’ | ‘jul’ | ‘aug’ | ‘sep’ | ‘sept’ | ‘oct’ | ‘nov’ | ‘dec’ | "I" | "II" | "III" | "IV" | "V" | "VI" | "VII" | "VIII" | "IX" | "X" | "XI" | "XII"  
M ‘jan’ | ‘feb’ | ‘mar’ | ‘apr’ | ‘may’ | ‘jun’ | ‘jul’ | ‘aug’ | ‘sep’ | ‘sept’ | ‘oct’ | ‘nov’ | ‘dec’  
mm "0"? [0-9] | "1"[0-2] "0", "04", "7", "12"
MM "0" [0-9] | "1"[0-2] "00", "04", "07", "12"
y [0-9]{1,4} "00", "78", "08", "8", "2008"
yy [0-9]{2} "00", "08", "78"
YY [0-9]{4} "2000", "2008", "1978"
YYY [0-9]{5,19} "81412", "20192"
本地化表示法
描述 格式 示例
美式月份和日期 mm "/" dd "5/12", "10/27"
美式月份、日期和年份 mm "/" dd "/" y "12/22/78", "1/17/2006", "1/17/6"
带斜杠的四位数年份、月份和日期 YY "/" mm "/" dd "2008/6/30", "1978/12/22"
四位数年份和月份 (GNU) YY "-" mm "2008-6", "2008-06", "1978-12"
带短线的年份、月份和日期 y "-" mm "-" dd "2008-6-30", "78-12-22", "8-6-21"
带点、制表符或短线的日期、月份和四位数年份 dd [.\t-] mm [.-] YY "30-6-2008", "22.12.1978"
带点或制表符的日期、月份和两位数年份 dd [.\t] mm "." yy "30.6.08", "22 12.78"
日期、月份文本和年份 dd ([ \t.-])* m ([ \t.-])* y "30-June 2008", "22DEC78", "14 III 1879"
月份文本和四位数年份(日期重置为1) m ([ \t.-])* YY "June 2008", "DEC1978", "March 1879"
四位数年份和月份文本(日期重置为1) YY ([ \t.-])* m "2008 June", "1978-XII", "1879.MArCH"
月份文本、日期和年份 m ([ .\t-])* dd [,.stndrh\t ]+ y "July 1st, 2008", "April 17, 1790", "May.9,78"
月份文本和日期 m ([ .\t-])* dd [,.stndrh\t ]* "July 1st,", "Apr 17", "May.9"
日期和月份文本 dd ([ .\t-])* m "1 July", "17 Apr", "9.May"
月份缩写、日期和年份 M "-" DD "-" y "May-09-78", "Apr-17-1790"
年份、月份缩写和日期 y "-" M "-" DD "78-Dec-22", "1814-MAY-17"
年份(仅年份) YY "1978", "2008"
年份(扩展,带符号的5-19位数字) [+-] YYY "-81120", "+20192"
月份文本(仅月份) m "March", "jun", "DEC"
ISO8601 表示法
描述 格式 示例
八位数年份、月份和日期 YY MM DD "15810726", "19780417", "18140517"
带斜杠的四位数年份、月份和日期 YY "/" MM "/" DD "2008/06/30", "1978/12/22"
带短线的两位数年份、月份和日期 yy "-" MM "-" DD "08-06-30", "78-12-22"
带可选符号的四位数年份、月份和日期 [+-]? YY "-" MM "-" DD "-0002-07-26", "+1978-04-17", "1814-05-17"
带必需符号的五位数以上年份、月份和日期 [+-] YYY "-" MM "-" DD "-81120-02-26", "+20192-04-17"

注意:

对于 yyy 格式,当使用 yyy 符号时,年份低于 100 的处理方式特殊。如果年份在 0(含)到 69(含)之间,则添加 2000。如果年份在 70(含)到 99(含)之间,则添加 1900。这意味着 "00-01-01" 将被解释为 "2000-01-01"。

注意:

“带点或制表符的日期、月份和两位数年份”格式 (dd [.\t] mm "." yy) 仅适用于 61(含)到 99(含)之间的年份值——在这些年份之外,时间格式 "HH [.:] MM [.:] SS" 优先。

注意:

“年份(仅年份)”格式只有在已找到时间字符串的情况下才能可靠地工作。否则,如果四位数年份与 HH MM 匹配,则会设置这两个日期元素。

要一致地解析仅年份,请使用 DateTimeImmutable::createFromFormat()Y 说明符。

警告

可能会出现 ddDD 格式的溢出和下溢。日期 0 表示前一个月的最后一天,而溢出会计入下一个月。这意味着 "2008-08-00" 等效于 "2008-07-31",而 "2008-06-31" 等效于 "2008-07-01"(六月只有 30 天)。

请注意,日期范围限制为 0-31,如上面的正则表达式所示。例如,"2008-06-32" 不是有效的日期字符串。

也可以使用值 0 对 mmMM 格式进行下溢。月份值为 0 表示前一年的 12 月。例如,"2008-00-22" 等效于 "2007-12-22"。

如果您组合前面两个事实并对日期和月份都进行下溢,则会发生以下情况:"2008-00-00" 首先转换为 "2007-12-00",然后转换为 "2007-11-30"。字符串 "0000-00-00" 也会发生这种情况,它将转换为 "-0001-11-30"(ISO 8601 日历中的年份 -1,在推算的格里高利历中为公元前 2 年)。

复合格式

此页面以类似 BNF 的语法描述了 DateTimeImmutableDateTimedate_create()date_create_immutable()strtotime() 解析器理解的不同复合日期/时间格式。

要格式化DateTimeImmutableDateTime对象,请参考DateTimeInterface::format()方法的文档。

使用的符号
描述 格式 示例
DD "0" [0-9] | [1-2][0-9] | "3" [01] "02", "12", "31"
doy "00"[1-9] | "0"[1-9][0-9] | [1-2][0-9][0-9] | "3"[0-5][0-9] | "36"[0-6] "001", "012", "180", "350", "366"
frac . [0-9]+ ".21342", ".85"
hh "0"?[1-9] | "1"[0-2] "04", "7", "12"
HH [01][0-9] | "2"[0-4] "04", "07", "19"
meridian [AaPp] .? [Mm] .? [\0\t ] "A.m.", "pM", "am."
ii [0-5]?[0-9] "04", "8", "59"
II [0-5][0-9] "04", "08", "59"
M ‘jan’ | ‘feb’ | ‘mar’ | ‘apr’ | ‘may’ | ‘jun’ | ‘jul’ | ‘aug’ | ‘sep’ | ‘sept’ | ‘oct’ | ‘nov’ | ‘dec’  
MM [0-1][0-9] "00", "12"
space [ \t]  
ss ([0-5]?[0-9])|60 "04", "8", "59", "60" (闰秒)
SS [0-5][0-9] "04", "08", "59"
W "0"[1-9] | [1-4][0-9] | "5"[0-3] "05", "17", "53"
tzcorrection "GMT"? [+-] hh ":"? II? "+0400", "GMT-07:00", "-07:00"
YY [0-9]{4} "2000", "2008", "1978"
标准格式
描述 示例
ATOM "2022-06-02T16:58:35+00:00"
COOKIE "Thursday, 02-Jun-2022 16:58:35 UTC"
ISO8601 "2022-06-02T16:58:35+0000"
» RFC 822 "Thu, 02 Jun 22 16:58:35 +0000"
» RFC 850 "Thursday, 02-Jun-22 16:58:35 UTC"
» RFC 1036 "Thu, 02 Jun 22 16:58:35 +0000"
» RFC 1123 "Thu, 02 Jun 2022 16:58:35 +0000"
» RFC 2822 "Thu, 02 Jun 2022 16:58:35 +0000"
» RFC 3339 "2022-06-02T16:58:35+00:00"
» RFC 3339 扩展 "2022-06-02T16:58:35.698+00:00"
» RFC 7231 "Thu, 02 Jun 2022 16:58:35 GMT"
RSS "Thu, 02 Jun 2022 16:58:35 +0000"
W3C "2022-06-02T16:58:35+00:00"
本地化表示法
描述 格式 示例
通用日志格式 dd "/" M "/" YY : HH ":" II ":" SS space tzcorrection "10/Oct/2000:13:55:36 -0700"
EXIF YY ":" MM ":" DD " " HH ":" II ":" SS "2008:08:07 18:11:31"
带 ISO 星期的 ISO 年份 YY "-"? "W" W "2008W27", "2008-W28"
带 ISO 星期和日期的 ISO 年份 YY "-"? "W" W "-"? [0-7] "2008W273", "2008-W28-3"
MySQL YY "-" MM "-" DD " " HH ":" II ":" SS "2008-08-07 18:11:31"
PostgreSQL:带一年中的日的年份 YY "."? doy "2008.197", "2008197"
SOAP YY "-" MM "-" DD "T" HH ":" II ":" SS frac tzcorrection? "2008-07-01T22:35:17.02", "2008-07-01T22:35:17.03+08:00"
Unix 时间戳 "@" "-"? [0-9]+ "@1215282385"
带微秒的 Unix 时间戳 "@" "-"? [0-9]+ "." [0-9]{0,6} "@1607974647.503686"
XMLRPC YY MM DD "T" hh ":" II ":" SS "20080701T22:38:07", "20080701T9:38:07"
XMLRPC(紧凑型) YY MM DD 't' hh II SS "20080701t223807", "20080701T093807"
WDDX YY "-" mm "-" dd "T" hh ":" ii ":" ss "2008-7-1T9:3:37"

注意:

“带 ISO 星期的 ISO 年份”和“带 ISO 星期和日期的 ISO 年份”格式中的“W”区分大小写,只能使用大写“W”。

SOAP、XMLRPC 和 WDDX 格式中的“T”区分大小写,只能使用大写“T”。

“Unix 时间戳”格式将时区设置为 UTC。

相对格式

此页面以类似 BNF 的语法描述了 DateTimeImmutableDateTimedate_create()date_create_immutable()strtotime() 解析器理解的不同相对日期/时间格式。

要格式化DateTimeImmutableDateTime对象,请参考DateTimeInterface::format()方法的文档。

使用的符号
描述 格式
dayname ‘sunday’ | ‘monday’ | ‘tuesday’ | ‘wednesday’ | ‘thursday’ | ‘friday’ | ‘saturday’ | ‘sun’ | ‘mon’ | ‘tue’ | ‘wed’ | ‘thu’ | ‘fri’ | ‘sat’
daytext ‘weekday’ | ‘weekdays’
number [+-]?[0-9]+
ordinal ‘first’ | ‘second’ | ‘third’ | ‘fourth’ | ‘fifth’ | ‘sixth’ | ‘seventh’ | ‘eighth’ | ‘ninth’ | ‘tenth’ | ‘eleventh’ | ‘twelfth’ | ‘next’ | ‘last’ | ‘previous’ | ‘this’
reltext ‘next’ | ‘last’ | ‘previous’ | ‘this’
space [ \t]+
unit ‘ms’ | ‘µs’ | (( ‘msec’ | ‘millisecond’ | ‘µsec’ | ‘microsecond’ | ‘usec’ | ‘sec’ | ‘second’ | ‘min’ | ‘minute’ | ‘hour’ | ‘day’ | ‘fortnight’ | ‘forthnight’ | ‘month’ | ‘year’) ‘s’?) | ‘weeks’ | daytext
基于日期的表示法
格式 描述 示例
‘昨天’ 昨天的午夜 “昨天14:00”
‘午夜’ 时间设置为00:00:00  
‘今天’ 时间设置为00:00:00  
‘现在’ 现在 - 此处被忽略  
‘中午’ 时间设置为12:00:00 “昨天中午”
‘明天’ 明天的午夜  
‘…点差’ 小时 指定小时后的15分钟 “7点差”、“15点差”
‘…点前’ 小时 指定小时前的15分钟 “5点前”、“23点前”
‘…月第一天’ 将日期设置为当前月份的第一天。此短语通常最好与后面的月份名称一起使用,因为它只影响当前月份 “2008年1月第一天”
‘…月最后一天’ 将日期设置为当前月份的最后一天。此短语通常最好与后面的月份名称一起使用,因为它只影响当前月份 “下个月的最后一天”
序数 空格 星期几 空格 ‘的’ 计算当前月份的第x个星期几。 “2008年7月的第一个星期六”
‘最后一个’ 空格 星期几 空格 ‘的’ 计算当前月份的最后一个星期几。 “2008年7月的最后一个星期六”
数字 空格?(单位 | ‘周’) 处理值为数字的相对时间项。 “+5周”、“12天”、“-7个工作日”
(序数 | 相对文本) 空格 单位 处理值为文本的相对时间项。lastprevious等效于-1this等效于空,next等效于+1 “第五天”、“第二个月”、“最后一天”、“去年”
‘之前’ 对先前找到的相对时间项的所有值取反。 “2天前”、“8天前14:00”、“2个月5天前”、“2个月前5天”、“2天前”
dayname 移至下一个此名称的日期。(参见注释 “星期一”
相对文本 空格 ‘周’ 处理特殊的格式“星期几 + 上/这/下周”。 “下周星期一”

注意:

相对语句始终在非相对语句之后处理。这使得“+1周 2008年7月”和“2008年7月 +1周”等效。

此规则的例外情况是:“昨天”、“午夜”、“今天”、“中午”和“明天”。请注意,“明天11:00”和“11:00明天”是不同的。如果今天的日期是“2008年7月23日”,则前者产生“2008-07-24 11:00”,而后者产生“2008-07-24 00:00”。原因是这五个语句直接影响当前时间。

诸如“第一天”之类的关键字取决于使用相对格式字符串的上下文。如果与静态方法或函数一起使用,则引用是当前系统时间戳。但是,如果在DateTime::modify()DateTimeImmutable::modify()中使用,则引用是调用modify()方法的对象。

注意:

当当前星期几与日期/时间字符串中使用的星期几相同时,请注意以下说明。但是,当前星期几可能是由日期/时间字符串的非相对部分(重新)计算的。

  1. 星期几不会提前到另一天。(例如,“2008年7月23日星期三”表示“2008-07-23”。)
  2. 数字 星期几不会提前到另一天。(例如,“2008年7月23日星期三1”表示“2008-07-23”。)
  3. 数字星期几”将首先添加周数,但不会提前到另一天。在这种情况下,“数字 周”和“星期几”是两个不同的块。(例如,“+1周 2008年7月23日星期三”表示“2008-07-30”。)
  4. 序数 星期几提前到另一天。(例如,“2008年7月23日第一个星期三”表示“2008-07-30”。)
  5. 数字序数 星期几”将首先添加周数,然后提前到另一天。在这种情况下,“数字 周”和“序数 星期几”是两个不同的块。(例如,“+1周 2008年7月23日第一个星期三”表示“2008-08-06”。)
  6. 序数 星期几 ‘的’ ”不会提前到另一天。(例如,“2008年7月23日第一个星期三的”表示“2008-07-02”,因为带有‘的’的特定短语会将月份的天数重置为‘1’,而此处忽略了‘23日’。)

还要注意,“序数 空格 星期几 空格 ‘的’ ”和“‘最后一个’ 空格 星期几 空格 ‘的’ ”中的“的”具有特殊作用。

  1. 它将月份的天数设置为1。
  2. 序数 星期几 ‘的’ ”不会提前到另一天。(例如,“2008年7月的第一个星期二”表示“2008-07-01”。)
  3. 序数 星期几提前到另一天。(例如,“2008年7月的第一个星期二”表示“2008-07-08”,另见上列表格中的第4点。)
  4. “‘最后一个’ 星期几 ‘的’ ”取当前月份的最后一个星期几。(例如,“2008年7月的最后一个星期三”表示“2008-07-30”。)
  5. “‘最后一个’ 星期几”取自当前日期的最后一个星期几。(例如,“2008年7月的最后一个星期三”表示“2008-06-25”;“2008年7月”首先将当前日期设置为“2008-07-01”,然后“最后一个星期三”移动到之前的星期三,即“2008-06-25”。)

注意:

相对月份值是根据它们经过的月份的长度计算的。例如,“+2个月 2011-11-30”将产生“2012-01-30”。这是因为11月有30天,12月有31天,总共61天。

注意:

数字是一个整数;如果给出十进制数,则点(或逗号)可能会被解释为分隔符。例如,'+1.5小时'被解析为'+1 5小时',而不是'+1小时 +30分钟'

变更日志

版本 描述
8.2.0 数字不再接受多个符号,例如+-2
7.0.8 星期总是从星期一开始。以前,星期日也被认为是一周的开始。

添加注释

用户贡献的注释

此页面没有用户贡献的注释。
To Top