要澄清一下,g/G 是 12/24 小時制 tanpa angka nol di depan,而 h/H 是 12/24 小時制 dengan angka nol di depan,如此處所述
https://php.net.tw/manual/en/datetime.format.php(PHP 5 >= 5.5.0, PHP 7, PHP 8)
DateTimeImmutable::createFromFormat -- date_create_immutable_from_format — 根據指定的格式解析時間字串
物件導向風格
$format, 字串 $datetime, ?DateTimeZone $timezone = null): DateTimeImmutable|false程序式風格
$format, 字串 $datetime, ?DateTimeZone $timezone = null): DateTimeImmutable|false傳回一個新的 DateTimeImmutable 物件,表示由 datetime 字串指定的日期和時間,該字串的格式為指定的 format。
format傳入的 字串 應使用的格式。請參閱下面的格式選項。在大多數情況下,可以使用與 date() 相同的字母。
所有欄位皆以目前的日期/時間初始化。在大多數情況下,您會希望將它們重置為「零」(Unix 紀元,1970-01-01 00:00:00 UTC)。您可以透過在 format 的第一個字元包含 ! 字元,或在最後包含 | 字元來完成此操作。請參閱下方每個字元的說明文件以取得更多資訊。
格式是從左到右解析的,這表示在某些情況下,格式字元出現的順序會影響結果。在 z(一年中的第幾天)的情況下,需要先解析年份,例如透過 Y 或 y 字元。
用於解析數字的字母允許廣泛的值,超出邏輯範圍。例如,d(月份中的第幾天)接受 00 到 99 範圍內的值。唯一的限制是位數。當給定超出範圍的值時,將使用日期/時間解析器的溢位機制。以下範例顯示了其中一些行為。
這也表示為格式字母解析的資料是貪婪的,它會讀取其格式允許的位數。這也可能表示 datetime 字串中沒有足夠的字元供後續的格式字元使用。此頁面上的一個範例也說明了這個問題。
format 字元 |
說明 | 可解析值的範例 |
|---|---|---|
| 日 | --- | --- |
d 和 j |
月份中的第幾天,2 位數字,可以有前導零,也可以沒有前導零 |
01 至 31 或 1 至 31。(大於一個月天數的兩位數也會被接受,此時月份會溢位。例如,一月使用 33 表示二月 2 日) |
D 和 l |
星期的文字表示法 |
Mon 至 Sun 或 Sunday 至 Saturday。如果給定的星期名稱與解析(或預設)日期的星期名稱不同,則會溢位至下一個具有給定星期名稱的日期。請參閱以下範例說明。 |
S |
月份日期的英文序數後綴,2 個字元。處理時會被忽略。 |
st、nd、rd 或 th。 |
z |
一年中的第幾天(從 0 開始);必須以 Y 或 y 作為前綴。 |
0 至 365。(大於一年天數的三位數也會被接受,此時年份會溢位。例如,2022 年使用 366 表示 2023 年 1 月 2 日) |
| 月份 | --- | --- |
F 和 M |
月份的文字表示法,例如 January 或 Sept |
January 至 December 或 Jan 至 Dec |
m 和 n |
月份的數字表示法,可包含或不包含前導零 |
01 至 12 或 1 至 12。(大於 12 的兩位數也會被接受,此時年份會溢位。例如,使用 13 表示下一年的 1 月) |
| 年份 | --- | --- |
X 和 x |
年份的完整數字表示法,最多 19 位數,可選擇以 + 或 - 作為前綴 |
範例:0055、787、1999、-2003、+10191 |
Y |
年份的完整數字表示法,最多 4 位數 | 範例:0055、787、1999、2003 |
y |
年份的兩位數表示法(假設範圍為 1970-2069,含) | 範例:99 或 03(將分別解讀為 1999 和 2003) |
| 時間 | --- | --- |
a 和 A |
上午和下午 | am 或 pm |
g 和 h |
12 小時制的小時數,可包含或不包含前導零 |
1 至 12 或 01 至 12(大於 12 的兩位數也會被接受,此時日期會溢位。例如,使用 14 表示下一個上午/下午時段的 02) |
G 和 H |
24 小時制,可包含或不包含前導零 |
0 至 23 或 00 至 23(大於 24 的兩位數也會被接受,此時會造成日期溢位。例如,使用 26 表示隔天的 02:00) |
i |
分鐘,包含前導零 |
00 至 59。(大於 59 的兩位數也會被接受,此時會造成小時溢位。例如,使用 66 表示下一個小時的 :06) |
s |
秒鐘,包含前導零 |
00 至 59(大於 59 的兩位數也會被接受,此時會造成分鐘溢位。例如,使用 90 表示下一分鐘的 :30) |
v |
毫秒的小數部分(最多三位數) | 範例:12(0.12 秒),345(0.345 秒) |
u |
微秒的小數部分(最多六位數) | 範例:45(0.000045 秒),654321(0.654321 秒) |
| 時區 | --- | --- |
e、O、p、P 和 T |
時區識別碼、與 UTC 的小時差、以冒號分隔小時和分鐘的與 UTC 的時差,或時區縮寫 | 範例:UTC、GMT、Atlantic/Azores 或 +0200 或 +02:00 或 EST、MDT |
| 完整的日期/時間 | --- | --- |
U |
自 Unix 紀元(1970 年 1 月 1 日 00:00:00 GMT)以來的秒數 | 範例:1292177455 |
| 空白和分隔符號 | --- | --- |
(空格) |
零個或多個空格、定位鍵、不換行空格 (U+A0) 或窄不換行空格 (U+202F) 字元 | 範例:"\t"、" " |
# |
下列分隔符號之一:;、:、/、.、,、-、( 或 ) |
範例:/ |
;、:、/、.、,、-、( 或 ) |
指定的字元。 | 範例:- |
? |
隨機位元組 | 範例:^(請注意,對於 UTF-8 字元,您可能需要多個 ?。在這種情況下,使用 * 可能是您想要的) |
* |
隨機位元組,直到下一個分隔符號或數字 | 範例:在字串 2009-aWord-08 中,使用 Y-*-d 中的 * 將會匹配 aWord |
! |
將所有欄位(年、月、日、小時、分鐘、秒、小數和時區資訊)重設為類似零的值(小時、分鐘、秒和小數為 0,月和日為 1,年為 1970,時區資訊為 UTC) |
如果沒有 !,所有欄位將會設定為目前的日期和時間。 |
| |
如果尚未解析,則會將所有欄位(年、月、日、時、分、秒、小數和時區資訊)重置為類似零的值。 | Y-m-d| 會將年、月和日設定為在要解析的字串中找到的資訊,並將時、分和秒設定為 0。 |
+ |
如果存在此格式指定符,則字串中的尾端數據不會導致錯誤,而是發出警告。 | 使用 DateTimeImmutable::getLastErrors() 來查明是否存在尾端數據。 |
格式字串中無法識別的字元將導致解析失敗,並將錯誤訊息附加到返回的結構。您可以使用 DateTimeImmutable::getLastErrors() 查詢錯誤訊息。
要在 format 中包含字面字元,您必須使用反斜線 (\) 對其進行跳脫。
如果 format 不包含字元 !,則在 format 中未指定的已產生日期/時間的部分將設定為目前的系統時間。
如果 format 包含字元 !,則在 format 中未提供的已產生日期/時間的部分,以及 ! 左側的值,將設定為 Unix 紀元中的對應值。
如果解析了任何時間字元,則所有其他與時間相關的欄位都設定為「0」,除非也已解析。
Unix 紀元是 1970-01-01 00:00:00 UTC。
datetime表示時間的字串。
timezone表示所需時區的 DateTimeZone 物件。
如果省略 timezone 或為 null 且 datetime 不包含時區,則將使用目前的時區。
注意事項:
當
datetime參數包含 UNIX 時間戳記(例如946684800)或指定時區(例如2010-01-28T15:00:00+02:00)時,將忽略timezone參數和目前的時區。
傳回新的 DateTimeImmutable 實例,如果失敗則傳回 false。
當 datetime 包含 NULL 位元組時,此方法會擲出 ValueError。
| 版本 | 說明 |
|---|---|
| 8.2.9 | (空格)指定符現在也支援 NBSP (U+A0) 和 NNBSP (U+202F) 字元。 |
| 8.2.0 | 已新增 X 和 x format 指定符。 |
| 8.0.21, 8.1.8, 8.2.0 | 現在,當將 NULL 位元組傳遞到 datetime 時會擲出 ValueError,以前會忽略此情況。 |
| 7.3.0 | 已新增 v format 指定符。 |
範例 #1 DateTimeImmutable::createFromFormat() 範例
物件導向風格
<?php
$date = DateTimeImmutable::createFromFormat('j-M-Y', '15-Feb-2009');
echo $date->format('Y-m-d');
?>範例 #2 使用預定義格式常數搭配 DateTimeImmutable::createFromFormat()
物件導向風格
<?php
$date = DateTimeImmutable::createFromFormat(DateTimeInterface::ISO8601, '2004-02-12T15:19:21+00:00');
$date = DateTimeImmutable::createFromFormat(DateTimeInterface::RFC3339_EXTENDED, '2013-10-14T09:00:00.000+02:00');
?>此範例中使用的格式常數是由一串用於格式化 DateTimeImmutable 物件的字元組成。在大多數情況下,這些字母與上面參數章節中定義的日期/時間資訊元素相同,但它們的限制通常較寬鬆。
範例 #3 DateTimeImmutable::createFromFormat() 的複雜性
<?php
echo 'Current time: ' . date('Y-m-d H:i:s') . "\n";
$format = 'Y-m-d';
$date = DateTimeImmutable::createFromFormat($format, '2009-02-15');
echo "Format: $format; " . $date->format('Y-m-d H:i:s') . "\n";
$format = 'Y-m-d H:i:s';
$date = DateTimeImmutable::createFromFormat($format, '2009-02-15 15:16:17');
echo "Format: $format; " . $date->format('Y-m-d H:i:s') . "\n";
$format = 'Y-m-!d H:i:s';
$date = DateTimeImmutable::createFromFormat($format, '2009-02-15 15:16:17');
echo "Format: $format; " . $date->format('Y-m-d H:i:s') . "\n";
$format = '!d';
$date = DateTimeImmutable::createFromFormat($format, '15');
echo "Format: $format; " . $date->format('Y-m-d H:i:s') . "\n";
$format = 'i';
$date = DateTimeImmutable::createFromFormat($format, '15');
echo "Format: $format; " . $date->format('Y-m-d H:i:s') . "\n";
?>上述範例的輸出會類似於
Current time: 2022-06-02 15:50:46 Format: Y-m-d; 2009-02-15 15:50:46 Format: Y-m-d H:i:s; 2009-02-15 15:16:17 Format: Y-m-!d H:i:s; 1970-01-15 15:16:17 Format: !d; 1970-01-15 00:00:00 Format: i; 2022-06-02 00:15:00
範例 #4 包含字面字元的格式字串
<?php
echo DateTimeImmutable::createFromFormat('H\h i\m s\s','23h 15m 03s')->format('H:i:s');
?>上述範例的輸出會類似於
23:15:03
範例 #5 溢位行為
<?php
echo DateTimeImmutable::createFromFormat('Y-m-d H:i:s', '2021-17-35 16:60:97')->format(DateTimeImmutable::RFC2822);
?>上述範例的輸出會類似於
Sat, 04 Jun 2022 17:01:37 +0000
雖然結果看起來很奇怪,但它是正確的,因為發生了以下溢位:
97 秒溢位到 1 分鐘,剩下 37 秒。
61 分鐘溢位到 1 小時,剩下 1 分鐘。
35 天溢位到 1 個月,剩下 4 天。剩餘的天數取決於月份,因為並非每個月的總天數都相同。
18 個月會溢位成 1 年,剩下 6 個月。
範例 #6 溢位日期名稱的行為
<?php
$d = DateTime::createFromFormat(DateTimeInterface::RFC1123, 'Mon, 3 Aug 2020 25:00:00 +0000');
echo $d->format(DateTime::RFC1123), "\n";
?>上述範例的輸出會類似於
Mon, 10 Aug 2020 01:00:00 +0000
雖然結果看起來很奇怪,但它是正確的,因為發生了以下溢位:
3 Aug 2020 25:00:00 會溢位成 (Tue) 4 Aug 2020 01:00。
Mon 會被套用,這會讓日期前進到 Mon, 10 Aug 2020 01:00:00。關於 Mon 等相對關鍵字的說明,請參閱 相對格式 的章節。
為了偵測日期溢位,您可以使用 DateTimeImmutable::getLastErrors(),如果發生溢位,它會包含一個警告。
範例 #7 偵測溢位的日期
<?php
$d = DateTimeImmutable::createFromFormat('Y-m-d H:i:s', '2021-17-35 16:60:97');
echo $d->format(DateTimeImmutable::RFC2822), "\n\n";
var_dump(DateTimeImmutable::GetLastErrors());
?>上述範例的輸出會類似於
Sat, 04 Jun 2022 17:01:37 +0000
array(4) {
'warning_count' =>
int(2)
'warnings' =>
array(1) {
[19] =>
string(27) "The parsed date was invalid"
}
'error_count' =>
int(0)
'errors' =>
array(0) {
}
}
範例 #8 貪婪式解析行為
<?php
print_r(date_parse_from_format('Gis', '60101'));
?>上述範例的輸出會類似於
Array
(
[year] =>
[month] =>
[day] =>
[hour] => 60
[minute] => 10
[second] => 0
[fraction] => 0
[warning_count] => 1
[warnings] => Array
(
[5] => The parsed time was invalid
)
[error_count] => 1
[errors] => Array
(
[4] => A two digit second could not be found
)
[is_localtime] =>
)
G 格式是用來解析 24 小時制的時數,可以有或沒有前導零。這需要解析 1 或 2 個數字。因為後面有兩個數字,它會貪婪地讀取為 60。
後面的格式字元 i 和 s 都需要兩個數字。這表示 10 會被當作分鐘 (i) 傳遞,然後就沒有足夠的數字可以解析為秒數 (s) 了。
errors 陣列會指出這個問題。
此外,60 的時數超出 0-24 的範圍,這會導致 warnings 陣列包含一個時間無效的警告。
要澄清一下,g/G 是 12/24 小時制 tanpa angka nol di depan,而 h/H 是 12/24 小時制 dengan angka nol di depan,如此處所述
https://php.net.tw/manual/en/datetime.format.php由於時區列的說明和範例並不完全相符,我想釐清每個字元輸出的確切格式。
`e` 輸出時區識別碼,例如 `America/New_York` 或 `Asia/Gaza`
`O` 輸出與 UTC 的時差(以小時為單位),例如 `-0500` 或 `+0200`
`P` 輸出與 UTC 的時差,小時和分鐘之間以冒號分隔,例如 `-05:00` 或 `+02:00`
`T` 輸出時區縮寫,例如 `EST` 或 `EET`如果您不滿意此方法為您進行的大範圍轉換和修復,或者只想檢查日期是否與輸入的日期完全相同
```
$datetime = \DateTimeImmutable::createFromFormat('Y-m-d G:i:s', $userDateTimeInput);
if ($datetime && $datetime->format('Y-m-d G:i:s') === $userDateTimeInput) {
// $datetime 不是 false,而且我們從使用者那裡得到了格式正確的日期
}
```