代码之家  ›  专栏  ›  技术社区  ›  Miserable Variable

如何在Perl中将log4j时间戳转换为毫秒?

  •  2
  • Miserable Variable  · 技术社区  · 15 年前

    我拥有的log4j日志包含以下格式的时间戳:

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

    124189673005 ,使用以下gawk函数。如何在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 回复  |  直到 15 年前
        1
  •  2
  •   Hercynium    15 年前

    尽管我几乎总是告诉人们使用CPAN中的许多优秀模块中的一个来实现这一点,但大多数模块都有一个主要缺点——速度。如果要实时解析大量日志文件,有时可能会出现问题。在这些情况下,您自己滚动通常是一个更合适的解决方案,但有许多陷阱和细微差别必须加以考虑和妥善处理。因此,更倾向于使用他人编写的已知正确、经验证、可靠的模块。:)

    然而,在我考虑上述建议之前,我查看了您的代码,并在脑海中将其转换为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. 日志时间戳字符串

    注意:如果取消注释标记为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
    
        2
  •  2
  •   Ryley    14 年前

    你应该好好利用这个机会 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的麻烦(尽管您必须通过 time_zone 参数)。如果它变得相关(我相信它会),它还可以避免您处理leap everything。

        3
  •  1
  •   Anon    15 年前
        4
  •  0
  •   Sergey Glotov Nitesh Khosla    12 年前
    SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss,SSS");
    Date time = dateFormat.parse(log4jts);
    long millis = time.getTime();