PHPバッドノウハウ・年と月のリストを得る

PHPバッドノウハウ・年と月のリストを得る

目的

業務で、年と月を組み合わせたリストを取得しようと考えていました。検索のためのチェックボックスに使うためです。ほしい出力は以下のようなものです。

2007-03
2007-02
2007-01
2006-12
2006-11
2006-10
2006-09
2006-08
2006-07
2006-06
2006-05
2006-04

strtotimeの使い方

strtotimeという関数でループを回せば簡単に目的を達成できそうです。

strtotime関数は日付を表す文字列を渡すとタイムスタンプを取得できる便利な関数です。それと同時に日付/時刻の加減算もできます。

たとえば、現在が2007年3月5日だとします。

一ヶ月前の「2007-02」というラベルを得たいとき、以下のコードで取得します。本来ならtime()を使いますが、今日は3/5日ではありませんので、$nowに3/5日を設定して代用します。(以下phpタグ省略)

$now = strtotime("2007-03-05");
echo date("Y-m", strtotime("-1 month", $now));
出力
2007-02

タイムスタンプをstrtotime("-1 month", $now)しながら年月のリストを生成しようと思いました。

strtotimeの問題

しかしこの関数を素直に使おうとすると、穴があります。

2007年3月31日の1ヶ月前、という計算をしたときの出力は自分の直感に反したものでした。

$now = strtotime("2007-03-31");
echo date("Y-m-d", strtotime("-1 month", $now));
出力
2007-03-03

これではstrtotimeを使って1ヶ月ずつずらしながらリストを取得することはできません。以下のようなリストを取得してしまう恐れがあります。

2007-03
2007-03
2007-02
2007-01
2006-12

strtotimeの挙動

自分の期待するところでは2007/02/28が出力されてほしいところです。少し調べてわかったことは、2007-03-31の一ヶ月前を求めると、2007-02-31となって、自動的に3月の日付に変換されてしまうということです。それは以下のコードで確かめることができます。

echo date("Y-m-d", strtotime("2007/02/31"));
出力
2007-03-03

もう少し調べたところ、全ての月に存在する28以下の日を指定すると、ちゃんと、1ヶ月前のタイムスタンプが取得できることがわかりました。

$now = strtotime("2007-03-31");
$current_month = date("Y-m", $now);
$month_firstday = strtotime($current_month . "-1");

//ループ用に
$firstday = $month_firstday;
for ($i=0; $i<12; $i++){
    echo date("Y-m", $firstday)."
\n"; $firstday = strtotime("-1 month", $firstday); }
出力
2007-03
2007-02
2007-01
2006-12
2006-11
2006-10
2006-09
2006-08
2006-07
2006-06
2006-05
2006-04

まとめ

無事年と月の形式のリストを得ることができました。出力のときに日の部分をstrtotime関数で現在の月(例:"2007-03")に最初の日("-1")を文字列結合させてタイムスタンプを取得していきます。

やりかたがスマートじゃありませんが、今日はこんなところで。

  • このエントリーをはてなブックマークに追加

この記事を読んだ人にオススメ