一、背景
假如開發(fā)一套統(tǒng)一的系統(tǒng)產品,供遍布全球的所有分公司使用。nvy28資訊網(wǎng)——每日最新資訊28at.com
產品功能設計中,經(jīng)常會遇到一場活動,分跨不同時區(qū),系統(tǒng)需要顯示不同時區(qū)的時間,同時希望跨時區(qū)的用戶可以同一時間開始,同一時間結束。nvy28資訊網(wǎng)——每日最新資訊28at.com
對于類似跨時區(qū)處理問題,那我們該如何設計實現(xiàn)呢?nvy28資訊網(wǎng)——每日最新資訊28at.com
nvy28資訊網(wǎng)——每日最新資訊28at.com
nvy28資訊網(wǎng)——每日最新資訊28at.com
二、幾個重要概念
劃分時區(qū)是為了便于人們進行跨地區(qū)的交流、協(xié)作和管理。nvy28資訊網(wǎng)——每日最新資訊28at.com
時區(qū)的劃分以地球表面按經(jīng)線從東到西劃成一個個區(qū)域,每隔經(jīng)度15°劃分一個時區(qū),規(guī)定相鄰區(qū)域的時間相差1小時,如下圖所示:nvy28資訊網(wǎng)——每日最新資訊28at.com
圖片nvy28資訊網(wǎng)——每日最新資訊28at.com
英國皇家格林尼治天文臺,UTC/GMT 0 (零時區(qū))。nvy28資訊網(wǎng)——每日最新資訊28at.com
有東五區(qū)、東六區(qū)、東七區(qū)、東八區(qū)、東九區(qū),新疆在東五、東六、而東北在東九區(qū),但解放后我們國家統(tǒng)一采用北京時間(東八區(qū))為準。nvy28資訊網(wǎng)——每日最新資訊28at.com
Coordinated Universal Time,世界統(tǒng)一時間,中國是UTC+8。nvy28資訊網(wǎng)——每日最新資訊28at.com
Greenwish Mean Time,以地球公轉和自轉來計算時間,而UTC以原子鐘來計算時間。nvy28資訊網(wǎng)——每日最新資訊28at.com
1970年1月1日(UTC/GMT的午夜)開始所經(jīng)過的秒數(shù),因此,不同的時區(qū)的時間戳是相同的。nvy28資訊網(wǎng)——每日最新資訊28at.com
nvy28資訊網(wǎng)——每日最新資訊28at.com
三、操作系統(tǒng)、數(shù)據(jù)庫時區(qū)設置
3.1 Linux 中設置時區(qū)
一臺Linux服務器有兩個時間源,一個是硬件時間,即服務器硬件CMOS維護的時間,還有一個是軟件時間,即操作系統(tǒng)維護的時間,前者通過hwclock命令來訪問,后者則主要通過date命令來訪問。nvy28資訊網(wǎng)——每日最新資訊28at.com
nvy28資訊網(wǎng)——每日最新資訊28at.com
date是最常用的時間相關的命令,例如:nvy28資訊網(wǎng)——每日最新資訊28at.com
# 獲取當前時間$ dateFri Apr 26 15:22:16 CST 2024# 以特定格式輸出當前時間,格式字符串前以"+"開頭,例如獲得當前時間的epoch$ date +%s1714117833# 設置當前時間$ sudo date -s "2024-04-25 00:00:00"Thu Apr 25 00:00:00 CST 2024
如果是云服務器的話,中國區(qū)服務器默認都是UTC+8,海外機器則是UTC+0,關于這個大家再需要確認一下。nvy28資訊網(wǎng)——每日最新資訊28at.com
nvy28資訊網(wǎng)——每日最新資訊28at.com
Linux 使用 tzselect 調整時區(qū)
該命令會向導式的選擇洲區(qū)、國家和城市,然后在/usr/share/zoneinfo下會生成時區(qū)的文件,將該文件覆蓋/etc/localtime即可完成時區(qū)設置。nvy28資訊網(wǎng)——每日最新資訊28at.com
#設置時區(qū)tzselect
nvy28資訊網(wǎng)——每日最新資訊28at.com
3.2 MySQL 中設置時區(qū)
先登錄到mysql 安裝所在的機器。nvy28資訊網(wǎng)——每日最新資訊28at.com
-- 看下當前的mysql時區(qū)設置show variables like "%time_zone%";
下圖顯示 SYSTEM,表示用的默認時區(qū)。nvy28資訊網(wǎng)——每日最新資訊28at.com
圖片nvy28資訊網(wǎng)——每日最新資訊28at.com
我們可以修改成 +8 的北京所在時區(qū),操作如下:nvy28資訊網(wǎng)——每日最新資訊28at.com
set global time_zone = '+8:00'; set time_zone = '+8:00';
nvy28資訊網(wǎng)——每日最新資訊28at.com
如上修改,MySQL如果重啟后,又會恢復之前的設置。nvy28資訊網(wǎng)——每日最新資訊28at.com
下面介紹一種設置,讓重啟永久生效的方案:修改設置,重啟永久生效。nvy28資訊網(wǎng)——每日最新資訊28at.com
修改配置文件 /etc/my.cnfnvy28資訊網(wǎng)——每日最新資訊28at.com
[mysqld]default-time_zone = '+8:00'
重啟 MySQL 生效nvy28資訊網(wǎng)——每日最新資訊28at.com
systemctl stop mysqld.servicesystemctl start mysqld.service
nvy28資訊網(wǎng)——每日最新資訊28at.com
四、系統(tǒng)跨時區(qū)設計
現(xiàn)在我們回到正規(guī),談談如何解決上面開篇提出的問題。nvy28資訊網(wǎng)——每日最新資訊28at.com
4.1 服務端中的時間處理
既然時區(qū)的處理不能在客戶端做,換言之就必須在服務端實現(xiàn)。nvy28資訊網(wǎng)——每日最新資訊28at.com
nvy28資訊網(wǎng)——每日最新資訊28at.com
這樣就需要解決兩個問題:時間的保存和獲取。nvy28資訊網(wǎng)——每日最新資訊28at.com
客戶端傳來的時間為客戶端所在時區(qū)的當?shù)貢r間,服務端接收到客戶端發(fā)送的時間后,需要基于客戶端相應時區(qū)轉換成UTC時間才能保存到數(shù)據(jù)庫。nvy28資訊網(wǎng)——每日最新資訊28at.com
nvy28資訊網(wǎng)——每日最新資訊28at.com
圖片nvy28資訊網(wǎng)——每日最新資訊28at.com
nvy28資訊網(wǎng)——每日最新資訊28at.com
所有后端暴露的接口中的時間對象,全部以 UTC 時間表示。nvy28資訊網(wǎng)——每日最新資訊28at.com
同時,所有后端在存儲、計算、傳輸時間時,也統(tǒng)一使用 UTC 時間。由于 DB 存儲時間時,時區(qū)信息會被丟掉,因此應保證丟掉的時區(qū),是大家明確約定清楚的無歧義的,即 UTC。這樣一來,數(shù)據(jù)庫中的所有時間字段也都沒有歧義。nvy28資訊網(wǎng)——每日最新資訊28at.com
nvy28資訊網(wǎng)——每日最新資訊28at.com
4.2 前端中的時間
時間在前端中的應用比較簡單,通常的方案是:后端直接返回 ISO 標準本地時間,避免 UTC 在前端再次格式化和處理時區(qū),否則會把問題變得更加復雜(時區(qū)設置只發(fā)生在應用服務器中)。nvy28資訊網(wǎng)——每日最新資訊28at.com
如果有需要處理跨時區(qū)的業(yè)務場景需,可以讓用戶選擇時區(qū),并在任何時候都將處理后的時區(qū)信息放到時間字符串中。nvy28資訊網(wǎng)——每日最新資訊28at.com
nvy28資訊網(wǎng)——每日最新資訊28at.com
圖片nvy28資訊網(wǎng)——每日最新資訊28at.com
前端的時間格式化比較簡單,可以使用 Day.js 和 Moment.js 等時間庫來完成。nvy28資訊網(wǎng)——每日最新資訊28at.com
正是因為前面講到的時區(qū)問題,Moment.js 為了處理此問題,使用了一個巨大的 JSON 文件記錄了不同年份之間、不同國家、不同經(jīng)緯度的時區(qū)信息,另外這些信息還會和語言信息綁定導致文件非常巨大。nvy28資訊網(wǎng)——每日最新資訊28at.com
nvy28資訊網(wǎng)——每日最新資訊28at.com
4.3 其它注意事項
在編程中還有一些額外的坑可能需要注意:nvy28資訊網(wǎng)——每日最新資訊28at.com
- 使用環(huán)境變量配置時區(qū)信息,使用應用服務器來裁決時區(qū)(沒有特別業(yè)務說明的情況下),因此確保服務器配置的時區(qū)相同。
- 如果是跨國交易或者數(shù)據(jù)同步的時候,根據(jù)客戶端連接到的服務器來決定操作用戶所屬的時區(qū)。
- 依賴應用服務器的時區(qū)信息做時區(qū)裁決,不要依賴數(shù)據(jù)庫的時區(qū)設置,數(shù)據(jù)庫透明存放數(shù)據(jù)即可。
- 時區(qū)配置來源有操作系統(tǒng)、環(huán)境變量、數(shù)據(jù)庫時區(qū)、Java 啟動參數(shù),建議統(tǒng)一使用 Java 啟動參數(shù),避免配置出錯,數(shù)據(jù)庫不要做時區(qū)自動轉換,避免使用 TIMESTAMP 類型。
- 在高并發(fā)的場景中獲取系統(tǒng)時間可能有性能問題,原因是 JVM 需要訪問進入系統(tǒng)內核態(tài)執(zhí)行指令,當高并發(fā)且不需要高精度時間時可以增加緩存,但需要權衡處理。
- 有時候在處理業(yè)務時,需要考慮自然月問題,需要特別注意。
- 關于時間同步問題中,還有一個墻上時鐘和單調時鐘的問題。墻上時鐘是指根據(jù)日歷獲取時間,會受到時間校對回撥的問題,而單調時鐘是指系統(tǒng)啟動后的秒數(shù),它不會回撥。在使用 NTP 服務時,可以配置為 NTPD 模式,通過調慢時間頻率避免回撥。
nvy28資訊網(wǎng)——每日最新資訊28at.com
五、補充知識:夏令時、冬令時
圖片nvy28資訊網(wǎng)——每日最新資訊28at.com
nvy28資訊網(wǎng)——每日最新資訊28at.com
夏令時(Daylight Saving Time:DST),也叫夏時制,又稱“日光節(jié)約時制”和“夏令時間”,是一種為節(jié)約能源而人為規(guī)定地方時間的制度,在這一制度實行期間所采用的統(tǒng)一時間稱為“夏令時間”。一般在天亮早的夏季人為將時間調快一小時,可以使人早起早睡,減少照明量,以充分利用光照資源,從而節(jié)約照明用電。nvy28資訊網(wǎng)——每日最新資訊28at.com
夏令時調整通常適用于:夏季日照時間相對較長,日出和日落時間發(fā)生較大變化的地方。關于夏令時的問題,人們褒貶不一。nvy28資訊網(wǎng)——每日最新資訊28at.com
nvy28資訊網(wǎng)——每日最新資訊28at.com
有夏令時就會有冬令時,冬令時 通常是指當?shù)厥褂玫臉藴蕰r間。在使用夏令時 - 日光節(jié)約時制(Daylight Saving Time) 的地區(qū),夏天時鐘撥快一小時,冬天再撥回標準時間。nvy28資訊網(wǎng)——每日最新資訊28at.com
nvy28資訊網(wǎng)——每日最新資訊28at.com
那為什么我國沒有夏令時呢?nvy28資訊網(wǎng)——每日最新資訊28at.com
其實不使用夏令時也能實現(xiàn)節(jié)約能源、減少照明成本的目的,只不過把調整人們生活節(jié)奏的權利給到了具體場景。在學校,會使用夏季和冬季課表,在工作環(huán)境中,某些公司也會針對下冬夏調整上班時間。nvy28資訊網(wǎng)——每日最新資訊28at.com
nvy28資訊網(wǎng)——每日最新資訊28at.com
六、閱讀更多及參考文獻nvy28資訊網(wǎng)——每日最新資訊28at.com
本文參考資料:
- https://en.wikipedia.org/wiki/Time_zone
- https://zh.wikipedia.org/wiki/ISO_8601
- https://www.rfc-editor.org/rfc/rfc3339
- https://datatracker.ietf.org/doc/html/rfc5545
- https://en.wikipedia.org/wiki/System_time
- https://www.iplocate.com/
- https://en.wikipedia.org/wiki/Timestamp
本文鏈接:http://www.www897cc.com/showinfo-26-86339-0.html系統(tǒng)設計中跨時區(qū)問題 解決方案
聲明:本網(wǎng)頁內容旨在傳播知識,若有侵權等問題請及時與本網(wǎng)聯(lián)系,我們將在第一時間刪除處理。郵件:2376512515@qq.com
上一篇: 大模型下B端前端代碼輔助生成的思考與實踐
下一篇: Python 教你三分鐘用Bert搭建問答搜索引擎