PHPで ISO 8601 のフォーマット('c') を扱う際にハマりました。
他にも同じ罠にひっかかる人が出てこないことを願っています 🥱
ISO 8601 フォーマットについて
年、月、日、時間、分、秒と「タイムゾーン」を出力してくれる便利なフォーマットです。
多言語サイト等を扱う際、時差を考慮する際にとても便利なフォーマットですよね。
例
$datetime = new DateTime('now');
echo $datetime->format('c');
// 出力 2024-06-24T21:00:00+09:00
罠にハマりました
何故か c フォーマットを createFromFormat で Datetime オブジェクトを生成しようとしてもうまくいかない...。
デバッグしようと ↓↓ を試してみました。
$datetime = new DateTime('now');
$create_format_datetime = Datetime::createFromFormat('c', $datetime->format('c'));
echo $create_format_datetime;
// 出力 false
え、falseになるんですね...。
なんでだよ。
原因
軽く調べました。
$datetime->format('c'); では.uが含まれないです。
ただ、createFromFormat('c', $datetime);では、.u が入ることを期待しているみたい。
対策
もちろん回避策もあるようです。
パターン①
.u を含める。
まぁ予想通りですね。ただ、わざわざ含める処理を追加実装するのもめんどいですよね。
こんな感じですかね。
$datetime = new DateTime('now');
$create_format_datetime = Datetime::createFromFormat('Y-m-d\TH:i:s.uP', $datetime->format('Y-m-d\TH:i:s.uP'))
echo create_format_datetime->format('c');
// 出力 2024-06-24T21:00:00+09:00
パターン②
new Datetime(${'c'のフォーマット})で行けるみたい。
$datetime = new Datetime('now');
$create_datetime = new Datetime($datetime->format('c'));
echo $create_datetime->format('c');
// 出力 2024-06-24T21:00:00+09:00
うーん。こっちのほうがわかりやすいかも。
まとめ
やっぱり、タイムゾーンを含む日付データの受け渡しにはISO 8601が便利ですよね。
クエリパラメータ等での活躍場面が今後も多そうです。
参考