如何在 Perl 中将纪元时间转换为正常时间?

Posted

技术标签:

【中文标题】如何在 Perl 中将纪元时间转换为正常时间?【英文标题】:How do I convert epoch time to normal time in Perl? 【发布时间】:2011-03-08 11:00:03 【问题描述】:

我正在尝试编写一个解析日志的 Perl 脚本,其中每一行的第二个值是日期。该脚本接受三个参数:输入日志文件、开始时间和结束时间。开始时间和结束时间用于解析出介于这两个时间之间的每一行的某个值。但是为了正确运行它,我将开始和结束时间转换为纪元时间。我遇到的问题是将循环“i”值转换回正常时间以与日志文件进行比较。运行localtime($i) 后,我打印了值,只看到打印的参考值而不是实际值。

这是我目前拥有的脚本(正在进行中):

#!/usr/bin/perl
use strict;
use warnings;
use Time::Local;
use Time::localtime;
use File::stat;

my $sec = 0;
my $min = 0;
my $hour = 0;
my $mday = 0;
my $mon = 0;
my $year = 0;
my $wday = 0;
my $yday = 0;
my $isdst = 0;

##########################
# Get the engine log date
##########################
my $date = `grep -m 1 'Metric' "$ARGV[0]" | awk 'print \$2'`;
($year,$mon,$mday) = split('-', $date);
$mon--;

#########################################
# Calculate the start and end epoch time
#########################################
($hour,$min,$sec) = split(':', $ARGV[1]);
my $startTime = timelocal($sec,$min,$hour,$mday,$mon,$year);
($hour,$min,$sec) = split(':', $ARGV[2]);
my $endTime = timelocal($sec,$min,$hour,$mday,$mon,$year);


my $theTime = 0;
for (my $i = $startTime; $i <= $endTime + 29; $i++) 
        #print "$startTime   $i \n";

        $theTime = localtime($i);

        #my $DBInstance0 = `grep "$hour:$min:$sec" "$ARGV[0]"`;# | grep 'DBInstance-0' | awk 'print \$9'`;
        #print "$DBInstance0\n";
        print "$theTime\n";

print "$startTime   $endTime \n";

输出如下:

Time::tm=ARRAY(0x8cbbd40)
Time::tm=ARRAY(0x8cbc1a0)
Time::tm=ARRAY(0x8cbbe80)
Time::tm=ARRAY(0x8cbc190)
Time::tm=ARRAY(0x8bbb170)
Time::tm=ARRAY(0x8cbc180)
Time::tm=ARRAY(0x8cbbf30)
Time::tm=ARRAY(0x8cbc170)
Time::tm=ARRAY(0x8cbc210)
Time::tm=ARRAY(0x8cbc160)
1275760356   1275760773

我只能访问核心 Perl 模块,无法安装任何其他模块。

【问题讨论】:

@Matt:在这种情况下,我建议将您的简历提交至careers.***.com。 @Ether,@Peter - 有些人为比初创公司更大的公司工作,在这些公司中,使用未经测试的代码所带来的收益远大于使用它的风险价值。当您因代码错误而损失数十亿美元时,您的观点会变得更加繁文缛节。因此,在此基础上对某人粗鲁不仅不会帮助您赢得 Perl 转换,而且是完全不公平的。 @Ether - 我不这么认为。我假设“只是使用它并稍后请求宽恕”可能在一家小公司是一种可以接受的态度 - 出于好或坏的原因 - 但通常,出于充分的理由,不尽管个人开发人员对该主题的看法以及我个人喜欢牛仔的方式,但在一家大公司中可以接受 此外,在 SO Perl 标签上经常看到的“找另一份工作”的下意识反应与基本恕我直言相去甚远。能够做任何你觉得需要和该死的后果并不总是人们想为特定公司工作的首要原因,很少是主要的。 让我解释一下为什么我不能使用未经测试的代码。我为世界上最大的交易所之一工作。如果我使用未经测试的模块并导致某人损失数百万或数十亿美元,则无法原谅。我们练习这种“偏执狂”,因为可能会失去很多东西,并可能使许多国家陷入萧条。 DVK 是正确的,不是每个人都可以“只是使用它,以后再请求原谅”。而且我热爱我的工作,即使我只能使用核心 Perl 模块。在测试模块之前,这确实让我的工作变得更加困难,但这对我来说很好。 【参考方案1】:

您可以使用ctime,具体取决于您对“正常时间”的定义:

示例代码:

use Time::Local; 
use Time::localtime; 
my $time=timelocal(1,2,3,24,6,2010);
print "$time\n"; 
$theTime = ctime($time); 
print "$theTime\n";

结果:

1279954921
Sat Jul 24 03:02:01 2010

另外,您不需要使用 Time::Localtime(which is why you get Time::tm 代替 Perl 内部 localtime 中的标准数组/字符串):

use Time::Local; 
my $time=timelocal(1,2,3,24,6,2010); 
print "$time\n"; 
$theTime = localtime($time); 
print "$theTime\n";

1279954921
Sat Jul 24 03:02:01 2010

【讨论】:

【参考方案2】:

别忘了从年份中减去 1900!

请记住,在标量上下文中,localtimegmtime 返回一个ctime 格式的字符串,因此您可以按如下方式使用它。如果这不合适,您可能需要使用 POSIX 模块中的 strftime

#! /usr/bin/perl

use warnings;
use strict;

use Time::Local;

my $start = "01:02:03";
my $end   = "01:02:05";
my $date  = "2010-02-10";

my($year,$mon,$mday) = split /-/, $date;
$mon--;
$year -= 1900;

my($startTime,$endTime) =
  map  my($hour,$min,$sec) = split /:/;
        timelocal $sec,$min,$hour,$mday,$mon,$year 
  $start, $end;

for (my $i = $startTime; $i <= $endTime + 29; $i++) 
  print scalar localtime($i), "\n";


print "$startTime   $endTime \n";

输出的尾部:

2010 年 2 月 10 日星期三 01:02:26
2010 年 2 月 10 日星期三 01:02:27
2010 年 2 月 10 日星期三 01:02:28
2010 年 2 月 10 日星期三 01:02:29
2010 年 2 月 10 日星期三 01:02:30
2010 年 2 月 10 日星期三 01:02:31
2010 年 2 月 10 日星期三 01:02:32
2010 年 2 月 10 日星期三 01:02:33
2010 年 2 月 10 日星期三 01:02:34
1265785323 1265785325

【讨论】:

以上是关于如何在 Perl 中将纪元时间转换为正常时间?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Perl 中将 dd/mm/yyyy 转换为纪元时间?

在 Perl 中将纪元时间转换为标准约定的问题

在 Windows 上的 perl 中将纪元转换为本地时间

在perl中将日期转换为纪元的最佳方法[关闭]

在 Oracle SQL 中将纪元时间转换为正常的日期时间格式

如何在 C 语言 (Linux) 中将 NTP 时间转换为 Unix 纪元时间