序
Zend Frameworkに含まれているZend_Dateクラスは、インスタンス生成コストがとにかく高い。
どれくらい高いかというと、以下の2つのプログラムで比較してみるとなんとなく分かる。
<?php $n = 10000; if ($argc >= 2) { $n = (int)$argv[1]; } set_include_path(dirname(__FILE__) . DIRECTORY_SEPARATOR . 'library'); require_once('Zend/Date.php'); date_default_timezone_set('Asia/Tokyo'); $start = microtime(true); for ($i = 0; $i < $n; ++$i) { $zd = new Zend_Date('2015-08-01 03:04:05'); } $end = microtime(true); printf("%8.5lf\n", $end - $start);
<?php $n = 10000; if ($argc >= 2) { $n = (int)$argv[1]; } set_include_path(dirname(__FILE__) . DIRECTORY_SEPARATOR . 'library'); require_once('Zend/Date.php'); date_default_timezone_set('Asia/Tokyo'); $start = microtime(true); for ($i = 0; $i < $n; ++$i) { $zd = new DateTime('2015-08-01 03:04:05'); } $end = microtime(true); printf("%8.5lf\n", $end - $start);
- test0-3.php: Zend_Dateオブジェクトをキャッシュしておいて、strtotimeとsetTimestampで対応
<?php $n = 10000; if ($argc >= 2) { $n = (int)$argv[1]; } set_include_path(dirname(__FILE__) . DIRECTORY_SEPARATOR . 'library'); require_once('Zend/Date.php'); date_default_timezone_set('Asia/Tokyo'); $zd = new Zend_Date(); $start = microtime(true); for ($i = 0; $i < $n; ++$i) { $time = strtotime('2015-08-01 03:04:05'); $zd->setTimestamp($time); } $end = microtime(true); printf("%8.5lf\n", $end - $start);
これらを実行する。
$ for i in {1,2,5,8}{,00,000} ; do
> printf "%d" $i
> for t in test0-1.php test0-2.php test0-3.php ; do
> php ${t} ${i} | awk '{printf(",%s", $0);}'
> done
> printf "\n"
> done
1, 0.03093, 0.00011, 0.00004
100, 0.23281, 0.00048, 0.00074
1000, 2.32891, 0.00825, 0.01088
2, 0.01160, 0.00012, 0.00005
200, 0.48956, 0.00336, 0.00224
2000, 5.51129, 0.01458, 0.02203
5, 0.02411, 0.00018, 0.00012
500, 1.08754, 0.00409, 0.00425
5000,11.39618, 0.03983, 0.06424
8, 0.03674, 0.00031, 0.00000
800, 2.20668, 0.00417, 0.00931
8000,19.13784, 0.07557, 0.11488
$
並べ替えてグラフにしてみるとこんな感じ。

本
とりあえず、欲しいものは「日時計算をして、その結果を日時文字列にしたもの」ということで話を進める。
Zend_Dateオブジェクトをキャッシュして使いまわすとよさそうということで、上記「test0-3.php」をベースに、以下のような計測をしてみる。
<?php $n = 10000; if ($argc >= 2) { $n = (int)$argv[1]; } set_include_path(dirname(__FILE__) . DIRECTORY_SEPARATOR . 'library'); require_once('Zend/Date.php'); date_default_timezone_set('Asia/Tokyo'); function _test(Zend_Date $zd) { return $zd->toString('YYYY-MM-dd'); } $zd = new Zend_Date('2015-08-01 03:04:05'); //var_dump(_test($zd)); $start = microtime(true); for ($i = 0; $i < $n; ++$i) { _test($zd); } $end = microtime(true); printf("%8.5lf\n", $end - $start);
<?php $n = 10000; if ($argc >= 2) { $n = (int)$argv[1]; } set_include_path(dirname(__FILE__) . DIRECTORY_SEPARATOR . 'library'); require_once('Zend/Date.php'); date_default_timezone_set('Asia/Tokyo'); function _test(Zend_Date $zd) { $ts = $zd->getTimestamp(); return date('Y-m-d', $ts); } $zd = new Zend_Date('2015-08-01 03:04:05'); //var_dump(_test($zd)); $start = microtime(true); for ($i = 0; $i < $n; ++$i) { _test($zd); } $end = microtime(true); printf("%8.5lf\n", $end - $start);
<?php $n = 10000; if ($argc >= 2) { $n = (int)$argv[1]; } set_include_path(dirname(__FILE__) . DIRECTORY_SEPARATOR . 'library'); require_once('Zend/Date.php'); date_default_timezone_set('Asia/Tokyo'); function _test(Zend_Date $zd) { $year = $zd->get(Zend_Date::YEAR); $month = $zd->get(Zend_Date::MONTH); $day = $zd->get(Zend_Date::DAY); return sprintf("%04d-%02d-%02d", $year, $month, $day); } $zd = new Zend_Date('2015-08-01 03:04:05'); $start = microtime(true); for ($i = 0; $i < $n; ++$i) { _test($zd); } $end = microtime(true); printf("%8.5lf\n", $end - $start);
さて、実行。
$ for i in {1,2,5,8}{,00,000,0000} ; do
> printf "%d" $i
> for t in test1-1.php test1-2.php test1-3.php ; do
> php ${t} ${i} | awk '{printf(",%s", $0);}'
> done
> printf "\n"
> done
結果。
1, 0.00020, 0.00002, 0.00009 100, 0.01489, 0.00010, 0.01203 1000, 0.15603, 0.00634, 0.17088 10000, 1.28451, 0.04945, 1.37297 2, 0.00009, 0.00002, 0.00063 200, 0.02691, 0.00093, 0.04130 2000, 0.30510, 0.01436, 0.27488 20000, 2.93000, 0.12693, 3.37226 5, 0.00057, 0.00008, 0.00116 500, 0.08533, 0.00256, 0.07560 5000, 0.85879, 0.03124, 0.98879 50000,11.33206, 0.39485, 7.20063 8, 0.00063, 0.00009, 0.00074 800, 0.10203, 0.00917, 0.09432 8000, 0.86644, 0.03868, 0.81726 80000,12.23691, 0.57610,14.96780

さすがに各フィールドの値を取るのはコストが高いが、「test1-2.php」のケースが使えそうなレベル。
また、コードは省略するが、「test2-1.php」「test2-2.php」「test2-3.php」は時分秒まで含めるケース(「HH:mm:ss」「H:i:s」等の追加による)。
「test1-2.php/test2-2.php」はフォーマットに関係なくいいパフォーマンスを出しているが、Zend_Dateは時分秒まで含めるとそれだけコストが高くなる。
結
Zend_Dateクラスとは適度に付き合うのがよさそう(謎)。