Time::Local - 有效率地計算當地時間和格林威治時間
版本 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 日格林威治時間午夜)以來的對應 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 已停止使用其正在執行的作業系統的時間實作。相反地,它有自己的這些常式的實作,安全範圍至少為 +/- 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 時間中較早的時間的 epoch。
當 DST 變更導致當地時鐘向前跳躍一小時時,將會有一小時不存在的當地時間。對於「歐洲/巴黎」時區來說,當地時鐘從 2001-03-25 01:59:59 跳到 2001-03-25 03:00:00。
如果 timelocal()
函式給定不存在的當地時間,它只會傳回一小時後時間的 epoch 值。
在 perl 版本 5.12.0 及更新版本中,完全支援負的 epoch 值。
在較舊版本的 perl 中,POSIX 標準未正式支援的負 epoch(time_t
)值,已知在某些系統上無法使用。這些系統包括 MacOS(OSX 之前)和 Win32。
在支援負 epoch 值的系統上,此模組應該能夠應付 epoch 開始之前的日期,直到系統的 time_t 最小值。
這些常式相當有效率,而且保證始終與 localtime()
和 gmtime()
相符。我們透過快取我們之前看過的任何月份的開始時間來管理這一點。如果我們知道該月份的開始時間,我們就可以隨時計算該月份內的任何時間。開始時間是使用數學公式計算的。這與其他呼叫 gmtime()
多次的演算法不同。
timelocal()
函式使用相同的快取來實作。我們假設我們正在轉換 GMT 時間,然後在完成時調整時區和夏令時間參數。請注意,時區會針對每個日期進行評估,因為各國偶爾會變更其官方時區。假設 localtime()
會修正這些變更,這個常式也會正確。
此模組是基於 Perl 4 函式庫 timelocal.pl,其包含在 Perl 4.036 中,而且很可能是由 Tom Christiansen 編寫的。
目前版本是由 Graham Barr 編寫的。
解釋兩位數年份的整個架構可以被視為一個錯誤。
錯誤可以提交至 https://github.com/houseabsolute/Time-Local/issues。
此發行版的使用者可以使用郵件列表 mailto:datetime@perl.org。
我通常也會在 irc://irc.perl.org
上以「autarch」的身分出現在 IRC 上。
Time-Local 的原始碼存放庫可以在 https://github.com/houseabsolute/Time-Local 找到。
Dave Rolsky <autarch@urth.org>
Florian Ragwitz <rafl@debian.org>
J. Nick Koston <nick@cpanel.net>
Unknown <unknown@example.com>
此軟體的著作權為 Graham Barr 和 Dave Rolsky 所有 (c) 1997 - 2020。
這是免費軟體;您可以在與 Perl 5 程式語言系統相同的條款下重新散布或修改它。
授權的全文可以在此發行版隨附的 LICENSE 檔案中找到。