目的
サマータイムのある地域において、特定の日付がサマータイムの期間内かどうかを調べる機会があったので、PHPで判定の実装をしてみました。
結論
DateTimeZone::getTransitionsを用いて判定を行います。
$timezone = new DateTimeZone('America/Los_Angeles');
$datetime = new DateTime('2022/3/12', $timezone);
$transitions = $tz->getTransitions($datetime->getTimestamp(), $datetime->getTimestamp());
echo $transitions[0]['isdst']; // false
DateTimeZoneオブジェクト
PHPの日付クラスであるDateTimeはタイムゾーンの情報は持っていますが、サマータイムの情報はもっていません。
与えられた日時においてサマータイムかを判定するためにDateTimeZone::getTransitionsを使用しました。
getTransitionsメソッドは与えられたUnixタイムスタンプの期間内において、そのタイムゾーンの推移を取得することができます。
キー | 型 | 説明 |
---|---|---|
ts | int | Unixタイムスタンプ |
time | string | DateTimeInterface::ISO8601 形式の文字列 |
offset | int | UTC からのオフセット(秒単位) |
isdst | bool | サマータイムが有効かどうか |
abbr | string | タイムゾーンの省略形 |
たとえばロサンゼルスでは、2022/1/1〜12/31の期間の推移を調べてみましょう。
$timezone = new DateTimeZone('America/Los_Angeles');
$timezone->getTransitions(strtotime('2022/1/1'), strtotime('2022/12/31'))
2022/3/13にサマータイムが開始され(PDT: 米国太平洋標準時(夏時間)になる)、2022/11/6にサマータイムが終了することがわかります(PST: 米国太平洋標準時になる)。
[
[
"ts" => 1640962800,
"time" => "2021-12-31T15:00:00+0000",
"offset" => -28800,
"isdst" => false,
"abbr" => "PST",
],
[
"ts" => 1647165600,
"time" => "2022-03-13T10:00:00+0000",
"offset" => -25200,
"isdst" => true,
"abbr" => "PDT",
],
[
"ts" => 1667725200,
"time" => "2022-11-06T09:00:00+0000",
"offset" => -28800,
"isdst" => false,
"abbr" => "PST",
],
]
このとき、startとendを同一日時にしてやることでその時点においてサマータイムが適用されているかをisdistで調べてやることができます。
$timezone->getTransitions(strtotime('2022/1/1'), strtotime('2022/1/1')); // startとendを一致させる
[
[
"ts" => 1640962800,
"time" => "2021-12-31T15:00:00+0000",
"offset" => -28800,
"isdst" => false,
"abbr" => "PST",
],
]
注意
サマータイムの切り替え日における判定
サマータイムの切り替えタイミングでは意図していない挙動になる可能性があります。
たとえばロサンゼルスでは2022/11/6 2:00にサマータイムが終了し、また1:00に巻き戻す処理が行われます。
つまり2022/11/6 1:00〜2:00が2回存在し、サマータイムである状態とそうでない状態のどちらも両立するということです。
$timezone = new DateTimeZone('America/Los_Angeles');
$datetime = new DateTime('2022/11/6 1:00', $timezone);
$timezone->getTransitions($datetime->getTimestamp(), $datetime->getTimestamp());
この場合、結果はサマータイムになります。
[
[
"ts" => 1667721600,
"time" => "2022-11-06T08:00:00+0000",
"offset" => -25200,
"isdst" => true,
"abbr" => "PDT",
],
]
判定可能日時
getTransitionsで取得可能な期間は2037年までですので、それ以降の判定にもちいることはできません。