2

私が持っているlog4jログには、次の形式のタイムスタンプが含まれています。

2009-05-10 00:48:41,905

次のgawk関数を使用して、エポック(この場合は124189673005)以降、perlでミル秒に変換する必要があります。Perlでそれを行うにはどうすればよいですか?

私はperlの経験がほとんどないかまったくないので、誰かがこれを行うスクリプト全体を投稿できるかどうかを感謝します

function log4jTimeStampToMillis(log4jts) {
    # log4jts is of the form 2009-03-02 20:04:13,474
    # extract milliseconds that is after the command
    split(log4jts, tsparts, ",");
    millis = tsparts[2];

    # remove - : from tsstr
    tsstr = tsparts[1];
    gsub("[-:]", " ", tsstr);
    seconds = mktime(tsstr);
    print log4jts;
    return seconds * 1000 + millis;
}
4

4 に答える 4

2

私はほとんどの場合、これにCPANの多くの優れたモジュールの1つを使用するように人々に言いますが、それらのほとんどには1つの大きな欠点があります。それは速度です。多数のログファイルをリアルタイムで解析している場合、それが問題になることがあります。そのような場合、自分でローリングする方が適切な解決策になることがよくありますが、適切に検討して処理する必要のある落とし穴やニュアンスがたくさんあります。したがって、他の誰かによって書かれた、既知の正しい、証明された、信頼できるモジュールを使用することを好みます。:)

しかし、上記のアドバイスを検討する前に、私はあなたのコードを見て、頭の中でそれをperlに変換しました...したがって、ここにあなたのgawkコードをperlに多かれ少なかれ直接変換します。私は、perlで日付と時刻を手作業で処理する際のより繊細な部分のいくつかを強調するために、できるだけ単純にそれを書くように努めました。

# import the mktime function from the (standard) POSIX module
use POSIX qw( mktime );

sub log4jTimeStampToMillis {
    my ($log4jts, $dst) = @_;

    # extract the millisecond field
    my ($tsstr, $millis) = split( ',', $log4jts );

    # extract values to pass to mktime()
    my @mktime_args = reverse split( '[-: ]', $tsstr );

    # munge values for posix compatibility (ugh)
    $mktime_args[3] -= 1;
    $mktime_args[4] -= 1;
    $mktime_args[5] -= 1900;
    # print Dumper \@mktime_args; ## DEBUG

    # convert, make sure to account for daylight savings
    my $seconds = mktime( @mktime_args, 0, 0, $dst );

    # return that time as milliseconds since the epoch
    return $seconds * 1000 + $millis;
}

私のコードとあなたのコードの重要な違いの1つは、log4jTimeStampToMillisサブルーチンが2つのパラメーターを受け取ることです。

  1. ログのタイムスタンプ文字列
  2. そのタイムスタンプが夏時間を使用しているかどうか(trueの場合は1、falseの場合は0)

もちろん、その時間がDSTに該当するかどうかを検出して自動的に調整するコードを追加することもできますが、私はそれを単純に保つように努めました。:)

注:DEBUGとマークされた行のコメントを解除する場合は、必ず「use Data::Dumper;」を追加してください。プログラムのその行の前にあるので、動作します。

そのサブルーチンをテストする方法の例を次に示します。

my $milliseconds = log4jTimeStampToMillis( "2009-05-10 00:48:41,905", 1 );    
my $seconds = int( $milliseconds / 1000 );
my $local = scalar localtime( $seconds );

print "ms:    $milliseconds\n"; # ms:    1241844521905
print "sec:   $seconds\n";      # sec:   1241844521
print "local: $local\n";        # local: Sat May  9 00:48:41 2009
于 2009-05-10T23:53:43.127 に答える
2

優れたDateTimeパッケージを利用する必要があります。具体的には、DateTime :: Format :: Strptime:を使用してください。

use DateTime;
use DateTime::Format::Strptime;

sub log4jTimeStampToMillis {
    my $log4jts=shift(@_);

    #see package docs for how the pattern parameter works
    my $formatter= new DateTime::Format::Strptime(pattern => '%Y-%m-%d %T,%3N');
    my $dayObj = $formatter->parse_datetime($log4jts);

    return $dayObj->epoch()*1000+$dayObj->millisecond();
}

print log4jTimeStampToMillis('2009-05-10 10:48:41,905')."\n";
#prints my local version of the TS: 1241952521905

これにより、DSTを自分で理解する手間が省けます(ただし、パラメーターを介してサーバーのTZをStrptimeに渡す必要がありtime_zoneます)。それが関連するようになった場合、それはまたあなたがすべてを飛躍させることに対処することからあなたを救います(そして私はそれがそうなると確信しています)。

于 2010-11-24T00:38:29.323 に答える
1

まだ使用していませんが、Time::ParseDateを確認することをお勧めします。

于 2009-05-10T16:18:57.963 に答える
0
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss,SSS");
Date time = dateFormat.parse(log4jts);
long millis = time.getTime();
于 2010-11-24T00:05:10.350 に答える