PHPの日時操作クラスと関数で日付・時間をスムーズに扱う
- 公開:
- カテゴリ: PHP Basics
- タグ: PHP,Basics
PHPを用いてWEBアプリケーションを構築していると、日時を扱う事も多いと思います。PHPで日時を操作する場合は、DateTimeクラス、もしくは関数であるdate/time/strftime/mktime/strtotimeを使います。
今回はPHPでデフォルトで利用できる(外部ライブラリを必要としない)オブジェクトや関数を用いて日時操作を行っていきます。
- アジェンダ
開発環境
今回の開発環境は以下の通りです。
- Linux CentOS 7
- Apache 2.4
- PHP 7.2
PHP7を使っていますが、今回扱う内容は最低でもPHP5.2以上であれば進めていけます。
PHPの日時について
ここで言う日時とは、年・月・日・時・分・秒・マイクロ秒の事を言います。PHPの関数やクラスを用いて日時を操作する場合、日時を取得する先はスクリプトを実行しているWEBサーバからになります。よって、アプリケーションを動作させるサーバのロケール設定をまず確認し、適切な日時を返す事を確認してください。
DateTimeクラス
DateTimeクラスでは、日時をオブジェクト指向で扱う事が出来ます。PHP5.2から利用可能です。
現在日時を任意のフォーマットで取得
// DateTimeクラス インスタンス化
$d = new DateTime();
// 任意のフォーマットで出力
echo $d->format('Y-m-d H:i:s');
// => 2018-08-18 07:35:30
echo $d->format('Y年m月d日 H時i分s秒');
// => 2018年08月18日 07時35分30秒
現在日時を取得するには、DateTimeクラスのインスタンス化の際に引数には日時を渡さない事で暗黙的に現在日時として設定されます。(日時については、インスタンス化後にセットする事も可能です)
任意のフォーマットで取得・表示するには、format() メソッドを用いて、引数に任意のフォーマットを渡します。
指定日時から任意のフォーマットで出力
// 指定日時
$date = '2018-08-18 07:35:30';
// DateTimeクラス インスタンス化
$d = new DateTime($date);
// 任意のフォーマットで出力
echo $d->format('Y-m-d H:i:s');
// => 2018-08-18 07:35:30
echo $d->format('Y/m/d');
// => 2018/08/18
任意の日時を扱うには、DateTimeクラスのインスタンス化の際に引数に日時を渡します。その後、フォーマットを指定して出力します。
setDate()
コンストラクタに渡さない場合でも、setDate()メソッドを用いる事で年月日をセットする事が出来ます。
$yaer = 2018;
$month = 8;
$day = 18;
// DateTimeクラス インスタンス化
$d = new DateTime();
// 年月日をセット
$d->setDate($yaer, $month, $day);
// 任意のフォーマットで出力
echo $d->format('Y-m-d');
// => 2018-08-18
setDate() メソッドにセットできるのは年月日だけです。また、引数は全て必須です。
setDate( int $year , int $month , int $day )
setTime()
時刻をセットする場合は、setTime()メソッドを使います。
$hour = 7;
$minute = 3;
$second = 12;
// DateTimeクラス インスタンス化
$d = new DateTime();
// 時分秒をセット
$d->setTime($hour, $minute, $second);
// 任意のフォーマットで出力
echo $d->format('H:i:s');
// => 07:03:12
setTime()メソッドでは、引数に時・分・秒を渡しますが、必須なのは時間と分です。秒はデフォルトで0が渡されます。
setTime ( int $hour , int $minute [, int $second = 0 ] )
もちろん、これらを組み合わせても使う事が出来ます。
$yaer = 2018;
$month = 8;
$day = 18;
$hour = 7;
$minute = 3;
$second = 12;
// DateTimeクラス インスタンス化
$d = new DateTime();
// 年月日をセット
$d->setDate($yaer, $month, $day);
// 時分秒をセット
$d->setTime($hour, $minute, $second);
// 任意のフォーマットで出力
echo $d->format('Y-m-d H:i:s');
// => 2018-08-18 07:03:12
別々でもセットできますし、チェーンさせる事も可能です。
// 年月日・時分秒をセット
$d->setDate($yaer, $month, $day)->setTime($hour, $minute, $second);
createFromFormat()
渡す日時のフォーマットを指定する事もできます。createFromFormat()メソッドを用います。
$date = '2018年08月18日 07時03分12秒';
$format = 'Y年m月d日 H時i分s秒';
$d = DateTime::createFromFormat($format, $date);
echo $d->format('Y-m-d H:i:s');
// => 2018-08-10 17:14:25
$d = DateTime::createFromFormat('Y m d H i s', '2018 08 10 17 14 25');
echo $d->format('Y/m/d H時i分s秒');
// => 2018/08/10 17時14分25秒
第一引数には渡す日時のフォーマット、そして第二引数に日時を渡します。createFromFormat()メソッドは静的メソッドで使うのがポイントです。
createFromFormat ( string $format , string $time [, DateTimeZone $timezone ] )
定義済み書式で現在日時を出力
DateTimeクラスには、既に定義済みの日時フォーマットが定数で容易されており、これらを使えば複雑に英字を取り回さなくても良くなります。
// ATOM形式
echo $d->format(DateTime::ATOM);
// => 2018-08-18T07:18:39+09:00
// HTTP Cookie形式
echo $d->format(DateTime::COOKIE);
// => Saturday, 18-Aug-2018 07:19:24 JST
// RFC 822形式
echo $d->format(DateTime::RFC822);
// => Sat, 18 Aug 18 07:20:41 +0900
// RFC 850形式
echo $d->format(DateTime::RFC850);
// => Saturday, 18-Aug-18 07:21:10 JST
// RFC 1036形式
echo $d->format(DateTime::RFC1036);
// Sat, 18 Aug 18 07:21:52 +0900
// RFC 1123形式
echo $d->format(DateTime::RFC1123);
// => Sat, 18 Aug 2018 07:22:21 +0900
// RFC 2822形式
echo $d->format(DateTime::RFC2822);
// => Sat, 18 Aug 2018 07:22:44 +0900
// RSS形式
echo $d->format(DateTime::RSS);
// => Sat, 18 Aug 2018 07:21:17 +0900
// W3C日時形式
echo $d->format(DateTime::W3C);
// => 2018-08-18T07:23:37+09:00
タイムゾーン
タイムゾーン情報の取得と出力は以下にして行います。
$d = new DateTime();
// タイムゾーン情報の取得
$timezone = $d->getTimezone();
// タイムゾーン名を出力
echo $timezone->getName();
// => UTC
- getTimezone()メソッドでタイムゾーン情報の取得を行います。
- getName()メソッドで、取得したタイムゾーンからタイムゾーン名を出力します。
ちなみにタイムゾーン情報は、他にtimezone_typeを保有します。
print_r($d->getTimezone());
=> DateTimeZone Object
(
[timezone_type] => 3
[timezone] => UTC
)
タイムゾーンの設定は、コンストラクタに渡すパターンと、setTimezone()メソッドを用いるパターンで設定できます。
$d = new DateTime();
// タイムゾーンの設定
$d->setTimezone(new DateTimeZone('Asia/Tokyo'));
setTimezone()メソッドでは、DateTimeZoneクラスのインスタンス化と共にセットするタイムゾーンを渡します。
$d = new DateTime(null, new DateTimeZone('Europe/Rome'));
コントラスタに渡す場合は、第一引数に日時、第二引数にDateTimeZoneインスタンスを渡します。
日時操作/modify()
日時操作、いわゆる日時を進めたり戻したりするには、modify()メソッドを用います。
$d = new DateTime('2018-08-18 07:53:02');
// 1日進める
$d->modify('+1 day');
echo $d->format('Y-m-d');
// => 2018-08-19
// 1日戻す
$d->modify('-1 day');
echo $d->format('Y-m-d');
// => 2018-08-17
$d->modify('+1 week'); // 1週間進める
$d->modify('next week'); // 1週間進める
$d->modify('-1 week'); // 1週間戻す
$d->modify('+1 month'); // 1ヵ月進める
$d->modify('next month'); // 1ヵ月進める
$d->modify('-1 month'); // 1ヵ月戻す
$d->modify('+1 year'); // 1年進める
$d->modify('next year'); // 1年進める
$d->modify('-1 year'); // 1年戻す
$d->modify('+1 hour'); // 1時間進める
$d->modify('next hour'); // 1時間進める
$d->modify('-1 hour'); // 1時間戻す
$d->modify('last hour'); // 1時間戻す
$d->modify('first day of this month'); // 指定日月の月初日
$d->modify('last day of this month'); // 指定日月の月末日
$d->modify('wednesday'); // 指定日(を含む)以降の日曜日
$d->modify('wednesday this week'); // 指定日の週の水曜日
$d->modify('first monday of this month'); // 指定日の月の第一月曜日
$d->modify('first day of next month'); // 指定日の次の月の月初日
$d->modify('first day of last month'); // 指定日の前の月の月初日
$d->modify('last day of next month'); // 指定日の次の月の月末日
$d->modify('last day of last month'); // 指定日の前の月の月末日
$d->modify('1year + 2month + 3day + 4hour'); // 1年+2ヵ月+3日+4時間進める
わりと使うものだけ抜粋しましたが、書式は他にもたくさんあります。これ以上はPHPマニュアルを参照してください。
相対的な書式
http://php.net/manual/ja/datetime.formats.relative.php
日時の差分/diff()
日時の差分を取るには、diff()メソッドを用います。
// 日付の差
$datetime_1 = new DateTime('2018-08-18');
$datetime_2 = new DateTime('2018-09-21');
$interval = $datetime_1->diff($datetime_2);
echo $interval->format('%R%a days');
// => +34 days
// 時間の差
$datetime_3 = new DateTime('2018-08-18 12:00:00');
$datetime_4 = new DateTime('2018-09-18 16:00:00');
$interval = $datetime_3->diff($datetime_4);
echo $interval->format('%R%h hours');
// => +4 hours
比較演算子による日時比較
PHP 5.2.2 以降でDateTimeオブジェクトを比較演算子で比較できるようになっています。
$datetime_1 = new DateTime('2018-08-20 23:59:59');
$datetime_2 = new DateTime('2018-09-21 00:00:00');
var_dump($datetime_1 == $datetime_2);
// => boolean false
var_dump($datetime_1 < $datetime_2);
// => boolean true
var_dump($datetime_1 > $datetime_2);
// => boolean false
日時の比較は良く使いますが、簡単に比較が行えるので便利です。
DateTimeImmutableクラス
DateTimeImmutableクラスは、イミュータブル(不変的)な日時操作を行う為のオブジェクトです。
DateTimeImmutableクラスの機能はDateTimeクラスとほぼ同じですが、自身は変更せずに新しいオブジェクトを返します。つまり、元々の日時データは変更せずに、変更した新しいオブジェクトを返却します。
DateTimeクラスは参照型なので、現在日時やセットした日時を変更すれば、保持している日時情報も変更されますが、こちらのクラスは元々の日時情報は変更されません。つまりは、1つの日時情報を基にして、色々と日時操作を行う場合などにはこちらのクラスの方が使えます。
$date = '2019-01-01';
// DateTimeクラス インスタンス化
$d1 = new DateTime($date);
// 1日進める
$d2 = $d1->modify('+1 days');
echo $d2->format('Y-m-d');
// => 2019-01-02
echo $d1->format('Y-m-d');
// => 2019-01-02
// DateTimeImmutable インスタンス化
$di1 = new DateTimeImmutable($date);
// 1日進める
$di2 = $di1->modify('+1 days');
echo $di2->format('Y-m-d');
// => 2019-01-02
echo $di1->format('Y-m-d');
// => 2019-01-01
date()
date関数はローカルの日付・時刻を書式化します。使用できるPHPのバージョンは4/5/7です。
date ( string $format [, int $timestamp = time() ] )
第一引数には日時フォーマット、第二引数にはオプションでタイムスタンプを渡します。タイムスタンプを渡さない場合はデフォルトで現在日時を対象として処理が行われます。
// 現在日時をdatetime形式で出力
echo date('Y-m-d H:i:s');
// => 2018-08-18 08:21:07
// 定数で書式指定
echo date(DATE_ATOM);
// => 2018-08-18T08:21:38+09:00
// 現在日時の1日先のタイムスタンプを取得
$timestamp = strtotime("+1 day");
echo $timestamp;
// => 1534634508
// 第二引数にタイムスタンプを渡す事で任意の日時を任意のフォーマットで出力する
echo date('Y-m-d H:i:s', $timestamp);
// => 2018-08-19 08:21:48
time()
time関数はシンプルに現在のUnixタイムスタンプを返します。現在時刻はUnixエポックタイム(1970年1月1日 00:00:00 GMT) からの通算秒として返します。使用できるPHPのバージョンは4/5/7です。
echo time();
// => 1534634572
date関数と組み合わせても使えます。
// 1日先の日時を出力する
echo date('Y-m-d H:i:s', time() + (60 * 60 * 24));
// => 2018-08-20 08:21:48
time()で現在日時のタイムスタンプが返りますが、以下のようにする事で、日時加算を行う事も出来ます。
time() + 60 => 1分先
time() + (60 * 60) => 1時間先
time() + (60 * 60 * 24) => 1日先
time() + (60 * 60 * 24 * 365) => 1年先
strftime()
strftime関数は、ロケールの設定に基づいてローカルな日付・時間をフォーマットします。使用できるPHPのバージョンは4/5/7です。
strftime ( string $format [, int $timestamp = time() ] )
第一引数には日時フォーマット、第二引数にはオプションでタイムスタンプを渡します。タイムスタンプを渡さない場合はデフォルトで現在日時を対象として処理が行われます。
// 現在日時を表示
echo strftime('%Y-%m-%d %H:%M:%S');
// => 2018-08-18 08:23:19
// 任意の日時を表示
echo strftime('%Y-%m-%d %H:%M:%S', strtotime("+1 day"));
// => 2018-08-19 08:24:02
strftime関数はdate関数と良く似ています。両者の違いは、日時フォーマットの書式が違う事と、こちらはロケール設定に基づいた処理を行うので、setlocale()でセットしたロケールによって月だったり曜日だったりが変化します。(例えば英語と日本語とか)
mktime()
mktime関数は、日付をUnixタイムスタンプとして取得します。使用できるPHPのバージョンは4/5/7です。
mktime(
int $hour = date("H"),
int $minute = date("i"),
int $second = date("s"),
int $month = date("n"),
int $day = date("j"),
int $year = date("Y")
)
引数に時・分・秒・月・日・年を渡しますが、右から順に省略する事が可能です。引数を全て渡さない場合は、現在日時のタイムスタンプを返します。
// 現在のUnixイムスタンプを出力する
echo mktime();
// => 1534634520
// 任意の日時(2018-08-19 08:22:52)のタイムスタンプを出力する
$timestamp = mktime(8, 22, 52, 8, 19, 2018);
echo $timestamp;
// => 1534634572
// DATETIME形式で出力する
echo date('Y-m-d H:i:s', $timestamp);
// => 2018-08-19 08:22:52
date関数と組み合わせて任意の日時を出力する事もできます。
strtotime()
strtotime関数は、英文形式の日付をUnixタイムスタンプに変換します。使用できるPHPのバージョンは4/5/7です。
strtotime(
string $time,
int $now = time()
)
引数に英字文字列での相対的な日時指定と、タイムスタンプを渡しますが、第二引数は必須ではありません。第一引数のみを指定した場合は、現在日時のタイムスタンプを基準としてその結果を返します。
// 現在日時のUnixタイムスタンプ
echo strtotime('now');
// => 1534548516
// 1日後
echo strtotime('+1 day');
// => 1534634928
// 1週間後
echo strtotime('next week');
// => 1535239728
strtotime関数もdate関数と組み合わせて任意の日時を出力する事ができます。以下の例は、現在日時から1年と1か月後の日時をDATETIME形式で出力しています。
// DATETIME形式で出力する
echo date('Y-m-d H:i:s', strtotime('+1 year +1 month'));
// => 2019-09-18 14:31:46
まとめ
このように、PHPで日時操作を行う為の関数やクラスは複数ありますが、1つ1つ丁寧に見ていくとそれら個々の役割や使いどころもよくわかってきます。日時操作はPHPプログラミングの基本なので、整理してきちんと理解しておくといざ使う時になって迷わなくてよいですね。