Laravel PHP

【php】Carbonまとめ【日時操作ライブラリ】

日時操作基礎知識(Carbonまとめの前に...)

タイムゾーンは各国の時刻を表すものになります。
イギリスを中心(±0時間)として各地域がどれだけ差異があるかを表します。
日本の時刻はJSTと呼び、+9時間になります。タイムゾーンとしてはAsia/Tokyoなどと表記します。
+9時間なのでイギリスが10時のときは日本は19時になります。
UTC/GMT、サマータイムなどについての説明はここでは省きます。

Laravelで使えるCarbonには
・元々のCarbon\Carbon
・少し機能が追加(後述)されている Illuminate\Support\Carbon
・加減処理の際にcopy()不要で直感的な Carbon\CarbonImmutable
の3種類があります。(参考

Laravelでは、Modelのデフォルトの日時フォーマットのキャストがCarbonなので
機能が追加されているIlluminate\Support\Carbon を基本的に使い、
必要に応じて加減処理が直感的なCarbon\CarbonImmutable を使うとよいです。
Modelの$castを全て設定するのであればCarbonImmutableに統一してしまえれば楽だと思いますが混ざると不具合になりやすいのでこの辺りはお好みで。

Illuminate\Support\Carbon はLaravel8.x、9.xと地味な機能が追加されてきているので今後も機能が増えていくかもしれません。

入力

Carbonにデータを入れるパターンです。

# 現在日時系
$carbon = Carbon::now(); // 現在の日時が入る

$carbon = Carbon::today(); // (今が何時でも)今日の0時0分0秒が入る
$carbon = Carbon::today('Asia/Tokyo'); // 引数にTimeZoneを入れられる 例の場合は日本時間(JST)で今日の0時0分0秒が入る

# 現在日時基準系
$carbon = Carbon::yesterday(); // (今が何時でも)昨日の0時0分0秒が入る
$carbon = Carbon::tomorrow(); // (今が何時でも)明日の0時0分0秒が入る


# 日時指定系
$carbon = Carbon::parse('2023/04/05 06:07:08'); // 指定の日時で入る parse内の形式はわりとよしなに解釈してくれる
$carbon = Carbon::parse('2023/04/05 06:07:08', 'Asia/Tokyo'); // 第2引数にTimeZoneを入れられる 例の場合JSTの指定日時として入る
$carbon = new Carbon('2023/04/05 06:07:08'); // Carbon::parse() と同様

$carbon = Carbon::parse('2023-12'); // 2023-12-01 00:00:00 日付指定の場合は指定されていないところは最小値(0か1)が自動的に入る
$carbon = Carbon::parse('01:23'); // 2022-10-20 01:23:00 時間指定の場合は日付は今日になる

# timestamp
$carbon = Carbon::createFromTimestamp(1680674828); // unixtimeで指定の日時で入る
$carbon = Carbon::createFromTimestampMs(1680674828000); // unixtime(ミリ秒)で指定の日時で入る

# 複製
$carbon2 = $carbon->copy(); // 複製する

日時の加算 / 減算

上記のように$carbonを生成したら、それを元に日時の加算や減算ができます。
なお、$carbonに格納せずにいきなり $example_at = Carbon::now()->addMinutes(5); などとすることも可能です。
冒頭でも書きましたがCarbonとCarbonImmutableで動作に差が出るところになります。
Carbonインスタンスに加算や減算したあとにも同インスタンスを使い回す場合はよく確認しておいてください。

$carbon->addDays(1); // +1日
$carbon->subDays(2); // -2日

$carbon->addHours(3); // +3時間
$carbon->subHours(4); // -4時間

加算や減算後の状態について

日時を加算や減算した際のインスタンスの状態に差異が出ます。
通常のCarbonの場合、 $today->addDays(7)->format('Y-m-d H:i:s'); などと実行してしまうと$todayの中身自体が7日後になってしまうので注意が必要です。

# use Illuminate\Support\Carbon; もしくは use Carbon\Carbon; なら
$today = Carbon::createFromFormat('Y-m-d H:i:s', '2023-01-23 01:23:45'); // 今日は23日
$today->addDays(1)->format('Y-m-d H:i:s'); // 2023-01-24 01:23:45 1日進んで24日
$today->format('Y-m-d H:i:s'); // 2023-01-24 01:23:45 24日になっていて$today自体が1日進んでいる!

# $todayを維持するなら下記のように操作する
$today = Carbon::createFromFormat('Y-m-d H:i:s', '2023-01-23 01:23:45'); // 今日は23日
$tomorrow = $today->copy()->addDays(1); // コピーしてから1日足したものを$tomorrowに格納
$tomorrow->format('Y-m-d H:i:s'); // 2023-01-24 01:23:45 こちらは24日
$today->format('Y-m-d H:i:s'); // 2023-01-23 01:23:45 $todayは23日のまま

# $tomorrowを作りたくなければ
$today->copy()->addDays(1)->format('Y-m-d H:i:s'); // これでもOK
# use Carbon\CarbonImmutable; なら
$today = Carbon::createFromFormat('Y-m-d H:i:s', '2023-01-23 01:23:45'); // 今日は23日
$today->addDays(1)->format('Y-m-d H:i:s'); // 2023-01-24 01:23:45 1日進んで24日
$today->format('Y-m-d H:i:s'); // 2023-01-24 01:23:45 $todayは23日のまま

出力

$carbonが保持している時間などの情報を出力するものです。

$carbon->getTimestamp(); // unixtimestampで出力 e.g. 1674444896
$carbon->toISOString(); // ISO-8601形式で出力(Laravel7以降のEloquentでtoArrayやtoJsonをするとデフォルトはこの形式)e.g. 2023-01-23T03:34:56.000000Z
$carbon->format('Y-m-d H:i:s'); // 指定した形式で出力 e.g. 例の場合 2023-01-23 12:34:56

# 曜日など
$carbon->dayOfWeek; // 数字が返る 月:1 火:2 水:3 木:4 金:5 土:6 日:0 
$carbon->dayOfWeekIso; // 数字が返る 月:1 火:2 水:3 木:4 金:5 土:6 日:7

# 日本語で曜日を出す ※localeを日本にする必要有 Carbon::setLocale('ja');
$carbon->isoFormat('Y年M月D日(ddd) H:m:s'); // e.g. 2023年1月23日(月) 1:23:45
$carbon->isoFormat('YYYY年MM月DD日(dddd) HH:mm:ss') // e.g. 2023年01月23日(月曜日) 01:23:45

比較(判定)

真偽判定など、$carbonが保持している時間以外の情報を返すものです。

$carbon->max($carbon2); // 大きいもの(より遅い:未来)を返す 引数を省略すると現在時刻との比較
$carbon->min($carbon2); // 小さいもの(より早い:過去)を返す 引数を省略すると現在時刻との比較

$carbon->isBirthday(); // $carbon生まれの人が今日誕生日か(年を無視して、月と日が一致しているか)引数で今日以外の指定も可

テスト用

テストをするとき、現在時刻の影響を受けることは多いと思います。
その際、まるで今が指定した時間であるかのように振る舞ってテストをするための機能があります。

なお、ここで Illuminate\Support\Carbon のCarbonを使っている場合、CarbonとCarbonImmutableの両方に一括でsetTestNowされます。(Laravel 8.x以降)
setTestNow()は基本的にIlluminate\Support\Carbonで行うのがよいでしょう。

# set1
$carbon = Carbon::parse('2023/04/05 06:07:08');
Carbon::setTestNow($carbon); // $carbonの時間を"今"扱いにする Carbon::now()がこの時間になる

# set2、3
Carbon::setTestNow('2023-04-05 06:07:08'); // これでもよい
Carbon::setTestNow('2023-01-23T03:34:56.000000Z'); // これでもよい テストとしてはタイムゾーンも指定しているこの形式がおすすめ

# set状況確認
Carbon::hasTestNow(); // テスト時間がセットされているか この例では前の行でセットされているのでtrueになる
Carbon::getTestNow(); // セットしたテスト時間が返る セットされていなければnull nullでなければ->format()などを繋げることもできる

Carbon::setTestNow(); // 空だと初期化 nowが実際の現在時刻の状態に戻る
Carbon::hasTestNow(); // テスト時間がセットされているか 前の行で外されているのでfalseになる

Illuminate\Support\Carbon の機能

おまけです。
Illuminate\Support\Carbon はLaravel8.xでCarbonImmutableも一緒にsetTestNow()できる機能、
Laravel9.xでwhen()とunless()が追加されています。
when()の使い方はStrのヘルパのwhenと同じで、falseの場合に実行するcallbackを第三引数に渡すこともできます。
休日が指定されたら会社の営業日にズラすなど作れそうですね。

$carbon = Carbon::now()
			->when(true, function (Carbon $carbon) {
				return $carbon->addDay();
			});

まとめ

とりあえず(自分が)Carbon関係を使うときに見るページを目指して作成しました。
重複した分かりにくい機能は省きつつ情報をまとめて、困ったら見る、どんな事ができるか把握したいときに見るという感じにしてあります。
ちなみに全機能知りたいときは普通にCarbonの公式ドキュメントがわかりやすくまとまっています。
必要に応じて適宜更新していきます。

-Laravel, PHP