はじめに
PHPで日付操作をする場合、Carbonを利用することが多いと思いますが、今回紹介するメソッドcreateFromFormat
には使用上の注意があったため、備忘録も兼ねて投稿しようと思います。
メソッドcreateFromFormat
とは
時刻の文字列を指定されたフォーマットに従ってパースし、Carbonオブジェクトを返します。
> $carbon = Carbon::createFromFormat('Ymd', '20250509');
> $carbon->format('Y/m/d');
= "2025/05/09"
第一引数でフォーマット、第二引数で時刻を設定します。
ただ、このままだと意図した処理ができないケースがあります。
意図した処理にならないケース
日付の比較
同じ日付を設定して、等しいか確認してみます
> $carbon1 = Carbon::createFromFormat('Ymd', '20250509');
> $carbon2 = Carbon::createFromFormat('Ymd', '20250509');
> $carbon1->eq($carbon2);
= false
true
になると思いきやfalse
が返ります。
なぜなのか、詳しく確認します。
フォーマットを時分秒まで指定して出力してみます。
> $carbon1 = Carbon::createFromFormat('Ymd', '20250509');
> $carbon1->format(DateTimeInterface::ISO8601);
= "2025-05-09T13:57:21+0900"
日付しか設定していないのにもかかわらず、時分秒も設定されています。
このせいで、意図しない値まで比較されており、結果がfalse
になっていました。
公式ドキュメントを確認してみます。
※Carbonはdatetimeのラッパーなので、ドキュメントはdatetimeを確認
https://www.php.net/manual/ja/datetimeimmutable.createfromformat.php
第一引数format
の説明に今回の問題の原因が明記されています。
全てのフィールドは現在の日付/時刻で初期化されます。
つまり、第二引数で設定した箇所以外(年月日以外)の値は現在の日付/時刻に置き換わります。
意図した値を設定するには
では年月日以外は0にしたい時はどうすれば良いでしょうか。
これも公式ドキュメントに書いてあります。
全てのフィールドは現在の日付/時刻で初期化されます。 ほとんどの場合、これらの値を "ゼロ" (Unix タイムのエポック 1970-01-01 00:00:00 UTC) でリセットしたいはずです。 これは、format の最初の文字に ! を入れるか、 最後の文字に | を入れることで実現できます。
実際に試してみます。
> $carbon1 = Carbon::createFromFormat('!Ymd', '20250509');
> $carbon1->format(DateTimeInterface::ISO8601);
= "2025-05-09T00:00:00+0900"
時分秒が0に変わりました。
比較も試してみます。
> $carbon1 = Carbon::createFromFormat('!Ymd', '20250509');
> $carbon2 = Carbon::createFromFormat('!Ymd', '20250509');
> $carbon1->eq($carbon2);
= true
意図通りtrue
が返りました。
さいごに
メソッドは思わぬ挙動をする場合があります。
初めて使うメソッドは公式のドキュメントまで確認しましょう。