PHPの日時操作クラスと関数で日付・時間をスムーズに扱う
- 公開日
- カテゴリ:Basics
- タグ:PHP,Basics

PHP を用いて WEB アプリケーションを構築していると、日時を扱う事も多いと思います。 PHP で日時を操作する場合は、DateTime クラス、もしくは関数である strtotime を使います。
今回は PHP でデフォルトで利用できる(外部ライブラリを必要としない)オブジェクトや関数を用いて日時操作を行っていきます。
Contents
開発環境
今回の開発環境は以下の通りです。
- Linux CentOS 7
- Apache 2.4
- PHP 7.2
今回扱う内容は最低でも PHP5.2 以上であれば進めていけます。
PHP の日時について
ここで言う日時とは、年・月・日・時・分・秒・マイクロ秒の事を言います。 PHP の関数やクラスを用いて日時を操作する場合、日時を取得する先はスクリプトを実行している WEB サーバからになります。よって、アプリケーションを動作させるサーバのロケール設定をまず確認し、適切な日時を返す事を確認してください。
DateTime クラス
DateTime クラスでは、日時をオブジェクト指向で扱う事が出来ます。 PHP 5.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 関数はローカルの日付・時刻を書式化します。
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) からの通算秒として返します。
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 関数は、ロケールの設定に基づいてローカルな日付・時間をフォーマットします。
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 タイムスタンプとして取得します。
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 タイムスタンプに変換します。
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 プログラミングの基本なので、整理してきちんと理解しておくといざ使う時になって迷わなくてよいですね。