【问题标题】:How can I use Perl to do datetime comparisons and calculate deltas?如何使用 Perl 进行日期时间比较和计算增量?
【发布时间】:2009-10-12 15:02:21
【问题描述】:

我从人类可读文本中提取了年、月、日、小时、分钟、秒和毫秒数据(不是时间戳格式,而是类似于“X 开始于 HH:MM:SS.SSS on DD MMM YYYY 并在 DD MMM YYYY 上的 HH:MM:SS.SSSS") 结束,因此对于每个记录的事件,我都有每个值。

但是,我需要将它们转换为某种时间戳,以便对其进行数学运算 - 我想确定事件持续了多长时间(结束时间 - 开始时间)。我希望time 函数可以接受参数,这样我就可以创建两个任意的times,但事实并非如此。

如果可能的话,我想坚持使用核心 Perl 库中可用的功能或我可以添加到项目中的脚本,因为在目标机器上安装 CPAN 模块只会让每个人都头疼,即使它是可以通过安全限制获取模块。

【问题讨论】:

  • 我在一天前看到过一个类似的问题:stackoverflow.com/questions/1365922/…
  • @Kinopiko:您可能在大约一天前看到它,但这个问题是在一个多月前提出的。 (它可能仍然值得一看。只是说......)
  • 我不得不说我不是特别喜欢 Thomas(或他的雇主)对 CPAN 模块的立场,但反对票和票数接近? WTF在这里进行吗?
  • 欢迎来到社交网站。
  • @Manni:同意,尤其是关于近距离投票。这篇文章没有没有有争议。他想要他想要的。投票是个人选择,但完全没有理由结束这个问题。

标签: perl timestamp date


【解决方案1】:

您需要 CPAN 模块 DateTimeHere's介绍。

在 Debian GNU/Linux 或 Ubuntu 系统上,只需运行:

apt-get install libdatetime-perl

安装模块。

【讨论】:

  • 没有。我想避免安装,因为由于安全限制,并非所有这些机器都可以安装随机 CPAN 模块。
  • DateTime 模块并不完全是一个“随机”CPAN 模块。您可能需要重新考虑您的安全政策或截止日期。
  • 说到 CPAN,它有高潮也有低谷。 Perl 黑客自己推荐的模块通常是 Perl 开发人员认为“值得信赖”的软件,相当于经过同行评审的科学报告。因此,虽然您确实应该小心使用 CPAN,但 DateTime不是“随机”CPAN 模块。例如:perlfoundation.org/perl5/…perlfoundation.org/perl5/index.cgi?recommended_datetime_modulesperl.net.au/wiki/Recommended_Perl_Modules#Date.2FTime
  • DateTime 无疑是一个值得努力安装的模块。如果您有很多需要跳过的环节,您可能希望包含一些格式化程序(它可以解析和格式化日期时间数据)。 DateTime::Format::Strptime 是一个很好的开始。
【解决方案2】:

您可以使用Time:Local 完成此操作。它基本上与内置的“localtime”函数相反,因此您可以从标准日期生成时间戳。

【讨论】:

  • 呵呵,我不知道Time::Local 是与Perl 捆绑在一起的!每天学些新东西。 +1
  • Time:Local 看起来不错,但不幸的是它只有第二个粒度。虽然我确实需要研究 sec 是否可以是十进制,因为我可以将 sec 和毫秒组合成 sec.milliseconds。
  • 好吧,您总是可以在“事后”将小数部分添加到时间戳中。我对mktime 的测试也表明了第二个粒度。 :-)
  • 是的,我能做到。无论哪种方式,这看起来都非常有希望。我现在要对此进行试验,如果可行,请回来接受。
  • 在使用Time::Local 与使用mktime 时,需要注意的一点是Time::Local 对年份的解释与mktime 不同。 (尽管月份仍然从 0 开始,即 0 == 一月,11 == 十二月。)恕我直言,Time::Local 中处理的年份“太自动”,但这是个人喜好问题。 :-)
【解决方案3】:

就内置功能而言,这些可能会有所帮助:

  1. POSIX(适用于mktimestrftime
  2. Time::PieceTime::LocalTime::Seconds。这些都是 Perl 5.10 中的标准,但在早期系统中可能默认不可用。

也就是说,时间/日期的计算是复杂的。如果唯一的障碍是安装模块时有些头疼(而不是公司政策禁止它们),我真的建议您查看 CPAN。

编辑:我从您对另一篇帖子的评论中看到公司限制。您应该更新您的原始帖子,因为“头痛”和“安全限制”之间存在很大差异。无论如何,DateTimeDate::Manip 都值得一看。即使你不安装它们,你也可以从阅读它们的源代码中得到很多。

【讨论】:

  • 老实说,我不确定确切的政策是什么,但有人告诉我要避免使用 CPAN 模块,因为它至少会延迟向某些机器推出,并防止推出在最坏的情况下。安全性和所有未经审查的软件。 Perl 及其核心库都经过审查,因此如果需要,更新 Perl 没有问题。
  • 好的,那么一定要看看Time::Piece,它有一个strptime 函数,你可能会用到。
  • @Thomas Owens:这很愚蠢。他们相信你给他们的代码,对吧?是什么阻止您在 CPAN 模块中复制和粘贴代码?你是什​​么把你想要的所有库捆绑到一个 PAR 文件中并包含在你的脚本中?
  • @Thomas Owens:另见perldoc.perl.org/…
【解决方案4】:

如果你只对比较时间感兴趣,

my $ts1 = sprintf( '%4.4d%2.2d%2.2d%2.2d%2.2d%3.3d', 
                   $year1, $month1, $mday1, $hour1, $min1, $sec1, $ms1 );

my $ts2 = sprintf( '%4.4d%2.2d%2.2d%2.2d%2.2d%3.3d', 
                   $year2, $month2, $mday2, $hour2, $min2, $sec2, $ms2 );

使用cmp 就足够了。

要对这些时间进行算术运算,请使用 Time::Local 获取自纪元以来的秒数,然后将 $ms1/1000 添加到该值。

my $time1 = timelocal($sec1, $min1, $hour1, $mday1, $mon1, $year1) + $ms1/1000;

【讨论】:

  • 但是,cmp 不会告诉您在t1t2 之间经过了多少毫秒......
  • 这将教会我不要仅根据标题和第一段发布答案。显然,计算经过的时间不是比较
  • 如果您查看结果,则可以将经过的时间视为比较。例如,负的经过时间意味着某件事发生在其他事情之前。
  • @Thomas Owens 和 cmp 将返回 -1 如果 $ts1 指的是 $ts2 之前的时间。
  • 对标题进行了编辑,以使 OP 想要的不仅仅是 风格的比较。
【解决方案5】:

您可以使用POSIX::mktime 将分解时间转换为时间戳。请注意,月份是从 0 开始的,而年份是从 1900 开始的,因此请进行相应调整。 :-)

use POSIX qw(mktime);
$timestamp = mktime($sec, $min, $hour, $day, $month - 1, $year - 1900);

【讨论】:

  • 虽然我的目标平台是Solaris,但是这个方法在Windows上也可以吗?尽管我认为现在是开始使用 Solaris 测试和调试这些脚本的最佳时机。
  • mktime 是一个标准的 C 函数,所以它应该也可以在 Windows 上使用。
  • 好的。这就是我的想法,但是当我看到 POSIX 时,我在处理 Windows 时会感到担心。虽然(反正按照要求),我不需要在windows机器上运行。
猜你喜欢
  • 2014-01-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-11-14
  • 1970-01-01
相关资源
最近更新 更多