現在時刻をミリ秒まで得る

いつも調べて書くことになるから、典型的なコードをここに貼っとく。

use Time::HiRes;

sub datetime {
    my ($dt1, $dt2, $dt3);
    {
        my ($sec, $min, $hour, $day, $mon, $year) = localtime;
        $dt1 = sprintf("%04d%02d%02d", 1900 + $year, $mon + 1, $day);
        $dt2 = sprintf("%02d%02d%02d", $hour, $min, $sec);
    }
    {
        my ($sec, $microsec) = Time::HiRes::gettimeofday;
        $dt3 = sprintf("%06d", $microsec);
    }
    return wantarray ? ($dt1, $dt2, $dt3) : "$dt1-$dt2-$dt3";
}

print datetime . "\n";
print join("=", datetime) . "\n";

一秒以内に 2 度実行したとき、2 回目の localtime 実行直後に秒が変化したとすると、実行順序が逆転してしまう。たとえば 1 回目の datetime の結果として 20090122-211545-123123 を得、2 回目は 2009-01-22 21:15:45.999999 に localtime を実行、 2009-01-22 21:15:46.000000 に gettimeofday を実行して結果として 20090122-211545-000000 を得てしまう、ということが起きうる。