系統時區處理

2021-06-21 11:27:37 字數 2967 閱讀 9414

隨著雲計算時代的到來,應用的使用者可能來自世界各地,如果依然固執的認為時間都是北京時間,就有些固步自封了。

時區的問題非常複雜,不時會讓人陷入迷惘之中。下面我為介紹一下我專案中的經驗,希望拋磚引玉,讓我們且行且思考。

很久很久以前,一般企業應用都是這樣假定的:客戶端(使用者),應用伺服器,db伺服器都位於同乙個時區,它們的時間被精準同步。

客戶端時區 / 應用伺服器時區 / db伺服器時區

tz(+8:00)

這種情況下,開發者無需考慮時區的問題,在任何一層取時間,如js端的new date(), .net 端的datetime.now, db端的getdate()之類,獲取的資料都被認為是相同的。而對於日期資料的傳遞,一般採用固定格式的字串,比如yyyy-mm-dd hh:mm:ss。可是時間易逝,純真難尋。一旦考慮到多時區的問題,這一切立即變得複雜起來:

客戶端時區

應用伺服器時區

db伺服器時區

tz-b

tz-c

tz-d

對於乙個需要支援global應用,它的使用者可能位於不同的時區,應用伺服器和db伺服器也可能跨時區部署。現在,一旦你獲取時間,或者對時間進行運算,格式化,傳輸等等,都必須考慮時區問題了。

更為不幸的是,專案的需求可能會進一步加強複雜性:

1.       支援使用者設定偏好時區

2.       支援db儲存時間的時區可配置

於是事情變成下面的樣子:

使用者配置時區

客戶端時區

應用伺服器時區

db伺服器時區

db

配置時區

tz-a

tz-b

tz-c

tz-d

tz-e

如果開發者在處理時間的時候,每次都需要在這麼多的時區間轉換,精神崩潰可能是唯一的結局。為了把大家帶回以前的純真年代,需要在公共層面做了大量工作。

1)       首先制定規範,保證時間序列化/反序列化的時候,都是iso-8601 utc格式。

關於iso-8601格式,參考下面的說明

2)       提供獲取當前時間的全域性函式,該時間為db配置時區的時間。開發者應該只通過該函式獲取時間。

3)       保證從應用伺服器記憶體中的時間,都是db配置時區的時間,且型別為utc。

--從資料庫讀出。設定日期型別為utc

--從http request 進來的都是iso-8601 格式。設定日期型別為utc

--從伺服器序列化出去,設定日期序列化格式為iso-8601

4)       時間的時區轉換和格式化全部在客戶端完成。公共庫定義了兩個js函式

-- 時間傳送到客戶端,先轉成當前使用者設定時區的時間(tz-a)bg.

tousertimezone

(source

, ignoretimezone

)-- 回發時間資料到伺服器,先轉成db時區時間(tz-e)bg.

tosystemtimezone

(source

, ignoretimezone)

做了這些工作後,開發者基本不再需要關注時區的轉換,只需要客戶端呼叫相應的函式即可。現在的情況如下圖描述:

事情似乎變得簡單些了,開發者只需要執行幾個簡單的規則即可。事實並不完全如此,對於介面上使用者輸入的時間,如何確定它的時區,必須要業務自己界定。類似設定到期日期,定期事件提醒等任務,也會變得非常複雜。

5) 其他

1. epoch time

相對於1970.1.1的毫秒數,指的是相對於1970-01-01 00:00:00 utc的毫秒數。

.net mvc 預設序列化日期資料,出來的格式是 "\/date(1329661800000)\/" 

這個數字怎麼計算的呢?

public datetime fromunixtime(long unixtime)

public long tounixtime(datetime date)

相關知識

unix time

同時here

解釋了為什麼1970-1-1可以作為乙個epoch time,即起始時間

2. 夏令時

有的時區實行夏令時,如果選擇某個實行夏令時的時區作為系統時區,事情會變得非常複雜。而且夏令時的實施可能每年不一樣。

.net的timezoneinfo物件提供了getadjustmentrules()方法,返回乙個描述夏令時調整的規則。

js庫方面建議使用momentjs以及對應的timezone外掛程式。

Linux 系統時區

檢視當前時間 date 檢視當前timezone zdump etc localtime 通過 tzselect 命令獲取當地時區的 tz 值 tzselect 之後選取對應時區 地區 最終 tzselect 會以 posix tz 格式 如 asia shanghai 輸出所在時區並記錄。更改li...

設定系統時區

ubuntu安裝後,預設使用的時區是阿根廷,相差中國十多個小時 我們要修改成上海的即可 1.開啟指令框 2.輸入 並回車 sudo tzselect 出現選則亞洲,按數字4然後回車,繼續選中,直到找到北京時區 然後會自動選則上海時間,這個就是網路時間 3.複製當地時間檔案到 etc目錄下 輸入 su...

iOS 時區 日期處理

越努力.越幸福.willingseal.無論使用者設定的是12小時制還是24小時制,如何獲得24小時制的時間?nsdateformatter formatter nsdateformatteralloc init formatter setdateformat yyyy mm dd hh mm ss...