1.22.2012

Perl: How to get the month without leading zero in strftime

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

0 件のコメント:

コメントを投稿