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 内置的 localtime
和 gmtime
函数的完全逆函数。这意味着调用 timelocal_posix( localtime($value) )
将始终为您提供您开始时的相同 $value
。timegm_posix( gmtime($value) )
也适用。
唯一的例外是当 localtime()
返回的值由于 DST 更改而表示模糊的本地时间时。有关更多详细信息,请参阅下面的文档。
这些函数期望年份值是自 1900 年以来的年数,这是 localtime()
和 gmtime()
内置函数返回的值。
它们默认对输入 $sec
、$min
、$hour
、$mday
和 $mon
值执行范围检查,如果给定的值超出允许范围,它们将发出错误(使用 Carp::croak()
)。
虽然将其设为默认行为会很好,但这几乎肯定会破坏很多代码,因此您必须显式导入这些函数并使用它们,而不是默认的 timelocal()
和 timegm()
。
强烈建议您在使用此模块的任何新代码中使用这些函数。这几乎肯定会使您的代码的行为不那么令人惊讶。
timelocal_modern()
和 timegm_modern()
当 Time::Local
首次编写时,通常的做法是用两位数字值表示年份,例如 99
表示 1999
或 1
表示 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 年的偏移量。然而,为了让人们更容易理解年份的解释,因为人们更习惯于将年份视为两位数或四位数的值,因此遵循以下约定
大于 999 的年份被解释为实际年份,而不是距 1900 年的偏移量。因此,1964 年表示马丁·路德·金获得诺贝尔奖的年份,而不是 3864 年。
100..999 范围内的年份被解释为距 1900 年的偏移量,因此 112 表示 2012 年。此规则也适用于小于零的年份(但请参阅以下有关日期范围的注释)。
0..99 范围内的年份被解释为当前“世纪”中的年份的简写,该世纪定义为当前年份两侧的 50 年。因此,今天,在 1999 年,0 将指 2000 年,45 将指 2045 年,但 55 将指 1955 年。20 年后,55 将改为指 2055 年。这很混乱,但符合人们目前对两位数日期的看法。尽可能使用绝对的四位数年份。
上述方案允许解释广泛的日期,特别是如果使用 4 位数年份。但这还意味着随着时间的推移,代码的行为会发生变化,因为滚动“当前世纪”每年都会改变。
在早于 5.12.0 的 perl 版本中,可实际处理的日期范围取决于给定平台上 time_t
(通常为有符号整数)的大小。目前,对于大多数系统而言,此大小为 32 位,产生的近似范围为 1901 年 12 月至 2038 年 1 月。
如果给定超出支持范围的日期,timelocal()
和 timegm()
都会发出 croak。
从 5.12.0 版本开始,perl 已停止使用其所运行操作系统的 time 实现。相反,它拥有自己的这些例程的实现,安全范围至少为 +/- 2**52(约 1.42 亿年)
由于 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 更改导致区域时钟向前跳过一小时时,将有一小时不存在的本地时间。同样,对于“欧洲/巴黎”时区,区域时钟从 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]>
Florian Ragwitz <[email protected]>
J. Nick Koston <[email protected]>
Unknown <[email protected]>
此软件的版权归 Graham Barr 和 Dave Rolsky 所有 (c) 1997 - 2020。
这是一个免费软件;你可以根据 Perl 5 编程语言系统本身的相同条款重新分发或修改它。
可以在此发行版中包含的 LICENSE 文件中找到许可证的全文。