Zend Framework [6] - Zend_Dateの問題点

2007.12.14 Author: Jas

Zend Framework Reference Guideの「9.5.3. 配列からの日付の作成」に以下のように書いてありました。

通常は、新しい日付インスタンスを作成する際には完全な形式の日付配列を渡します。 しかし、指定されていない項目があった場合は、 その項目の値はゼロとして処理されます。 つまり、たとえば hour を指定しなかった場合は 0 時として扱われるということです。

要するに、mkdate(0, 0, 0, 12, 14, 2007);のように、インスタンス生成時に「'hour' => 0, 'minute' => 0, 'second' => 0」と記述しなくてもいいというわけです。これは便利ですね。

ただ、ここでふと疑問がわいてきました。
「年月日を指定しなかったらどうなるんだろう?」

ということで、今回はその検証と、その他Zend_Dateの問題点を紹介します。

それでは、実際に年月日を指定せずに日付のインスタンスを生成してみましょう。


$datearray = array('hour' => 17, 'second' => 3);
$date = new Zend_Date($datearray);
echo $data;

すると、画面には以下のように表示されました。
「00-1/11/30/ 17:00:03」

年のところの表示が"00-1"となっています。
-1年でしょうか?それにしても、年の表示としては不適切な表示です。

月日の部分はというと、どうやら前の月の末日が表示されているようです。
これは、PHPのmktime()と同じ挙動です。
試しに以下のように記述すると、「1999/11/30 00:00:00」と表示されるでしょう。


echo date("Y/m/d H:i:s", mktime(0,0,0,0,13,0));

もう少しこの挙動を調べてみましょう。
年・月・日のいずれか一つだけが不足した状態でインスタンスを生成してみます。


$datearray1 = array('month' => 3, 'day' => 10);
$date1 = new Zend_Date($datearray1);
echo $date1;

$datearray2 = array('year' => 2005, 'day' => 10);
$date2 = new Zend_Date($datearray2);
echo $date2;

$datearray3 = array('year' => 2005, 'month' => 3);
$date3 = new Zend_Date($datearray3);
echo $date3;


その結果は以下のようになります。

1.$data1の場合: 0000/03/10 0:00:00
2.$data2の場合: 2004/12/10 0:00:00
3.$data3の場合: 2005/02/28 0:00:00

年を指定しない場合は、マニュアルに記載の通り「指定されていない項目があった場合は、 その項目の値はゼロとして処理」され、0000年となりました。
それに対して、月または日を指定しない場合は、mkdate()で月または日に0を指定した場合と同じ結果でした。

要するに・・・

インスタンス生成時には年月日は必ず指定して使いましょう!

ということですね。
mktime()と同じ挙動とはいっても、意としない日付になるのは大変危険です。


ところで、年月日のすべてを指定しない場合に年の表示が"00-1"となっていたので、この原因についてもう少し調べてみましょう。


$date4 = new Zend_Date();
$date4->sub(2010, Zend_Date::YEAR);
echo $data4;

$date5 = new Zend_Date();
$date5->sub(2010, Zend_Date::YEAR);
echo $data5;

$date6 = new Zend_Date();
$date6->add(10000, Zend_Date::YEAR);
echo $data6;

$date7 = new Zend_Date();
$date7->sub(5000, Zend_Date::YEAR);
echo $data7;


4.現在日時から1500年減算の場合: 0507/12/14 18:48:47
5.現在日時から2010年減算の場合: 00-3/12/14 18:50:25
6.現在日時に10000年加算の場合: 12007/12/14 18:51:09
7.現在日時から5000年減算の場合: -2993/12/14 18:54:41

この結果からZend Framework内部で日付がどのように扱われているか一目瞭然です。

年の値が1000未満の場合でも、4桁の文字列として扱われています。
しかも、年がマイナスになる場合(紀元前!?)はマイナス(-)まで右詰にされ、4桁に足りない部分には0で埋めてあります。

そう、sprintf()のフォーマットで"%04s"の扱いになっているんですね。
そのため、西暦-99年から999年までの日付を扱うと、表記がおかしくなってしまうので注意が必要です。


以上、今回の検証からZend Frameworkの日付関数にはいくつかの問題点がわかりました。
しかし、mktime()のように常に時分秒まで指定しなくてもよいのは便利ですし、-99年~999年までの扱いには注意が必要とはいえ、1970年から2037年の範囲外の日付を扱えるようになるのは魅力的です。
問題点を理解した上で、Zend_Dateを上手に利用していきましょう。

名古屋のWebシステム開発・ネットワーク構築会社 コネクティボへ