内容

名称

Time::Local - 有效计算本地时间和 GMT 时间

版本

版本 1.30

语法

use Time::Local qw( timelocal_posix timegm_posix );

my $time = timelocal_posix( $sec, $min, $hour, $mday, $mon, $year );
my $time = timegm_posix( $sec, $min, $hour, $mday, $mon, $year );

说明

此模块提供与内置 perl 函数 localtime()gmtime() 相反的函数。它们接受一个日期作为六个元素的数组,并返回自系统纪元(例如,Unix 上的 1970 年 1 月 1 日午夜 GMT)以来的相应 time(2) 值(以秒为单位)。此值可以为正或负,但 POSIX 只要求支持正值,因此在某些操作系统上,系统纪元之前的日期可能无法使用。

值得特别注意的是所提供值的预期范围。月份中的天数的值是实际天数(即 1..31),而月份是自 1 月以来的月份数(0..11)。这与从 localtime()gmtime() 返回的值一致。

函数

timelocal_posix()timegm_posix()

这些函数是 Perl 内置的 localtimegmtime 函数的完全逆函数。这意味着调用 timelocal_posix( localtime($value) ) 将始终为您提供您开始时的相同 $valuetimegm_posix( gmtime($value) ) 也适用。

唯一的例外是当 localtime() 返回的值由于 DST 更改而表示模糊的本地时间时。有关更多详细信息,请参阅下面的文档。

这些函数期望年份值是自 1900 年以来的年数,这是 localtime()gmtime() 内置函数返回的值。

它们默认对输入 $sec$min$hour$mday$mon 值执行范围检查,如果给定的值超出允许范围,它们将发出错误(使用 Carp::croak())。

虽然将其设为默认行为会很好,但这几乎肯定会破坏很多代码,因此您必须显式导入这些函数并使用它们,而不是默认的 timelocal()timegm()

强烈建议您在使用此模块的任何新代码中使用这些函数。这几乎肯定会使您的代码的行为不那么令人惊讶。

timelocal_modern()timegm_modern()

Time::Local 首次编写时,通常的做法是用两位数字值表示年份,例如 99 表示 19991 表示 2001。这引起了各种问题(如果您很年轻,请谷歌搜索“Y2K 问题”),开发人员最终意识到这是一个可怕的想法。

当给定小于 1000 的年份值时,timelocal()timegm() 的默认导出会进行复杂的计算。在许多情况下,这会导致令人惊讶的结果。有关详细信息,请参阅 “年份值解释”

time*_modern() 函数不会执行此年份转换,而是直接采用提供的年份值。

它们默认对输入 $sec$min$hour$mday$mon 值执行范围检查,如果给定的值超出允许范围,它们将发出错误(使用 Carp::croak())。

timelocal()timegm()

此模块默认导出两个函数,timelocal()timegm()

它们默认对输入 $sec$min$hour$mday$mon 值执行范围检查,如果给定的值超出允许范围,它们将发出错误(使用 Carp::croak())。

警告:这些函数及其 nocheck 变体使用的年份值解释几乎肯定会导致代码中的错误,如果不是现在,那么将来也会。强烈建议不要在新的代码中使用它们,并且如果可能,你应该将旧代码转换为使用 *_posix*_modern 函数。

timelocal_nocheck()timegm_nocheck()

如果你使用已知有效的数据,则可以使用“nocheck”变体,timelocal_nocheck()timegm_nocheck()。这些变体必须显式导入。

如果你提供无效的数据(月份 27,秒数 1,000),结果将不可预测(所以不要这样做)。

请注意,我的基准测试表明,这比已检查的版本仅快 3%,因此除非调用 Time::Local 是应用程序中最热门的地方,否则使用这些 nocheck 变体不太可能对应用程序产生很大影响。

年份值解释

这不适用于 *_posix*_modern 函数。如果你想确保代码老化时行为一致,请使用那些导出。

