我的日志文件的时间戳如下:
Fri Nov 30 10:19:35:152.92 PST 2012
Fri Nov 30 10:19:35:228.8 PST 2012
or even:
Thu Nov 29 14:20:58:3.44 PST 2012
Fri Nov 30 10:27:50:742 PST 2012
我是Perl的新手,但这是每个人都使用的,所以我试图快速学习它(刚刚开始这项工作)。我需要能够比较时间戳(我正在合并时间可能重叠的日志文件,并且需要在结果文件中连续所有时间戳)。 这是子程序,我将时间提取并格式化为可以比较的字符串:
my %months = ( 'Jan'=>1, 'Feb'=>2, 'Mar'=>3, 'Apr'=>4, 'May'=>5, 'Jun'=>6, 'Jul'=>7,
'Aug'=>8, 'Sep'=>9, 'Oct'=>10, 'Nov'=>11, 'Dec'=>12);
sub to_comparable {
my $date = shift;
my ($mmm, $d, $H, $M, $S, $mils, $fra, $tz, $Y) = $date =~
m{^<\w{3} (\w{3}) (\d{1,2}) (\d{1,2}):(\d{1,2}):(\d{1,2}):(\d{1,3})[.]{0,1}(\d{0,2}) (\w{3}) (\d{4})>}
or return undef;
if ($mils eq "") { $mils = 0; }
if ($fra eq "") { $fra = 0; }
my $m = $months{$mmm};
return sprintf('%04d%02d%02d%02d%02d%02d%03d%02d',$Y,$m,$d,$H,$M,$S,$mils,$fra);
}
只要时间戳都来自同一时区,这样就可以正常工作。但是,我想确保它们对于与标准时间和夏令时(或者我从其他时区获取日志)的更改重叠的日志正常工作。我想也许DateTime包可以做到这一点,但我很困惑如何使用时区来获得可比较的时间。我可以创建一个日期/时间对象,除了用于时区的内容。 在我的测试中,我在映射月份后添加了以下内容:
my $ns = sprintf('%03d.%02d',$mils,$fra);
$ns *= 1000;
my $dt = DateTime->new(
year => $Y,
month => $m,
day => $d,
hour => $H,
minute => $M,
second => $S,
nanosecond => $ns,
time_zone => "$tz",
);
这会导致错误“无效的偏移:PST”。 我发现了这个说明:“强烈建议您不要将这些名称用于显示以外的任何名称。这些名称不是官方的,其中许多只是Olson数据库维护者的发明。而且,这些名称不是例如,-0500和+ 1000 / + 1100都有一个“EST”。“ 和其他地方一样:“时区的短名称并不是唯一的,所以任何从这个名称确定实际时区的尝试都需要猜测。请改用长名称。”
我无法控制我给出的时区显示,所以我现在不知道该怎么做。如果我使用“PST8PDT”或“America / Los_Angeles”,我如何指出给定时间是标准时间还是夏令时?并且是否会将美国时区转换为DateTime接受的时区?有人可以帮我解决这个问题吗?我看似微不足道的合并日志文件的项目正在进行,我的老板认为我是个白痴。 : - (
答案 0 :(得分:7)
遗憾的是,如此多的日志文件使用如此糟糕的时间戳格式选择。我推荐RFC 3339(也是ISO 8601格式之一)。
无论如何,关于这个问题。
创建映射以将源系统的标识符定义转换为构造函数的time_zone
参数接受的标准名称或偏移量。
my %time_zones = (
EST => '-0500',
PST => '-0800',
PDT => '-0700',
...
);
然后使用time_zone
参数传递偏移量。
$ perl -MDateTime -E'say
DateTime->new(
year => 2012, month => 11, day => 4,
hour => 1, minute => 16, second => 0,
time_zone => "-0800",
)->epoch;
'
1352020560
$ perl -MDateTime -E'say
DateTime->new(
year => 2012, month => 11, day => 4,
hour => 1, minute => 16, second => 0,
time_zone => "-0700",
)->epoch;
'
1352016960
$ perl -E'say 1352020560 - 1352016960'
3600