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

发布于 2024-07-19 14:13:50 字数 641 浏览 5 评论 0原文

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

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

我需要使用以下 gawk 函数将其以 perl 格式转换为自纪元以来的毫秒数,在本例中为 124189673005。 我如何在 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;
}

The log4j logs I have contain timestamps in the following format:

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

I need to convert it in perl to millseconds since epoch, which in this case would be 124189673005, using the following gawk function. How do I do it in perl?

I have little or no experience in perl, so appreciate if someone can post an entire script that does this

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;
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

无远思近则忧 2024-07-26 14:13:50

尽管我几乎总是告诉人们为此使用 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;
}

我的代码和你的代码之间的一个重要区别 - 我的 log4jTimeStampToMillis 子例程采用两个参数:

  1. 日志时间戳字符串
  2. ,无论该时间戳是否使用夏令时( 1 表示 true,0 表示 false )

当然,您可以添加代码来检测该时间是否属于夏令时并自动调整,但我试图保持简单。 :)

注意:如果取消注释标记为 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

Though I almost always tell people to go use one of the many excellent modules from the CPAN for this, most of them do have one major drawback - speed. If you're parsing a large number of log files in real-time, that can sometimes be an issue. In those cases, rolling your own can often be a more suitable solution, but there are many pitfalls and nuances that must be considered and handled properly. Hence the preference for using a known-correct, proven, reliable module written by somebody else. :)

However, before I even considered my advice above, I looked at your code and had converted it to perl in my head... therefore, here is a more-or-less direct conversion of your gawk code into perl. I've tried to write it as simply as possible, so as to highlight some of the more delicate parts of dealing with dates and times in perl by hand.

# 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;
}

One important difference between my code and yours - my log4jTimeStampToMillis subroutine takes two parameters:

  1. the log timestamp string
  2. whether or not that timestamp is using daylight savings time ( 1 for true, 0 for false )

Of course, you could just add code to detect if that time falls in DST or not and adjust automatically, but I was trying to keep it simple. :)

NOTE: If you uncomment the line marked DEBUG, make sure to add "use Data::Dumper;" before that line in your program so it will work.

Here's an example of how you could test that subroutine:

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
轻许诺言 2024-07-26 14:13:50

您应该利用出色的 DateTime 包,特别是使用 日期时间::格式::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 参数将服务器的 TZ 传递给 Strptime)。 如果它变得相关的话,它还可以让你免于处理所有事情(我相信它会)。

You should take advantage of the great DateTime package, specifically use 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

This saves you the pain of figuring out DST yourself (although you'll have to pass your server's TZ to Strptime via the time_zone parameter). It also saves you from dealing with leap everything if it becomes relevant (and I'm sure it will).

一花一树开 2024-07-26 14:13:50

还没有使用过它,但您可能想查看 Time ::解析日期

Haven't used it, but you might want to check out Time::ParseDate.

几味少女 2024-07-26 14:13:50
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss,SSS");
Date time = dateFormat.parse(log4jts);
long millis = time.getTime();
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss,SSS");
Date time = dateFormat.parse(log4jts);
long millis = time.getTime();
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文