うまいぼうぶろぐ

linuxとhttpdとperlのメモ

perl - Time::Piece で日付を計算

perl 5.8には時刻を扱う標準モジュールがなくて、たいていCPANのDateTimeを使ってたんですが、DateTimeは巨大?で依存モジュールも多いので、ちょっとした日付計算には大げさだなーと思っていました。

すると Time::Piece という軽量なモジュールがあることを知りました。5.10 では標準モジュールに加わったということもあるので、普段はこれを使えばいいかな。

Time::Piece

use すると標準のlocaltime を上書きする。詳細な使い方は↑のurlとperldocで。

use Time::Piece;
my $t = localtime;
print $t->ymd();

Time::Piece で前月の計算

Time::Piece に関わらず、日付を計算するとき全般の話ですが。前月を計算するのって簡単なようで少し手間。何も考えずに$mon - 1 とすると、年をまたぐときにおかしくなるし、$day - 30 (-86400 * 30) でも 月末/月初 の場合におかしくなる(5/31 => 5/1, 3/1 => 1/30 (非うるう年))。

で、hiroseさんのdateコマンドでの前月取得のエントリを思い出したので、同じようなことをTime::Pieceでやってみることに。

use Time::Piece;

## 今日が2011/03/01 だとする	
## my $t = localtime;

my $t = Time::Piece->strptime('2011-03-01', '%Y-%m-%d');
print "today: " . $t->ymd . "\n";
	
## 例えば単純に30日前で計算すると。。。
my $wrong_prev = localtime($t->epoch - 86400 * 30);
print "wrong prev month: " . $wrong_prev->ymd . " oops!! \n";
	
## 日にちの部分を15に置き換えてから、30日前で計算
my $prev = Time::Piece->strptime($t->strftime('%Y-%m-15'), '%Y-%m-%d') - 86400 * 30;
print "prev month: " . $prev->ymd . "\n";
  • 実行結果
today: 2011-03-01
wrong prev month: 2011-01-30 oops!!
prev month: 2011-02-13

という感じで無事 2月になっているので あとは $prev->mon とすれば"2" が取得できる。