PHP Conference Japan 2024

支援的日期和時間格式

此章節描述了 DateTimeImmutableDateTimedate_create_immutable()date_create()date_parse()strtotime() 解析器所理解的所有不同格式,以類似 BNF 的格式呈現。這些格式按章節分組。在大多數情況下,來自不同章節的格式,以空白、逗號或點分隔,可以在同一個日期/時間字串中使用。對於每個支援的格式,都會提供一個或多個範例,以及該格式的描述。格式中單引號中的字元不區分大小寫('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\t12.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」。

注意:

「日期、月份和兩位數年份,帶點或 Tab」格式 (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
基於日期的符號
格式 描述 範例
「yesterday」 昨天的午夜 「yesterday 14:00」
「midnight」 時間設定為 00:00:00  
「today」 時間設定為 00:00:00  
「now」 現在 - 這會被直接忽略  
「noon」 時間設定為 12:00:00 「yesterday noon」
「tomorrow」 明天的午夜  
「back of」 hour 指定時間之後的 15 分鐘 「back of 7pm」、「back of 15」
「front of」 hour 指定時間之前的 15 分鐘 「front of 5am」、「front of 23」
「first day of」 將日期設定為當月的第一天。此片語通常最好與其後的月份名稱一起使用,因為它只會影響當月 「first day of January 2008」
「last day of」 將日期設定為當月的最後一天。此片語通常最好與其後的月份名稱一起使用,因為它只會影響當月 「last day of next month」
ordinal space dayname space 「of」 計算當月的第 x 個星期幾。 「first sat of July 2008」
「last」 space dayname space 「of」 計算當月的_最後_一個星期幾。 「last sat of July 2008」
number space? (unit | 「week」) 處理值為數字的相對時間項目。 「+5 weeks」、「12 day」、「-7 weekdays」
(ordinal | reltext) space unit 處理值為文字的相對時間項目。lastprevious 等同於 -1this 等同於無,而 next 等同於 +1 「fifth day」、「second month」、「last day」、「previous year」
「ago」 將先前找到的相對時間項目之值取反。 「2 天前」、「8 天前 14:00」、「2 個月 5 天前」、「2 個月前 5 天」、「2 天前」
dayname 移動到此名稱的下一天。(請參閱註記 「星期一」
reltext 空格 'week' 處理「weekday + last/this/next week」的特殊格式。 「下週一」

注意:

相對語句總是在非相對語句之後處理。這使得「+1 week july 2008」和「july 2008 +1 week」等效。

此規則的例外情況為:「yesterday」、「midnight」、「today」、「noon」和「tomorrow」。請注意,「tomorrow 11:00」和「11:00 tomorrow」是不同的。考慮到今天的日期是「2008 年 7 月 23 日」,第一個會產生「2008-07-24 11:00」,而第二個會產生「2008-07-24 00:00」。原因在於這五個語句直接影響目前的時間。

諸如「first day of」之類的關鍵字取決於相對格式字串的使用情境。如果與靜態方法或函式一起使用,則參照物為目前的系統時間戳記。但是,如果在 DateTime::modify()DateTimeImmutable::modify() 中使用,則參照物為呼叫 modify() 方法的物件。

注意:

當目前星期幾與日期/時間字串中使用的星期幾相同時,請注意以下事項。目前星期幾可能已經由日期/時間字串的非相對部分(重新)計算過。

  1. dayname不會前進到另一天。(例如:「Wed July 23rd, 2008」表示「2008-07-23」)。
  2. number dayname不會前進到另一天。(例如:「1 wednesday july 23rd, 2008」表示「2008-07-23」)。
  3. number week dayname」將首先加上週數,但不會前進到另一天。在此情況下,「number week」和「dayname」是兩個不同的區塊。(例如:「+1 week wednesday july 23rd, 2008」表示「2008-07-30」)。
  4. ordinal dayname前進到另一天。(例如:「first wednesday july 23rd, 2008」表示「2008-07-30」)。
  5. number week ordinal dayname」將首先加上週數,然後前進到另一天。在此情況下,「number week」和「ordinal dayname」是兩個不同的區塊。(例如:「+1 week first wednesday july 23rd, 2008」表示「2008-08-06」)。
  6. ordinal dayname 'of' 」不會前進到另一天。(例如:「first wednesday of july 23rd, 2008」表示「2008-07-02」,因為帶有 'of' 的特定片語會將月份中的日重設為 '1',而 '23rd' 在此處被忽略)。

還要觀察「ordinal 空格 dayname 空格 'of' 」和「'last' 空格 dayname 空格 'of' 」中的「of」會做一些特殊的事情。

  1. 它將月份中的日設定為 1。
  2. ordinal dayname 'of' 」不會前進到另一天。(例如:「first tuesday of july 2008」表示「2008-07-01」)。
  3. ordinal dayname前進到另一天。(例如:「first tuesday july 2008」表示「2008-07-08」,另請參閱上面列表中的第 4 點)。
  4. 「'last' dayname 'of' 」會取得目前月份的最後一個 dayname。(例如:「last wed of july 2008」表示「2008-07-30」)
  5. 「'last' dayname」會從當前日期取得最後一個 dayname。(例如:「last wed july 2008」表示「2008-06-25」;「july 2008」首先將目前的日期設定為「2008-07-01」,然後「last wed」移至上一個星期三,即「2008-06-25」)。

注意:

相對月份值是根據它們經過的月份長度來計算的。例如「+2 month 2011-11-30」會產生「2012-01-30」。這是因為 11 月的長度為 30 天,而 12 月的長度為 31 天,總共產生 61 天。

注意:

number 是一個整數數字;如果給出小數,則點號(或逗號)可能會被解釋為分隔符號。例如,'+1.5 hours' 會被解析為 '+1 5 hours',而不是 '+1 hour +30 minutes'

更新日誌

版本 描述
8.2.0 number 不再接受多個符號,例如 +-2
7.0.8 週總是從星期一開始。以前,星期日也會被視為一週的開始。

新增註解

使用者貢獻的註解

此頁面沒有使用者貢獻的註解。
To Top