DateTimeクラスを使ったモダンな日付処理
こんにちは。小川です。
今回はPHPのDateTimeクラスについてご紹介します。
-----------------------------------
最初に告知です。日本Symfonyユーザー会を設立しました!
ユーザー会の活動として、
- 入門者向けのサポート活動
- メーリングリストの運営
- ドキュメントの整理
- 公式ドキュメントやブログの翻訳
- 勉強会などのイベントの開催
などを行っていきます。また、昨晩に第1回 Symfonyユーザー会IRC集会を行いました。今後も定期的にIRCで集会を行います。内容はsymfonyに関する質問にお答えしたり、議論をしたりなど様々です。次回は6/20(日)の21時~23時開催を予定していますので、ぜひぜひご参加ください!
※ちなみにアシアルとしては金銭の管理やサーバーの提供などを行っています。Webサイトのデザインもアシアルのデザイナーが行いました。
-----------------------------------
さて本題です。皆さんDateTimeクラスはご存知ですか?PHPをお使いの方ならばdate()関数はよく使われていると思います。DateTimeは日付をオブジェクトとして扱うためのクラスで、PHP 5.2.0以降から利用可能です。例えば次のようなコードがあったとします。
これをDateTimeオブジェクトに置き換えると次のようになります。
次に、特定の日付から3ヵ月引いた日付を出す例です。
DateTimeを使うと次のようになります。下の例はPHP 5.3.0以降で利用可能なDateIntervalクラスを用いた例です。
DateTimeなら2038年問題も大丈夫です。
DateTimeではDateTimeZoneクラスを用いてタイムゾーンを設定することも可能です。DateTimeZoneはDateTimeのコンストラクタの第2引数にも指定可能です。
2つのDateTimeのdiffをとることも可能です。
DateTime::diff()メソッドは2つのDateTimeの差分をDateIntervalオブジェクトとして返します。そのためこれはPHP 5.3.0以降から使える機能になります。
--------------------------------
Error401さんよりコメントいただき、一部の環境でDateTime::diff()にバグがあるようです。詳細はコメントをご覧ください。
--------------------------------
日付のイテレーションを行うDatePeriodクラスもあります。次の例は6月1日から6月30日までを1日ずつループする例です。これもPHP 5.3.0からの機能です。
ちょっとだけ気を付けなければならないのが new DateTime('last day of 2010-06') とすると6月30日の日付がとれるのですが、時間が00:00:00のままだとイテレーションの対象にならないようです。ですので
+1 secondsとして1秒だけ追加してあげています。(バグ?仕様?)
---------------------
追記。上記の件でもしかしてバグ?とか思って、bugs.php.netにレポートしてみました。
#52015 Ending date is ignored while iterating DatePeriod
書いた後、後方互換性が失われるので、きっとオプションで対応することになるのかなと思ったら案の定その方向で対応されるそうです。
---------------------
手短でしたが、以上がDatetimeクラスおよびそれに関連するクラスの紹介になります。詳細はPHPマニュアルをご覧ください。
いくつかサンプルを出しましたが、DateTimeを使ったからといって記述が短くなるとかそういった話ではありません。重要なのは、日付をオブジェクトとして扱えるということです。
オブジェクトの状態として日付を保持しているのであれば、フォーマットに依存せずに日付を処理することが可能です。
PHP 5でオブジェクト指向機能の強化が行われて以降、SPLやPDOを筆頭にPHP内部のクラスが充実していっています。オブジェクトで扱えると操作しやすくていいですね。今後もこういったオブジェクト指向機能の強化や、クラスの拡張などが行われていくと思われます。今後のPHPの流れに乗り遅れないためにもぜひ皆さんDateTimeを活用していきましょう!
※アシアルのPHPスクールに最近オブジェクト指向編ができましたので、オブジェクト指向がよくわからない方はぜひ受講してください。講師は僕が務めさせていただきます。
--------
ちなみに6月18日は僕の誕生日です。今年で23歳になります。よく「28くらいですか?」とか言われるのですが全然そんなことはないです。アシアルの正社員の中でもまだ最年少をキープしています。
ここまでやってこれたのも、アシアルの社員の方々に色々ご指導いただいたり、勉強会などで多くの方々に色々教えていただいたおかげです。
皆さま今後とも、ご指導ご鞭撻のほどよろしくお願いします!。
今回はPHPのDateTimeクラスについてご紹介します。
-----------------------------------
最初に告知です。日本Symfonyユーザー会を設立しました!
ユーザー会の活動として、
- 入門者向けのサポート活動
- メーリングリストの運営
- ドキュメントの整理
- 公式ドキュメントやブログの翻訳
- 勉強会などのイベントの開催
などを行っていきます。また、昨晩に第1回 Symfonyユーザー会IRC集会を行いました。今後も定期的にIRCで集会を行います。内容はsymfonyに関する質問にお答えしたり、議論をしたりなど様々です。次回は6/20(日)の21時~23時開催を予定していますので、ぜひぜひご参加ください!
※ちなみにアシアルとしては金銭の管理やサーバーの提供などを行っています。Webサイトのデザインもアシアルのデザイナーが行いました。
-----------------------------------
さて本題です。皆さんDateTimeクラスはご存知ですか?PHPをお使いの方ならばdate()関数はよく使われていると思います。DateTimeは日付をオブジェクトとして扱うためのクラスで、PHP 5.2.0以降から利用可能です。例えば次のようなコードがあったとします。
- $date
= date('Y-m-d', strtotime('+3 months')); - echo
$date . "\n"; - //
=> 2010-09-07
これをDateTimeオブジェクトに置き換えると次のようになります。
- $dt
= new DateTime('+3 months'); - echo
$dt->format('Y-m-d') . "\n"; - //
=> 2010-09-07
次に、特定の日付から3ヵ月引いた日付を出す例です。
- $date
= date('Y-m-d', strtotime('2010-09-18 -3 months')); - echo
$date . "\n"; - //
=> 2010-06-18
DateTimeを使うと次のようになります。下の例はPHP 5.3.0以降で利用可能なDateIntervalクラスを用いた例です。
- $dt
= new DateTime('2010-09-18 -3 months'); - echo
$dt->format('Y-m-d') . "\n"; - //
=> 2010-06-18 - //
PHP 5.3.0以降 - $dt
= new DateTime('2010-09-18'); - $interval
= DateInterval::createFromDateString('-3 months'); - echo
$dt->add($interval)->format('Y-m-d') . "\n"; - //
=> 2010-06-18
DateTimeなら2038年問題も大丈夫です。
- $date
= date('Y-m-d', strtotime('2038-04-01')); - echo
$date . "\n"; - //
1970-01-01 - $dt
= new DateTime('2038-04-01'); - echo
$dt->format('Y-m-d') . "\n"; - //
2038-04-01
DateTimeではDateTimeZoneクラスを用いてタイムゾーンを設定することも可能です。DateTimeZoneはDateTimeのコンストラクタの第2引数にも指定可能です。
- $dt
= new DateTime(); - //
Asia/Tokyo - echo
$dt->setTimeZone(new DateTimeZone('Asia/Tokyo')) ->format('Y-m-d H:i') . "\n"; - //
2010-06-07 15:40 - //
Europe/London - echo
$dt->setTimeZone(new DateTimeZone('Europe/London')) ->format('Y-m-d H:i') . "\n"; - //
2010-06-07 07:40
2つのDateTimeのdiffをとることも可能です。
- $dt1
= new DateTime('2010-06-18'); - $dt2
= new DateTime('2010-06-07'); - echo
$dt1->diff($dt2)->format('誕生日まであと %a 日') . "\n"; - //
誕生日まであと 11 日
DateTime::diff()メソッドは2つのDateTimeの差分をDateIntervalオブジェクトとして返します。そのためこれはPHP 5.3.0以降から使える機能になります。
--------------------------------
Error401さんよりコメントいただき、一部の環境でDateTime::diff()にバグがあるようです。詳細はコメントをご覧ください。
--------------------------------
日付のイテレーションを行うDatePeriodクラスもあります。次の例は6月1日から6月30日までを1日ずつループする例です。これもPHP 5.3.0からの機能です。
- $period
= new DatePeriod( new DateTime('first day of 2010-06'), new DateInterval('P1D'), new DateTime('last day of 2010-06 +1 second') - );
- foreach
($period as $day) { echo $day->format('Y-m-d') . "\n"; - }
- //
2010-06-01 - //
2010-06-02 - //
(中略) - //
2010-06-29 - //
2010-06-30
ちょっとだけ気を付けなければならないのが new DateTime('last day of 2010-06') とすると6月30日の日付がとれるのですが、時間が00:00:00のままだとイテレーションの対象にならないようです。ですので
+1 secondsとして1秒だけ追加してあげています。(バグ?仕様?)
---------------------
追記。上記の件でもしかしてバグ?とか思って、bugs.php.netにレポートしてみました。
#52015 Ending date is ignored while iterating DatePeriod
書いた後、後方互換性が失われるので、きっとオプションで対応することになるのかなと思ったら案の定その方向で対応されるそうです。
---------------------
手短でしたが、以上がDatetimeクラスおよびそれに関連するクラスの紹介になります。詳細はPHPマニュアルをご覧ください。
いくつかサンプルを出しましたが、DateTimeを使ったからといって記述が短くなるとかそういった話ではありません。重要なのは、日付をオブジェクトとして扱えるということです。
オブジェクトの状態として日付を保持しているのであれば、フォーマットに依存せずに日付を処理することが可能です。
PHP 5でオブジェクト指向機能の強化が行われて以降、SPLやPDOを筆頭にPHP内部のクラスが充実していっています。オブジェクトで扱えると操作しやすくていいですね。今後もこういったオブジェクト指向機能の強化や、クラスの拡張などが行われていくと思われます。今後のPHPの流れに乗り遅れないためにもぜひ皆さんDateTimeを活用していきましょう!
※アシアルのPHPスクールに最近オブジェクト指向編ができましたので、オブジェクト指向がよくわからない方はぜひ受講してください。講師は僕が務めさせていただきます。
--------
ちなみに6月18日は僕の誕生日です。今年で23歳になります。よく「28くらいですか?」とか言われるのですが全然そんなことはないです。アシアルの正社員の中でもまだ最年少をキープしています。
ここまでやってこれたのも、アシアルの社員の方々に色々ご指導いただいたり、勉強会などで多くの方々に色々教えていただいたおかげです。
皆さま今後とも、ご指導ご鞭撻のほどよろしくお願いします!。
コメント
コメントフォーム
トラックバック
最近の記事
- もうすぐ健康診断があるんだ・・・ [2010年09月02日 : 阿部恵]
- Photoshopで壁紙を作りながら、基本的な使い方を覚える [2010年09月01日 : 鴨田健次]
- はじめての共同作業 Canvas編 (node.js + websocket) [2010年09月01日 : 中川善樹]
- 「PHP×Flex(後編)」PHPテクニカルセミナー(無料)第4弾の募集を開始しました!! [2010年08月26日 : 和田記光]
- 【HTML5】Canvasでお絵かきしてみた(前編) [2010年08月25日 : 橋本章史]
- MacにgroongaのMySQL用ストレージエンジン [2010年08月23日 : 笹亀弘]
- Appleのサイトで見たiPhone4をFireworksで描いてみました-1/2 [2010年08月19日 : 和田記光]
- iPad版の会社紹介を作ってみました [2010年08月19日 : 小林有佳]
- iPhoneアプリ開発開始時に気をつけるべきファイルの取り扱い (2) [2010年08月19日 : 亀本大地]
- symfonyセミナー動画無料公開! [2010年08月13日 : 岡本雄樹]



日付差が6015日になるバグです。以下を参照。
http://bugs.php.net/bug.php?id=51184
ご報告ありがとうございます!バグの件について、本文中に追記させていただきました。
# それにしてもとんでもないバグですね
#51184がfixされているかと思ったのですが、リリースノートには表記がありませんでした。
で、http://bugs.php.net/bug.php?id=51184を確認しにいったら、Wont fix(修正はしないよ)でcloseされていました。
> [2010-06-14 10:50 UTC] pajoye@php.net
>
> Sorry, I meant won't fix. It is not something we can easily fix, use the VC9 versions instead (apachelounge.com for the VC9 versions of apache).
とのことです。(要約:ごめん、VC9バージョン使ってね)
なるほどー。PHP 5.3は可能な限りVC9バージョンを使った方がよいのですかね。(僕はLinuxユーザなのでこのあたりは意識しないのですが・・・)
ちなみに5.3.3では#52015もfixされていませんでした。ライブラリなどでDatePeriodを使って何かしたいとき、結局対応するバージョンの幅を広げたいと思ったら、+1 secondsのような形で対応になるのかなーと考えると、開発バージョンのうちから新しい機能は試しておいた方がいいですねえ。。。