Zend_Date の年指定子には’y’を使おう

Zend_Date のget()メソッドを使って、独自形式で日付文字列を取得したい場合に、
日付出力に関する定数を使って取得することも多いと思います。
例えば、’YYYY-MM-dd’ という指定で、年月日のハイフン区切り文字列を期待できますが、
‘YYYY-MM-dd’ ではなく、 ‘yyyy-MM-dd’ とした方が無難です。

Zend_Date Y指定子とy指定子 の説明

Zend_Dateのマニュアルに、’Y’と’y’に関する、気になる説明があります。

「年」 については、間違えやすい指定子がふたつあります。 ISO 形式の年を表す Y 指定子と、 実際の年を表す y 指定子です。 両者の違いは些細なものではありますが、非常に重要です。 Y は ISO 形式の年を算出するものです。 これは、カレンダーを作成する際によく用いられます。 2007 年 12 月 31 日を例にとって考えてみましょう。 実際の年は 2007 ですが、この日は 2008 年の最初の週 (第 1 週) の最初の日でもあります。 したがって、’dd.MM.yyyy’ として場合は ’31.December.2007′ が得られますが、’dd.MM.YYYY’ とした場合の結果は ’31.December.2008′ となるのです。これはバグではなく、期待通りの振る舞いです。 これが、ふたつの指定子の違いとなります。
日付関数全般用の定数 – Zend_Date – Zend Framework

オブジェクトの保持する日付の週番号が、実際の年の翌年に属する場合、‘Y’によって得られる年は翌年になってしまうということです。
これを知らずに’Y’を使うと結構ハマることがあります。

Zend_Date の挙動を確認

下記のコードで、実際に挙動を確認してみます。

テストコード(testZendDate.php)

<?php

require_once('/usr/share/php/Zend/Date.php');

// 2012-12-30 を、YYYY形式とyyyy形式で表示
$date = new Zend_Date(strtotime('2012-12-30'), Zend_Date::TIMESTAMP);
echo '2012-12-30 to YYYY-MM-dd='.$date->get('YYYY-MM-dd')."\n";
echo '2012-12-30 to yyyy-MM-dd='.$date->get('yyyy-MM-dd')."\n";
// 2012-12-31 を、YYYY形式とyyyy形式で表示
$date = new Zend_Date(strtotime('2012-12-31'), Zend_Date::TIMESTAMP);
echo '2012-12-31 to YYYY-MM-dd='.$date->get('YYYY-MM-dd')."\n";
echo '2012-12-31 to yyyy-MM-dd='.$date->get('yyyy-MM-dd')."\n";
echo "\n";

// 2013-01-31 を、YYYY形式とyyyy形式で表示
$date = new Zend_Date(strtotime('2013-01-31'), Zend_Date::TIMESTAMP);
echo '2013-01-31 to YYYY-MM-dd='.$date->get('YYYY-MM-dd')."\n";
echo '2013-01-31 to yyyy-MM-dd='.$date->get('yyyy-MM-dd')."\n";
// 2013-01-31 の1か月前 →2012-12-31のはず
$date->add(-1, Zend_Date::MONTH);
echo '2013-01-31 - 1month to YYYY-MM-dd='.$date->get('YYYY-MM-dd')."\n";
echo '2013-01-31 - 1month to yyyy-MM-dd='.$date->get('yyyy-MM-dd')."\n";

// end of file

テストコードの実行

[user@localhost]$ php testZendDate.php
2012-12-30 to YYYY-MM-dd=2012-12-30
2012-12-30 to yyyy-MM-dd=2012-12-30
2012-12-31 to YYYY-MM-dd=2013-12-31
2012-12-31 to yyyy-MM-dd=2012-12-31

2013-01-31 to YYYY-MM-dd=2013-01-31
2013-01-31 to yyyy-MM-dd=2013-01-31
2013-01-31 - 1month to YYYY-MM-dd=2013-12-31
2013-01-31 - 1month to yyyy-MM-dd=2012-12-31
[user@localhost]$

ここで問題になるのは、2012-12-31 です。
2012-12-31は、2013年1月の第1週目ということになるため、
‘YYYY’を使用すると、[2013]が得られます。

実際にこのように文字列として年月日を渡している場合には、
比較的すぐに異常に気付くと思うのですが、
Zend_Dateを使って月の加減算を行っている場合、
特定のタイミングでしか問題が発生しないため、原因調査が少し面倒になります。

上記の例だと、2013-01-31の1か月前を期待しても、2013-12-31になってしまいます。

まとめ

Zend_Dateの日付文字列を取得したい場合は、年の指定には’y’を使うのが無難です。

といっても、’Y’の存在意義が無いわけではなくて、用途としては、
Zend_Dateのマニュアルの説明にもある通り、カレンダー表示などの特定の用途や、
週番号を取得した際に、その週番号が該当する年度を知りたい場合、とかでしょうか。

他にも ‘Y’ には大きな意味があるのかもしれませんが、
単純に年月日を取得したいというだけなら、とにかく’y’を使っておけば間違いは無いでしょう。

 

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

このサイトはスパムを低減するために Akismet を使っています。コメントデータの処理方法の詳細はこちらをご覧ください

Post Navigation