天天看點

跨語言時區處理與Epoch

0 時區與Unix Epoch

為了統一地球上各地區的時間,建立了世界時,格林威治标準時間即作為第一個标準時間。地球以格林威治子午線為标準即0時區,按經度劃分為24時區,東半球早于标準時間為正時區,西半球晚于标準時間為負時區。中國采用中原標準時間即正8區。格林威治标準時間縮寫為GMT,東8區用GMT+08:00表示,即格林威治子午線的時間加上8小時為北京當地時間。

随着計時精度要求的提高,出現了原子計時器,形成了新的世界時,又稱世界協調時簡寫UTC,就日常生活需求GMT與UTC等同。同時時區的劃分也是一緻的,北京時區用UTC+08:00表示。

在Unix系統上,為了用一個整數表示具體的時間,以<code>1970年1月1日0時0分0秒0</code>為基準, 将經過的秒數記為一個數值,然後用該數值表示某個時間。比如時間戳<code>3600</code>即表示<code>1970年1月1日1時0分0秒</code>,也就是在基準時間上經過了3600秒。由于時區問題,對于<code>UTC+00:00</code>時區的<code>1970年1月1日0時0分0秒0</code>時間點,實際為北京當地時間的<code>1970年1月1日8時0分0秒0</code>,這樣對于時間戳<code>3600</code>即為北京當地時間的<code>1970年1月1日9時0分0秒0</code> 表示為 <code>1970-01-01 09:00:00+08:00</code>。

時間表示一般分為帶時區資訊的、不帶時區的、Unix Epoch。不帶時區的日期串稱為<code>Naive Date</code>,如<code>1970-01-01 09:00:00</code>。在日常生活中特指當地時間,在程式語言中有的沒有特指,就是時區缺失,可以加上時區資訊,有的語言預設為作業系統預設時區。

下面以<code>Python</code>和<code>golang</code>為例, 進行API操作描述

1 Python 時區操作

将某個時區的日期轉換為另一個時區的日期,如中原標準時間的晚18點,轉換為東京時間,即為晚19點。

2 總結

在進行跨時區處理時,隻要正确區分naive日期對象和帶時區的日期對象,基本就保證了時間處理的正确性,而Epoch值表示相對于基準時間的內插補點,有效的回避了該問題(不同時區基準naive不一樣)。避免了傳遞不帶日期的時間字元串的時區問題。

以Token過期為例,中原標準時間2017-04-25 18:00:03生成一個Token,一小時後過期,即中原標準時間2017-04-25 19:00:03過期。該Token傳給東京的伺服器後,按東京當地時間應該在東京2017-04-25 20:00:03時過期。

互動時傳遞參數為2017-04-25 19:00:03+0800時,由于帶有時區資訊可以準确表達,若缺失時區如2017-04-25 19:00:03時,雙方都沒有處理時會出錯。

若用Epoch表示,Token生成時間為中原標準時間2017-04-25 18:00:03對應Epoch值為1493114403(即距離基準中原標準時間1970-01-01 08:00:00 相隔1493114403秒),Token過期時間為中原標準時間2017-04-25 19:00:03對應Epoch為1493118003(即生成時間之後3600秒)。 傳遞該Epoch值至東京伺服器,收到後,解釋為東京基準時間起之後1493118003秒的那個時間點該Token過期,自然就對應東京時間2017-04-25 20:00:03了。此過程,無需時區處理。

也就是說Epoch <code>1</code>對應

<code>1970-01-01 00:00:01+0000</code>(UTC)

<code>1970-01-01 08:00:01+0800</code>(北京當地時間)

<code>1970-01-01 09:00:01+0900</code>(東京當地時間)

而Epoch <code>1493118003</code>對應

<code>2017-04-25 11:00:03+0000</code>(UTC)

<code>2017-04-25 19:00:03+0800</code>(北京)

<code>2017-04-25 20:00:03+0900</code>(東京)

這樣使用Epoch進行跨時區、跨語言互動時,處理與平常(無時區互動時)一緻,無需任何特殊處理。若進行特殊處理,又處理不對應時,反倒會畫蛇添足。

當采用的架構提供修改時區的功能是,可能會導緻與語言預設行為不一緻,此時要特别注意。

繼續閱讀