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
0 件のコメント:
コメントを投稿