2024 日本 PHP 研討會

日期/時間運算

以下範例顯示了日期/時間運算中關於日光節約時間轉換和月份天數不同的幾個陷阱。

範例 #1 DateTimeImmutable::add/sub 增加涵蓋經過時間的時間間隔

在日光節約時間轉換期間增加 PT24H 看起來會增加 23/25 小時(對於大多數時區)。

<?php
$dt
= new DateTimeImmutable("2015-11-01 00:00:00", new DateTimeZone("America/New_York"));
echo
"Start: ", $dt->format("Y-m-d H:i:s P"), PHP_EOL;
$dt = $dt->add(new DateInterval("PT3H"));
echo
"End: ", $dt->format("Y-m-d H:i:s P"), PHP_EOL;
?>

以上範例會輸出

Start: 2015-11-01 00:00:00 -04:00
End:   2015-11-01 02:00:00 -05:00

範例 #2 DateTimeImmutable::modify 與 strtotime 會遞增或遞減個別的組成值

在日光節約時間轉換期間加上 24 小時會精確地增加 24 小時,如日期/時間字串所示(除非開始或結束時間正好落在轉換點上)。

<?php
$dt
= new DateTimeImmutable("2015-11-01 00:00:00", new DateTimeZone("America/New_York"));
echo
"Start: ", $dt->format("Y-m-d H:i:s P"), PHP_EOL;
$dt = $dt->modify("+24 hours");
echo
"End: ", $dt->format("Y-m-d H:i:s P"), PHP_EOL;
?>

以上範例會輸出

Start: 2015-11-01 00:00:00 -04:00
End:   2015-11-02 00:00:00 -05:00

範例 #3 加上或減去時間可能會導致日期溢位或不足

例如 1 月 31 日加 1 個月會變成 3 月 2 日(閏年)或 3 月 3 日(平年)。

<?php
echo "平年:\n"; // 二月有 28 天
$dt = new DateTimeImmutable("2015-01-31 00:00:00", new DateTimeZone("America/New_York"));
echo
"起始: ", $dt->format("Y-m-d H:i:s P"), PHP_EOL;
$dt = $dt->modify("+1 month");
echo
"結束: ", $dt->format("Y-m-d H:i:s P"), PHP_EOL;

echo
"閏年:\n"; // 二月有 29 天
$dt = new DateTimeImmutable("2016-01-31 00:00:00", new DateTimeZone("America/New_York"));
echo
"起始: ", $dt->format("Y-m-d H:i:s P"), PHP_EOL;
$dt = $dt->modify("+1 month");
echo
"結束: ", $dt->format("Y-m-d H:i:s P"), PHP_EOL;
?>

以上範例會輸出

Normal year:
Start: 2015-01-31 00:00:00 -05:00
End:   2015-03-03 00:00:00 -05:00
Leap year:
Start: 2016-01-31 00:00:00 -05:00
End:   2016-03-02 00:00:00 -05:00

為了取得下個月的最後一天(例如,避免溢位),可以使用 `last day of` 的日期格式。

<?php
echo "平年:\n"; // 二月有 28 天
$dt = new DateTimeImmutable("2015-01-31 00:00:00", new DateTimeZone("America/New_York"));
echo
"起始: ", $dt->format("Y-m-d H:i:s P"), PHP_EOL;
$dt = $dt->modify("last day of next month");
echo
"結束: ", $dt->format("Y-m-d H:i:s P"), PHP_EOL;

echo
"閏年:\n"; // 二月有 29 天
$dt = new DateTimeImmutable("2016-01-31 00:00:00", new DateTimeZone("America/New_York"));
echo
"起始: ", $dt->format("Y-m-d H:i:s P"), PHP_EOL;
$dt = $dt->modify("last day of next month");
echo
"結束: ", $dt->format("Y-m-d H:i:s P"), PHP_EOL;
?>

以上範例會輸出

Normal year:
Start: 2015-01-31 00:00:00 -05:00
End:   2015-02-28 00:00:00 -05:00
Leap year:
Start: 2016-01-31 00:00:00 -05:00
End:   2016-02-29 00:00:00 -05:00

新增註解

使用者提供的註解

此頁面沒有使用者提供的註解。
To Top