目錄

名稱

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 內建函式 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 已停止使用其正在執行的作業系統的時間實作。相反地,它有自己的這些常式的實作,安全範圍至少為 +/- 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 時間中較早的時間的 epoch。

不存在的當地時間 (DST)

當 DST 變更導致當地時鐘向前跳躍一小時時,將會有一小時不存在的當地時間。對於「歐洲/巴黎」時區來說,當地時鐘從 2001-03-25 01:59:59 跳到 2001-03-25 03:00:00。

如果 timelocal() 函式給定不存在的當地時間,它只會傳回一小時後時間的 epoch 值。

負的 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>

貢獻者

著作權和授權

此軟體的著作權為 Graham Barr 和 Dave Rolsky 所有 (c) 1997 - 2020。

這是免費軟體;您可以在與 Perl 5 程式語言系統相同的條款下重新散布或修改它。

授權的全文可以在此發行版隨附的 LICENSE 檔案中找到。