PHPで日付をフォーマットするならCarbonを使おう
プログラムを書いていて日付を操作することは非常によくあることです。
また、日付をフォーマットするなんてことは日常茶飯事ですが、日本以外を扱い始めると途端に煩雑になりがちです。
今回は PHP で日付を操作するライブラリ Carbon をご紹介します。
余談ですが、Carbon は CakePHP3 や Laravel でも使用されています。
(CakePHP3 は3.2.0以前まで使用されていました)
◆Carbon に関するリンク
目次
環境
実行環境はこんな感じです。
CentOS 7
PHP Version 7.1.11
Composer
※Composerのインストールおよび使い方の説明は割愛します
※Linuxの使い方の説明は割愛します
実装方法
インストール
まずは composer で Carbon をインストールします
1 2 3 |
$ composer require nesbot/carbon:~2.31.0 |
続いて Carbon を使用できるようにします
1 2 3 4 5 6 |
require 'vendor/autoload.php'; // Carbon use Carbon\Carbon; |
これで Carbon を使用する準備ができました。
現在日時を取得する
現在日時を取得するには下記のような感じになります。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
<?php require_once 'vendor/autoload.php'; // Carbon use Carbon\Carbon; // 現在日時を取得 $date = Carbon::now(); // 現在日時を出力: 2019-09-01 12:34:56 echo $date->toDateTimeString(); // UTCで取得 $date = Carbon::now('UTC'); // 現在日時を出力: 2019-09-01 03:34:56 echo $date->toDateTimeString(); // 日付を指定して取得: 2019/01/02 03:04:05 $date = Carbon::create(2019, 1, 2, 3, 4, 5); |
とても簡単ですね。
タイムゾーンを指定しない場合 php.ini の date.timezone の値が使用されます。
日時を加減する
日時の加算・減算をしたい場合は下記のような感じです。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
<?php require_once 'vendor/autoload.php'; // Carbon use Carbon\Carbon; // 日付を取得 $date = Carbon::now(); // 1日加算する $date->addDays(1); // 15分減算する $date->subMinutes(15); |
お察しかと思いますが、加算は add 、減算は sub です。
あとの項目は Years, Months, Days, Hours, Minutes, Seconds という名前で各項目を操作できます。
さらに Weekdays という名前を使用すると 営業日 で計算ができます。(祝日は計算されません)
ただし 月の操作は31日操作する というものですので、加減算時は要注意です。
日時を比較する
2つの日時を比較するには、下記のような感じです。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
require_once 'vendor/autoload.php'; // Carbon use Carbon\Carbon; // 日付1を取得 $date1 = Carbon::now(); // 日付2を取得 $date2 = Carbon::now('UTC'); // 同じ日かどうか: true $date1->isSameDay($date2); // 同じかどうか: false $date1->eq($date2); // date1 が date2 より過去か: 1=過去 $date1->diff($date2)->invert; |
1つ目のポイントは isSameDay と eq です。
一見同じように見えますが isSameDayは日付、 eqは日時 を見るという違いがあります。
また isSameDayはタイムゾーンを見ません が eqはタイムゾーンを見る などの違いもあります。
2つ目のポイントは diff->invert です。
invert は 負の場合に1になる という仕様なので、同じか正の値の場合は0となる点に気をつけましょう。
日時をフォーマットする
日時をフォーマットして出力するには下記のような感じです。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
require_once 'vendor/autoload.php'; // Carbon use Carbon\Carbon; // 日付を取得 $date = Carbon::now(); // 2019/01/02 13:04:05.123456 echo $date->format('Y/m/d H:i:s.u'); // PM 01:04:05 echo $date->format('A h:i:s'); // 2019/01/02(Wed) echo $date->format('Y/m/d(D))'); // 2019年01月02日(水) setlocale(LC_ALL, 'ja_JP.UTF-8'); echo $date->formatLocalized('%Y年%m月%d日(%a)'); // Unixtime(formatは文字列、timestampは数値) echo $date->format('U'); echo $date->timestamp; |
ここでのポイントは 日本語の曜日取得はLocaleを設定する というところでしょうか。
setlocale をコメントアウトするとわかりますが、普通に英語の短縮曜日名が返ってきます。
また、フォーマットに関する文字列は date 関数と同じものが使用できます。
その他の便利な情報
大枠で紹介する以外に、このライブラリを使用すると便利な情報が取得できますので、ご紹介していきます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 |
require_once 'vendor/autoload.php'; // Carbon use Carbon\Carbon; // Unixtimeから日付を取得 $date = Carbon::createFromTimestamp(1546365845); // 日付を判定: 未来、過去、今日、明日、昨日、うるう年、平日、週末、各曜日 $date->isFuture(); $date->isPast(); $date->isToday(); $date->isTomorrow(); $date->isYesterday(); $date->isLeapYear(); $date->isWeekday(); $date->isWeekend(); $date->isMonday(); // 誕生日かどうか $date = Carbon::now(); $birthday = Carbon::createFromTimestamp(946652400); $date->isBirthday($birthday); // 年齢を取得 $age = $date->age; // 数字のように比較: =, !=, <, >, <=, >=, A <= date <= B $date1 = Carbon:create(2019, 1, 1, 0, 0, 0); $date2 = Carbon:create(2019, 1, 2, 0, 0, 0); $date1->eq($date2); $date1->ne($date2); $date1->lt($date2); $date1->gt($date2); $date1->lte($date2); $date1->gte($date2); $date1->between(Carbon::parse('2019-01-01'), Carbon::parse('2019-12-31')); // 日付の差を指定した単位で取得: 秒、分、時間、日、週、月、年 $date1->diffInSeconds($date2); $date1->diffInMinutes($date2); $date1->diffInHours($date2); $date1->diffInDays($date2); $date1->diffInWeeks($date2); $date1->diffInMonths($date2); $date1->diffInYears($date2); // その月の日数 $date->daysInMonth; // 翌週の水曜日 $date = $date->next(Carbon::WEDNESDAY); // 日付オブジェクトのコピー $date2 = $date1->copy(); |
大体使いそうなものを列挙してみました。
ライブラリの中身を見ていると 誕生日かどうか まであるのはビックリですね。
日時を複製する場合、Unixtimeを取得してから新しいオブジェクトを生成しても良いのですが copy を使う方がお手軽です。
copyの場合はUnixtimeと違い、マイクロ秒までコピーされます。
注意点(2020/03/24 追記)
このCarbonで気を付け無ければならない点があります。
まずは下記のプログラムを見てください。
1 2 3 4 5 6 7 8 9 10 11 12 |
require_once 'vendor/autoload.php'; // Carbon use Carbon\Carbon; $date1 = Carbon::now(); $date2 = $date1->addDay(1); print_r($date1); print_r($date2); |
date1に1日加算した日付をdate2として取得したい、という場合に書いたソースコードです。
これの結果は下記のようになってしまいます。
(見やすいように整形してます)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
Carbon\Carbon Object ( [date] => 2020-03-25 17:37:17.689076 [timezone_type] => 3 [timezone] => Asia/Tokyo ) Carbon\Carbon Object ( [date] => 2020-03-25 17:37:17.689076 [timezone_type] => 3 [timezone] => Asia/Tokyo ) |
見事にdate1とdate2の日付が1日加算されました。
これは Carbonがミュータブルなこと に起因しています。
これは copy や clone をすれば解決することではありますが、直感的ではなくなってしまいます。
そのため、下記のような方法にすることで、意識せずともバグの発生を回避をすることができます。
イミュータブル型Carbonで使用しておく
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
require_once 'vendor/autoload.php'; // Carbon use Carbon\Carbon; use Carbon\CarbonImmutable; $date1 = CarbonImmutable::now(); // date2だけ1日加算する $date2 = $date1->addDay(1); print_r($date1); print_r($date2); |
イミュータブル型Carbonに変換してから使う
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
require_once 'vendor/autoload.php'; // Carbon use Carbon\Carbon; $date1 = Carbon::now(); // date2だけ1日加算する $date2 = $date1->toImmutable()->addDay(1); print_r($date1); print_r($date2); |
Composerが使えない・使わない場合
もし環境によりComposerが使えない場合やWindowsで使用する場合など、別の方法でインストールしたい時はこちらの記事をご参照ください。
PhpSpreadsheetを例に挙げた、Composerを使わずに使用する方法を記載しています。
さいご
よくある教科書的な書籍やサイトでは date 関数が用いられます。
しかし、業務で使用する場合などではどうにも不便になってしまいがち・・・。
また、グローバル化の対応をしようと思うと、日付まわりだけで時間を消費してしまうことも冗談ではありません。
そんな時はこの Carbon の使用を検討してみてはいかがでしょうか?
※このライブラリを使用しても 2038年問題 の解決にはなりませんので、予めご注意ください。
- おすすめ記事
POPULAR
のえる
Full-stack Developer