🤕
Carbon::createFromFormat にやられたはなし
起こったこと
$a = Carbon::createFromFormat('Ym', $value);
$b = $a->startOfMonth();
のような処理を行っているところで、月末だけ意図通りの値が取得できない問題に遭遇した。
# 3/31 に実行すると `2024-10-01` として扱われる
$a = Carbon::createFromFormat('Ym', '202409');
$b = $a->startOfMonth();
原因は、 Carbon (や PHP の DateTime 型)は省略した部分を現在の日時で初期化するから。
上に挙げたケースだと、 $a は 2024-09-31
として扱われる。これは 2024-10-01
と言うことになる。
全てのフィールドは現在の日付/時刻で初期化されます。
解決方法
解決方法もドキュメントに書いてある。
ほとんどの場合、これらの値を "ゼロ" (Unix タイムのエポック 1970-01-01 00:00:00 UTC) でリセットしたいはずです。 これは、format の最初の文字に ! を入れるか、 最後の文字に | を入れることで実現できます。 詳細な情報は、以下で示すそれぞれの文字に関するドキュメントを参照ください。
と言うことで、以下のようにすれば解決できる。
# いつ実行しても `2024-09-01` として扱われる
$a = Carbon::createFromFormat('!Ym', '202409');
$b = $a->startOfMonth();
ググったときに解決方法として、 createFromFormat('Ymd', "{$value}01")
みたいにすればよい、という記事があったんだけど、無駄に日付を入れるのが気持ち悪かった。
結論
マニュアルは読み得
余談
バグってたコードの修正を日を入れる方法でやっちゃったのでなおさないと……
Discussion