严格来说,年份应以与 localtime() 一致的形式指定,即距 1900 年的偏移量。然而,为了让人们更容易理解年份的解释,因为人们更习惯于将年份视为两位数或四位数的值,因此遵循以下约定

上述方案允许解释广泛的日期,特别是如果使用 4 位数年份。但这还意味着随着时间的推移,代码的行为会发生变化,因为滚动“当前世纪”每年都会改变。

time_t 的限制

在早于 5.12.0 的 perl 版本中,可实际处理的日期范围取决于给定平台上 time_t(通常为有符号整数)的大小。目前,对于大多数系统而言,此大小为 32 位,产生的近似范围为 1901 年 12 月至 2038 年 1 月。

如果给定超出支持范围的日期,timelocal()timegm() 都会发出 croak。

从 5.12.0 版本开始,perl 已停止使用其所运行操作系统的 time 实现。相反,它拥有自己的这些例程的实现,安全范围至少为 +/- 2**52(约 1.42 亿年)

不明确的本地时间 (DST)

由于 DST 更改,在同一天的不同 GMT 时间会出现相同的本地时间,这在许多时区中很常见。例如,在“欧洲/巴黎”时区中,2001-10-28 02:30:00 的本地时间可以表示 2001-10-28 00:30:00 GMT, 2001-10-28 01:30:00 GMT。

当给定不明确的本地时间时,timelocal() 函数将始终返回两个可能的 GMT 时间中较早的时间的纪元。

不存在的本地时间 (DST)

当 DST 更改导致区域时钟向前跳过一小时时,将有一小时不存在的本地时间。同样,对于“欧洲/巴黎”时区,区域时钟从 2001-03-25 01:59:59 跳到 2001-03-25 03:00:00。

如果 timelocal() 函数给定不存在的本地时间,它将仅返回一小时后的时间的纪元值。

负纪元值

在 perl 版本 5.12.0 及更高版本中,完全支持负纪元值。

在较早版本的 perl 中,POSIX 标准未正式支持的负纪元 (time_t) 值已知在某些系统上无法使用。其中包括 MacOS(pre-OSX)和 Win32。

在支持负纪元值的系统上,此模块应该能够处理纪元开始之前的日期,直到系统的 time_t 的最小值。

实现

这些例程非常高效,但始终保证与 localtime()gmtime() 一致。我们通过缓存之前见过的任何月份的开始时间来管理此操作。如果我们知道该月份的开始时间,我们始终可以计算该月份内的任何时间。开始时间是使用数学公式计算的。这与对 gmtime() 执行多次调用的其他算法不同。

timelocal() 函数使用相同的缓存实现。我们仅假设要转换格林尼治时间,然后在完成时根据时区和夏令时参数进行调整。请注意,会针对每个日期评估时区,因为国家/地区偶尔会更改其官方时区。假设 localtime() 会更正这些更改,则此例程也将正确无误。

荣誉作者

此模块基于 Perl 4 库 timelocal.pl,该库包含在 Perl 4.036 中,很可能由 Tom Christiansen 编写。

当前版本由 Graham Barr 编写。

错误

解释两位数年份的整个方案可以被视为一个错误。

可以在 https://github.com/houseabsolute/Time-Local/issues 提交错误。

此发行版的用户可以使用邮件列表 mailto:[email protected]

我通常在 irc://irc.perl.org 上以“autarch”的身份活跃于 IRC。

源代码

Time-Local 的源代码存储库位于 https://github.com/houseabsolute/Time-Local

作者

Dave Rolsky <[email protected]>

贡献者

版权和许可证

此软件的版权归 Graham Barr 和 Dave Rolsky 所有 (c) 1997 - 2020。

这是一个免费软件;你可以根据 Perl 5 编程语言系统本身的相同条款重新分发或修改它。

可以在此发行版中包含的 LICENSE 文件中找到许可证的全文。