DateTime
日時を表す3番目の形式DateTimeを紹介しましょう。
現在の日時
まず、date_create()で現在の日時を取得します。
$now=date_create();
表示の際、date()で使えたフォーマットをここでも使えます。
echo $now->format(DATE_ISO8601); // 2007-10-16T07:50:06+0000
日時の設定
ISO 8601形式の文字列でDateTimeオブジェクトを生成することができます(ほかにもGNU Date Input Formatに準拠した形式ならば使えるようです)。エポックタイムスタンプがintの範囲外にある日時も扱えます。
$date=date_create('1901-12-13T20:45:51+0000'); echo $date->format(DATE_ISO8601); // 1901-12-13T20:45:51+0000 //(正しい)
DateTime::modify(string $modify)を使って日時の移動ができるはずなのですが、1582年10月4日の翌日は、かなりおかしなことになっています。
$date=date_create('1582-10-04T00:00:00+0000'); $date->modify('+1 day'); echo $date->format(DATE_ISO8601); // 1582-09-24T00:00:00+0000 (間違い)
DateTimeは比較的新しく実装されたクラスのせいか(PHP 5.1以上)、このようなバグを含んでいます。また、PEAR Dateに比べて機能も劣っています。
ユリウス日
結局、標準に用意されている方法で1582年10月4日の翌日を10月15日にするためには、JulianToJD()でユリウス暦の日付をユリウス日に変換し、そのユリウス日に1を追加、JDToGregorian()でグレゴリオ暦の日付に直すという作業が必要になります。
$jd=JulianToJD(10,4,1582); $jd++; echo JDToGregorian($jd); // 10/15/1582 (正しい)
ユリウス日とは、ユリウス暦の紀元前4713年1月1日からの積算日のことです(ユリウス日とユリウス暦はまったく別物です)。ユリウス日を使えば、筆者の祖母が生まれてから今日で何日になるかも計算できます(PEARのDate_Spanでは扱えなかった期間です)。
$birthdayJD=GregorianToJD(3,8,1923); $now=date_parse(date_create()->format(DATE_ISO8601)); $nowJD=GregorianToJD($now[month],$now[day],$now[year]); echo $nowJD-$birthdayJD; // 30903 (正しい)
このように、ユリウス日を基準に考えることで、日付の計算を正しく行えます。
しかしながら、PHPのユリウス日には、それが「整数」だという致命的な欠点があります。1未満の数を使って時間を表すことができないのです。タイムゾーンのことを考えれば、日付と時刻を分離して管理してはいけないことは容易に想像できるでしょう。
また、いちいちユリウス日に変換しなければならないのも面倒です(内部的に行って欲しいものです)。ちなみに、Javaの場合、日時を管理するクラスGregorianCalendarのデフォルトの動作が「1548年10月4日以前はユリウス暦、それより後はグレゴリオ暦」ということになっているので、一般的なユーザーが1582年10月15日の暦の切り替えを意識する必要はありません(拙著『初級プログラマのためのWebアプリケーション構築入門』を参照してください)。
まとめ
PHPで日付と時刻を扱う標準的な方法を紹介しました。大きく分けて4つの方法があり、そのすべてに問題があることが分かりました。
- エポックタイムスタンプ
- PEAR Date
- DateTime
- ユリウス日
日付や時刻の処理を実装するのはとても大変なので、大抵の場合はプログラミング言語にあらかじめ備わっているライブラリやクラスを利用します。ライブラリには適用可能な範囲があり、その範囲内で使う分には問題ないのですが、その範囲を超えると結果はまったく信用できないものになってしまいます。
悪いことに、PHPの場合は適用範囲外で利用しようとしても、分かりやすいエラーが返らないことがほとんどです。かつての2000年問題や、今起こりつつある2038年問題のような問題を再び生まないためにも、この記事で紹介したようなケースを心にとめて開発していただきたいと思います。
この記事は参考になりましたか?
既に会員の方はを行ってください。
- この記事の著者
-
山田 祥寛(ヤマダ ヨシヒロ)
静岡県榛原町生まれ。一橋大学経済学部卒業後、NECにてシステム企画業務に携わるが、2003年4月に念願かなってフリーライターに転身。Microsoft MVP for Visual Studio and Development Technologies。執筆コミュニティ「WINGSプロジェクト」代表。主な著書に「独習シリーズ(Java・C#・Python・PHP・Ruby・JSP&サーブレットなど)」「速習シリーズ(ASP.NET Core・Vue.js・React・TypeScript・ECMAScript、Laravelなど)」「改訂3版JavaScript本格入門」「これからはじめるLaravel実践入門」「はじめてのAndroidアプリ開発 Kotlin編 」他、著書多数。
※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です
-
WINGSプロジェクト 矢吹 太朗(ヤブキ タロウ)
<WINGSプロジェクトについて>有限会社 WINGSプロジェクトが運営する、テクニカル執筆コミュニティ(代表 山田祥寛)。主にWeb開発分野の書籍/記事執筆、翻訳、講演等を幅広く手がける。 2026年時点での登録メンバは約50名で、現在も執筆メンバを募集中。興味のある方は、どしどし応募頂きたい。著書、記事多数。 RSS X: @WingsPro_info(公式)、@WingsPro_info/wings(メンバーリスト) Facebook
※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です
この記事は参考になりましたか?
この記事をシェア
