読者です 読者をやめる 読者になる 読者になる

weblog of key_amb

主にIT関連の技術メモ

DateTime::Format::Strptime にパッチを送った話 #Perl

Perl CPAN develop

CPAN モジュールの DateTime::Format::Strptime は DateTime と同じ Dave Rolsky さんが開発しているもので、日付時刻を含む文字列のパースによく使われているのではないかと思います。

このモジュールの挙動が v1.58 から変わっていました。

#!perl
use feature qw(say);
use DateTime::Format::Strptime;
my $strp = DateTime::Format::Strptime->new(
    pattern => '%Y%m%d',
);
for my $str (qw/20160330 access_log.20160330/) {
    my $dt = $strp->parse_datetime($str);
    say "$str => undef " and next unless $dt;
    say "$str => " . $strp->format_datetime($dt);
}

これを実行すると、下のようになりました。

# v1.57 以前
20160330 => 20160330
access_log.20160330 => 20160330

# v1.58 以降
20160330 => 20160330
access_log.20160330 => undef 

そう。
日付時刻を表す文字列の前に、別の文字列があるようなものはパースできなくなっていたのです。

Changes や差分を見ていたところ、どうやら v1.57 〜 v1.60 の間に互換性を崩す大幅な変更があったようです。
ので、仕様変更かなーと同僚の間で話していたのですが、作者に聞くのが確実だろうと思ったので、GitHub の Issued で聞いてみました。

f:id:key_amb:20160401074307p:plain

なんとバグだったようです。

せっかくなので、直せるかどうか手元でやってみることにしました。

GitHub で fork して、まずはテストを書いて再現させてみました。 テストを書いたところ、どうやら 20160330.log のように、後ろに文字列があるケースはパースできるということに気がつきました。

…で、試行錯誤した結果、正規表現を数文字変えれば問題の挙動が直り、既存のテストも通るということがわかりました。
ので、Pull Request を送りました。

取り込まれる過程で少し修正されていましたが、めでたく修正版の v1.67 がリリースされました。

めでたしめでたし。