ごもちゃ箱BLOG

自作の PHP クラスライブラリ PEACH の開発日記です。

PHPでオレオレ時間管理モジュール

気が付いたら最後に日記を書いてからもう2ヶ月以上経ってしまいました。現在、オレオレ時間管理モジュール DT の単体テストをガリガリ書いているところです。

今作っているモジュールについて、コード例を踏まえて特徴を紹介します。

イミュータブル(副作用がない)

まず、デフォルトで定義されている DateTime クラスはこのような使い方をするとおもいます。

$d = new DateTime();
echo $d->format("Y-m-d") . "\n"; // 2012-08-27
$d->modify("-1 day");
echo $d->format("Y-m-d") . "\n"; // 2012-08-26
$d->modify("+2 day");
echo $d->format("Y-m-d") . "\n"; // 2012-08-28

このように modify メソッドによって変数 $d の内部データを書き換えてますが、このモジュールの時間オブジェクトはイミュータブルなので、副作用を気にする必要がありません。上に挙げたのと同じコードは、以下のように書くことができます。変数名を分かりやすく出来ることもポイントです。

$now       = DT_Date::now();
$yesterday = $now->add("date", -1);
$tomorrow  = $now->add("date",  1);
echo $now->format()       . "\n"; // 2012-08-27
echo $yesterday->format() . "\n"; // 2012-08-26
echo $tomorrow->format()  . "\n"; // 2012-08-28

さらに、フィールドを変更するメソッド (add, set など) の返り値が時間オブジェクトになるので、メソッドチェーンもできます。

// 現在から1年後の3日前の日付
$d = DT_Date::now()->add("year", 1)->add("date", -3);
echo $d->format() . "\n"; // 2013-08-24

必要なフィールドだけ扱うことが出来る

既存の DateTime は年・月・日・時・分・秒のすべてのフィールドの値を持っているため, 例えば日付だけの比較を行いたい場合などに、 いちいち時・分・秒を 0 で初期化する必要があったりして面倒な時があるんじゃないかと思うのですが (少なくとも自分はそう)、このモジュールでは日付・日時・秒までの時刻それぞれで別々のクラスを用意しています。

$d1 = DT_Date::now();
$d2 = DT_Datetime::now();
$d3 = DT_Timestamp::now();
echo get_class($d1)  . "\n"; // DT_Date
echo get_class($d2)  . "\n"; // DT_Datetime
echo get_class($d3)  . "\n"; // DT_Timestamp
echo $d1->format()   . "\n"; // 2012-08-27
echo $d2->format()   . "\n"; // 2012-08-27 20:30
echo $d3->format()   . "\n"; // 2012-08-27 20:30:45
echo $d1->get("min") . "\n"; // NULL
echo $d2->get("min") . "\n"; // 30
echo $d2->get("sec") . "\n"; // NULL
echo $d3->get("sec") . "\n"; // 45

別のクラス同士での比較も普通にできます。整数と浮動小数点数を比較するようなイメージです。ただし 2012-08-27 < 2012-08-27T00:00 < 2012-08-27T00:00:00 のような挙動を取る点は少し気をつけたほうが良いかもしれません。

$d1 = new DT_Date(2012, 8, 27);
$d2 = new DT_Datetime(2012, 8, 27, 20, 30);
var_dump($d1->after($d2)); // FALSE
var_dump($d2->after($d1)); // TRUE