Perl: strftime によるゼロ埋めなしの「月」の取得
strftime を実行する際、フォーマット指定子「%m」利用すると、結果が1桁の場合ゼロ埋めが行われる。(01, 02, 03 … 12)
一部の環境では'%-m' (UNIX)や '%#m' (Windows) を指定することで、ゼロ埋めなしの月(1, 2, 3, … 12)を取得できるが、
汎用的に変換を行うには、以下のようなコードを書く必要がある。
コード
・拡張版strftime
制約: '%-m' の部分が最初に評価されるため、'%%-m' のようなフォーマットが指定された場合は
期待(文字列としての % – m の3文字を出力したい)と異なる結果となる可能性がある。
use POSIX qw( strftime );
sub strftime_ext {
my ($fmt, $sec, $min, $hour, $mday, $mon, $year, $wday, $yday, $isdst)
= @_;
my $m = $mon+ 1;
$fmt =~ s/ %-m /$m/gxms;
return strftime($fmt, $sec, $min, $hour, $mday, $mon, $year, $wday, $yday,
$isdst);
}
・呼び出し側
print strftime('%Y-%m-%d', localtime ), "\n";
print strftime('%Y-%-m-%d', localtime ), "\n";
print strftime_ext('%Y-%m-%d', localtime ), "\n";
print strftime_ext('%Y-%-m-%d', localtime ), "\n";
・出力結果(例)
2012-01-22
2012-%-m-22
2012-01-22
2012-1-22
所要時間の測定
他の方法も試し、所要時間を測ってみた。
測定には、Time::HiRes モジュールの gettimeofday および tv_interval を使えばよい。
・拡張版strftime (別の実装)
sub strftime_ext2 {
my ($fmt, $sec, $min, $hour, $mday, $mon, $year, $wday, $yday, $isdst)
= @_;
$fmt =~ s{ %-m }{ $mon + 1 }gexms;
return strftime($fmt, $sec, $min, $hour, $mday, $mon, $year, $wday, $yday,
$isdst);
}
sub strftime_ext3 {
my ($fmt, @args) = @_;
my $m = $args[4] + 1;
$fmt =~ s/ %-m /$m/gxms;
return strftime($fmt, @args);
}
sub strftime_ext4 {
my ($fmt, @args) = @_;
$fmt =~ s{ %-m }{ $args[4] + 1 }gexms;
return strftime($fmt, @args);
}
・測定用コード
use Time::HiRes qw( gettimeofday tv_interval );
sub test {
my ($fnc_ref) = @_;
my @time = localtime;
my $start = [gettimeofday];
for my $i (1..100000) {
$fnc_ref->('%-m', @time );
}
print tv_interval($start), "\n";
}
test \&strftime_ext;
test \&strftime_ext2;
test \&strftime_ext3;
test \&strftime_ext4;
・結果
0.34079
0.519459
0.381004
0.561233
以下の順で性能が良いことがわかった。
strftime_ext > strftime_ext3 > strftime_ext2 > strftime_ext4
参考:
http://jabnz.blog69.fc2.com/blog-entry-728.html