日付計算の落とし穴 (その2)
前回の「日付計算の落とし穴」の続きです。
それでは、翌月の末日を取得したい場合にはどうすれば良いか?
という話ですが、以下のようにすれば良いことが分かります。
実行環境:PHP version 5.2.6
[php]
<?php
print("2012/01/29の一か月後→".GetNextMonth_Fixed("2012/01/29")."<br>");
print("2012/01/31の一か月後→".GetNextMonth_Fixed("2012/01/31")."<br>");
print("2012/02/29の一か月後→".GetNextMonth_Fixed("2012/02/29")."<br>");
print("2012/03/31の一か月後→".GetNextMonth_Fixed("2012/03/31")."<br>");
print("2012/04/30の一か月後→".GetNextMonth_Fixed("2012/04/30")."<br>");
print("2012/05/31の一か月後→".GetNextMonth_Fixed("2012/05/31")."<br>");
print("2012/06/30の一か月後→".GetNextMonth_Fixed("2012/06/30")."<br>");
print("2012/07/31の一か月後→".GetNextMonth_Fixed("2012/07/31")."<br>");
print("2012/08/31の一か月後→".GetNextMonth_Fixed("2012/08/31")."<br>");
print("2012/09/30の一か月後→".GetNextMonth_Fixed("2012/09/30")."<br>");
print("2012/10/31の一か月後→".GetNextMonth_Fixed("2012/10/31")."<br>");
print("2012/11/30の一か月後→".GetNextMonth_Fixed("2012/11/30")."<br>");
print("2012/12/31の一か月後→".GetNextMonth_Fixed("2012/12/31")."<br>");
function GetNextMonth_Fixed($pDate){
$wkTimeStamp = strtotime(‘+2 month’,strtotime(date("Ym01",strtotime($pDate))));
$wkTimeStamp = strtotime(‘-1 day’,$wkTimeStamp);
$wkDate = date("Y",$wkTimeStamp)."/".date("m",$wkTimeStamp)."/".date("d",$wkTimeStamp);
return $wkDate;
}
?>
[/php]
一旦、当月の1日に遡る
↓
2カ月後の日付を取得する
↓
1日前の日付を取得する
という手順を踏むことで、翌月の末日を取得することができました。
出力結果:
2012/01/29の一か月後→2012/02/29
2012/01/31の一か月後→2012/02/29
2012/02/29の一か月後→2012/03/31
2012/03/31の一か月後→2012/04/30
2012/04/30の一か月後→2012/05/31
2012/05/31の一か月後→2012/06/30
2012/06/30の一か月後→2012/07/31
2012/07/31の一か月後→2012/08/31
2012/08/31の一か月後→2012/09/30
2012/09/30の一か月後→2012/10/31
2012/10/31の一か月後→2012/11/30
2012/11/30の一か月後→2012/12/31
2012/12/31の一か月後→2013/01/31
今後もPHPについてのTipsがあれば、
備忘録を兼ねて投稿しようと思います。
日付計算の落とし穴
久しぶりにプログラミングについて書きます。
近頃は主にPHPを使って開発する機会が多いのですが、
便利な関数を使っていると思いがけない落とし穴(?)に
遭遇する事があります。
PHPは非常に使い勝手の良い言語で、日付の計算をする場合も
strtotime関数という直感的にイメージしやすい引数を渡せるものがあります。
しかし、その使い勝手の良さ故にバグを誘発することも
時として起こります。
例えば、このstrtotime関数を使用して1か月後の日付を取得したい場合、
引数の1番目に”next month”という様に英単語を渡すと
簡単に取得できるように思えます。
実行環境:PHP version 5.2.6
[php]
<?php
print("2012/01/29の一か月後→".GetNextMonth("2012/01/29")."<br>");
print("2012/01/31の一か月後→".GetNextMonth("2012/01/31")."<br>");
print("2012/02/29の一か月後→".GetNextMonth("2012/02/29")."<br>");
print("2012/03/31の一か月後→".GetNextMonth("2012/03/31")."<br>");
print("2012/04/30の一か月後→".GetNextMonth("2012/04/30")."<br>");
print("2012/05/31の一か月後→".GetNextMonth("2012/05/31")."<br>");
print("2012/06/30の一か月後→".GetNextMonth("2012/06/30")."<br>");
print("2012/07/31の一か月後→".GetNextMonth("2012/07/31")."<br>");
print("2012/08/31の一か月後→".GetNextMonth("2012/08/31")."<br>");
print("2012/09/30の一か月後→".GetNextMonth("2012/09/30")."<br>");
print("2012/10/31の一か月後→".GetNextMonth("2012/10/31")."<br>");
print("2012/11/30の一か月後→".GetNextMonth("2012/11/30")."<br>");
print("2012/12/31の一か月後→".GetNextMonth("2012/12/31")."<br>");
function GetNextMonth($pDate){
$wkTimeStamp = strtotime(‘next month’,strtotime($pDate));
$wkDate = date("Y",$wkTimeStamp)."/".date("m",$wkTimeStamp)."/".date("d",$wkTimeStamp);
return $wkDate;
}
?>
[/php]
しかし、2012年の1,3,5,8,10月の場合、月末の日付を渡すと
翌々月の日付を取得してしまいます。
出力結果:
2012/01/29の一か月後→2012/02/29
2012/01/31の一か月後→2012/03/02
2012/02/29の一か月後→2012/03/29
2012/03/31の一か月後→2012/05/01
2012/04/30の一か月後→2012/05/30
2012/05/31の一か月後→2012/07/01
2012/06/30の一か月後→2012/07/30
2012/07/31の一か月後→2012/08/31
2012/08/31の一か月後→2012/10/01
2012/09/30の一か月後→2012/10/30
2012/10/31の一か月後→2012/12/01
2012/11/30の一か月後→2012/12/30
2012/12/31の一か月後→2013/01/31
恐らくは、
2012/03/31の一か月後
↓
2012/04/31は存在しない
↓
存在する日付まで進める
↓
2012/05/01 という流れをもって
翌々月の日付を取得していると思われますが、直感的に見て
若干違和感を覚える挙動をしています。
既存のプログラミング言語の機能でも、
便利さに目を奪われると思いがけない落とし穴に出くわす事があります。
便利なものこそ、時と場合に応じて本当に有効かどうか確かめる必要がある、
と思いました。
記事投稿日
日 | 月 | 火 | 水 | 木 | 金 | 土 |
---|---|---|---|---|---|---|
« 9月 | ||||||
1 | 2 | 3 | 4 | |||
5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 | 27 | 28 | 29 | 30 | 31 |