時(shí)區(qū)那些事兒

摘要:本文總結(jié)幾類項(xiàng)目中跟時(shí)區(qū)相關(guān)的問題,給大家分享一些基本的時(shí)區(qū)知識(shí),以及如何在軟件開發(fā)和測(cè)試中注意考慮時(shí)區(qū)因素,以避免因時(shí)區(qū)而導(dǎo)致系統(tǒng)功能的問題。

(原文:時(shí)區(qū)那些事兒

場(chǎng)景一

“小D,我發(fā)現(xiàn)調(diào)整不同的timezone(時(shí)區(qū)),咱們的KPI計(jì)算結(jié)果可能會(huì)有一天的誤差...”

“?。∥铱纯词裁丛?。”

“嗯啦,KPI務(wù)必是準(zhǔn)確的,可不能有誤差...”

“小Q,我知道啦!咱們的工單任務(wù)完成時(shí)間記錄的是UTC時(shí)間,是考慮了timezone轉(zhuǎn)換的,但是缺失信息的記錄并沒有考慮... ”

“為什么缺失信息不記錄UTC時(shí)間呢?”

“因?yàn)槿笔畔⒅挥涗浫掌冢]有時(shí)間?!?/p>

藍(lán)鯨項(xiàng)目的小Q和小D說的是啥呢?下面先來借助維基百科的解釋來介紹時(shí)區(qū)和UTC的概念:

  1. 時(shí)區(qū)(timezone)
    時(shí)區(qū)是地球上的區(qū)域使用同一個(gè)時(shí)間的定義。以前,人們通過觀察太陽的位置決定時(shí)間,這就使得不同的地方的時(shí)間有所不同(地方時(shí))。1863年,首次使用時(shí)區(qū)的概念,通過設(shè)立一個(gè)區(qū)域的標(biāo)準(zhǔn)時(shí)間部分地解決了這個(gè)問題。

  2. UTC
    協(xié)調(diào)世界時(shí)(英語:Coordinated Universal Time,法語:Temps Universel Coordonné,簡(jiǎn)稱UTC)是世界上調(diào)節(jié)時(shí)鐘和時(shí)間的主要時(shí)間標(biāo)準(zhǔn),它與0度經(jīng)線的平太陽時(shí)相差不超過1秒。協(xié)調(diào)世界時(shí)是最接近格林威治標(biāo)準(zhǔn)時(shí)間(GMT)的幾個(gè)替代時(shí)間系統(tǒng)之一。對(duì)于大多數(shù)用途來說,UTC時(shí)間被認(rèn)為能與GMT時(shí)間互換,但GMT時(shí)間已不再被科學(xué)界所確定。

原來小Q和小D所在的藍(lán)鯨項(xiàng)目正在開發(fā)一個(gè)全球性的系統(tǒng),用戶處于世界各地的不同時(shí)區(qū)。

系統(tǒng)的工單處理流程中每個(gè)任務(wù)的完成因?yàn)橛邢群笠蕾囮P(guān)系,當(dāng)時(shí)記錄的是完成時(shí)刻的UTC時(shí)間,以防不同時(shí)區(qū)的用戶完成依賴任務(wù)的時(shí)候產(chǎn)生沖突。

比如:處于UTC+0800時(shí)區(qū)的用戶S在當(dāng)?shù)貢r(shí)間2019-02-28 09:30處理了任務(wù)1,系統(tǒng)記錄的時(shí)間是UTC 2019-02-28 01:30,接下來處于UTC-0800的用戶G在當(dāng)?shù)貢r(shí)間2019-02-27 18:20來處理任務(wù)2(必須晚于任務(wù)1完成),系統(tǒng)記錄的是UTC 2019-02-28 02:20,這個(gè)時(shí)間就不會(huì)有問題。

工單任務(wù)處理

在處理某個(gè)任務(wù)的時(shí)候如果發(fā)現(xiàn)有信息缺失,需要記錄發(fā)現(xiàn)和收集到缺失信息的時(shí)間(可以是過去時(shí)間,由用戶輸入),而這個(gè)發(fā)現(xiàn)和收集完成的時(shí)間一般都是同一個(gè)用戶來記錄,本身不會(huì)有時(shí)區(qū)問題,另外這個(gè)時(shí)間跟工單處理流程中的任務(wù)完成時(shí)間并沒有特別直接的關(guān)系,就對(duì)缺失信息部分只記錄由用戶輸入的日期,而且是直接記錄用戶當(dāng)?shù)貢r(shí)間的日期,并沒有記錄時(shí)分秒,也沒法根據(jù)UTC進(jìn)行轉(zhuǎn)換。

這樣,同一個(gè)日期,比如,在東部時(shí)區(qū)的2019-04-28可能就是西部時(shí)區(qū)的2019-04-27,在西部時(shí)區(qū)的2019-04-28可能就是東部時(shí)區(qū)的2019-04-29,前后有相差一天的可能性。

但是,在做到KPI功能的時(shí)候,計(jì)算KPI需要結(jié)合工單任務(wù)處理時(shí)間和缺失信息記錄時(shí)間,由于沒有考慮時(shí)區(qū)問題,不同時(shí)區(qū)可能會(huì)造成KPI有一天的誤差。

場(chǎng)景二

“我們這里有個(gè)線上用戶報(bào)過來一個(gè)bug,合同簽訂日期簽完以后打開編輯,在頁面上變成了一個(gè)后一天的日期,沒法保存”,R說。

“我們的合同簽訂日期最晚是簽訂當(dāng)天的日期,的確不能用將來日期,這個(gè)業(yè)務(wù)上是這么要求的”,小B說。

“我們前端也有校驗(yàn)不允許存儲(chǔ)將來日期??墒菫槭裁磿?huì)變成后一天的日期呢”,小D一臉迷惑。

“會(huì)不會(huì)還是timezone的問題?!” 小Q由于前一陣做KPI的時(shí)候測(cè)試時(shí)區(qū)相關(guān)問題花了不少精力去搞明白各種case,對(duì)時(shí)區(qū)也有了不少的研究,對(duì)此比較敏感。

“那個(gè)報(bào)bug的用戶設(shè)置是什么timezone的?” 小B問。

“是東14區(qū)(UTC+14:00)!” R回答。

“竟然還有東14區(qū),我一直以為都在正負(fù)12時(shí)區(qū)之間。”小Q很驚訝。

“那就對(duì)了!的確是timezone引發(fā)的問題!”小D沉思了一會(huì),激動(dòng)的跳起來。

這又是為什么呢?大家都在焦急地等待小D的解釋。

原來,對(duì)于這種沒有時(shí)分秒要求的時(shí)間,我們系統(tǒng)統(tǒng)一用當(dāng)天中午UTC的12:00存入DB,這樣做的原因是保證-12~+12時(shí)區(qū)內(nèi)都不會(huì)有問題,換算以后都是當(dāng)天,但是沒有考慮到正負(fù)13、14區(qū)的情況。

下面我們來舉例說明為什么東14區(qū)的會(huì)有問題。

假設(shè)用戶A和用戶B分別處于東12區(qū)和東14區(qū),A和B分別在當(dāng)?shù)貢r(shí)間的2019年04月28日的上午9:00簽訂了合同,那么系統(tǒng)記錄的時(shí)間都是UTC 2019-04-28 12:00,在用戶A的頁面上顯示的日期是2019-04-28UTC 2019-04-28 12:00轉(zhuǎn)換東12區(qū)的時(shí)間是2019-04-28 24:00,這個(gè)時(shí)間的日期還是4月28日),而在用戶B的頁面上顯示的日期應(yīng)該是2019-04-29UTC 2019-04-28 12:00轉(zhuǎn)換東14區(qū)的時(shí)間是2019-04-28 26:00,也就是2019-04-29 02:00,這個(gè)時(shí)間的日期變成了4月29日)。

如下表,用戶A、B、C、D的合同簽訂時(shí)間都是當(dāng)?shù)貢r(shí)間2019年04月28日的上午9:00:

用戶 所處時(shí)區(qū) 系統(tǒng)記錄時(shí)間 記錄時(shí)間轉(zhuǎn)換為當(dāng)?shù)貢r(shí)間 存儲(chǔ)后頁面顯示時(shí)間
A UTC+12:00 UTC 2019-04-28 12:00 2019-04-28 24:00 2019-04-28
B UTC+14:00 UTC 2019-04-28 12:00 2019-04-29 02:00 2019-04-29
C UTC-12:00 UTC 2019-04-28 12:00 2019-04-28 00:00 2019-04-28
D UTC-13:00 UTC 2019-04-28 12:00 2019-04-27 23:00 2019-04-27

同理,用戶C和D處于西部時(shí)區(qū),從上表我們可以看到處于-12的C的時(shí)間是跟實(shí)際日期一樣,而處于-13的用戶D的時(shí)間則比實(shí)際時(shí)間早了一天,也是有問題的。

至此,我們明白了為什么東14區(qū)會(huì)引起系統(tǒng)功能有問題。但是,一直以來以為時(shí)區(qū)都在正負(fù)12之間,為什么會(huì)有大于+12的時(shí)區(qū)呢?原來小D是早就知道的,他給我們解釋了是下面兩個(gè)原因:

  1. 有些跨國(guó)際日期變更線的地區(qū),為了保證該地區(qū)所有地方的時(shí)間都在同一天,就把時(shí)區(qū)設(shè)置成了大于+12的,比如基里巴斯。
  2. 有些處于+12區(qū)的地區(qū)有夏令時(shí),夏令時(shí)的時(shí)候時(shí)區(qū)會(huì)變成+13,比如新西蘭。

其實(shí),時(shí)區(qū)還有很多有意思的,有偏移量是半個(gè)小時(shí)的(如印度),還有45分鐘的(如尼泊爾),不一定都是整點(diǎn)。更多詳情可以參考維基百科的時(shí)區(qū)列表。

場(chǎng)景三

客戶P發(fā)過來一封郵件:
“自2017年初以來,土耳其和白俄羅斯政府不再遵守夏令時(shí)(DST),因此這將改變這些國(guó)家的時(shí)區(qū)為GMT+3,而不是GMT+2。 目前,在我們系統(tǒng)伊斯坦布爾和明斯克都顯示為GMT+2?!?/p>

這個(gè)問題聽起來很簡(jiǎn)單,直接在DB里把對(duì)應(yīng)的時(shí)區(qū)改一下就ok了??墒?,正當(dāng)小D準(zhǔn)備去改數(shù)據(jù)的時(shí)候,發(fā)現(xiàn)了一個(gè)崩潰的事情:伊斯坦布爾和明斯克還跟另外兩個(gè)地區(qū)的時(shí)區(qū)是綁定在一起的,見下圖。當(dāng)前系統(tǒng)中已經(jīng)設(shè)置好的一些會(huì)議,沒法判斷真正需要的是哪個(gè)地區(qū)對(duì)應(yīng)的時(shí)區(qū)... 已有數(shù)據(jù)無法修復(fù)!


伊斯坦布爾和明斯克

在此先不解釋如何修復(fù)的數(shù)據(jù)問題。

當(dāng)時(shí),我們正好要把時(shí)區(qū)引入到另外一個(gè)新系統(tǒng),考慮到避免再出現(xiàn)類似的情況,采用了一個(gè)新的庫(kù),那就是每個(gè)地區(qū)對(duì)應(yīng)一個(gè)時(shí)區(qū)。比如:GMT+08:00分別有上海、烏魯木齊、重慶、香港、新加坡等時(shí)區(qū)。

場(chǎng)景四

“這個(gè)新的timezone里怎么有一些亂七八糟的時(shí)區(qū)?”

“亂七八糟的時(shí)區(qū)?”

“Etc什么的,好像還正負(fù)矛盾的。比如:(GMT+08:00)Etc/GMT-8” 對(duì)時(shí)區(qū)敏感的小Q覺得這些時(shí)區(qū)不太順眼。

“這個(gè)是咱們新的時(shí)區(qū)庫(kù)引入的,不過的確挺奇怪的,不知道這個(gè)Etc時(shí)區(qū)是啥?!?小B也不是很明白。

原來,這個(gè)時(shí)區(qū)表示法里時(shí)區(qū)名字都是用“區(qū)域/位置”來表示,比如“Asia/Shanghai”,而前面的“(GMT+08:00)”是表示相對(duì)于GMT的一個(gè)偏移量。前面對(duì)話中提到的“Etc/GMT-8”只是時(shí)區(qū)名字而已。那為什么叫這么奇怪的名字呢?

下面引用維基百科的解釋來說明:

區(qū)域分為大陸,海洋或“Etc”三類。 目前使用的大陸和海洋是非洲,美洲,南極洲,北極,亞洲,大西洋,澳大利亞,歐洲,印度和太平洋。

包括海洋的原因是一些島嶼很難連接到某個(gè)大陸,有些地理位置與一個(gè)大陸相連,在政治上卻與另一個(gè)大陸相連。

“Etc”屬于特殊區(qū)域,用于某些管理區(qū)域,特別是用于表示協(xié)調(diào)世界時(shí)的“Etc/UTC”。 為了符合POSIX樣式,以“Etc/GMT”開頭的區(qū)域名稱的標(biāo)志與標(biāo)準(zhǔn)ISO 8601慣例相反。 在“Etc”區(qū)域,格林威治標(biāo)準(zhǔn)時(shí)間以西的區(qū)域有一個(gè)正號(hào),而以東區(qū)域的名稱有一個(gè)負(fù)號(hào)(例如“Etc/GMT-14”比GMT早14個(gè)小時(shí)。)

總結(jié)

對(duì)于國(guó)際化的軟件系統(tǒng)來說,時(shí)區(qū)還是需要特別關(guān)注的。根據(jù)所經(jīng)歷項(xiàng)目出現(xiàn)的時(shí)區(qū)相關(guān)問題,嘗試總結(jié)以下幾點(diǎn)供大家參考。

開發(fā)方面

  1. 對(duì)于具體操作執(zhí)行時(shí)間,這種都是包含時(shí)分秒的具體時(shí)刻,存儲(chǔ)全部采用UTC時(shí)間,在顯示的時(shí)候根據(jù)時(shí)區(qū)偏移量轉(zhuǎn)換為對(duì)應(yīng)的當(dāng)?shù)貢r(shí)間。不同模塊之間傳遞的時(shí)間參數(shù)要以UTC格式。
  2. 對(duì)于沒有精確時(shí)間點(diǎn)的、由用戶輸入的日期,這種一般對(duì)時(shí)間要求沒有那么精確,可以加上操作時(shí)候的時(shí)間戳存儲(chǔ)到數(shù)據(jù)庫(kù)。當(dāng)然還需要結(jié)合業(yè)務(wù)對(duì)時(shí)間的具體需求來定不同方案。
  3. 時(shí)區(qū)數(shù)據(jù)庫(kù)單獨(dú)一個(gè)位置作為一個(gè)時(shí)區(qū)的方式可以更方便修改對(duì)應(yīng)位置的時(shí)區(qū),比如:“(GMT+08:00)Asia/Chongqing”,而不是“(GMT+08:00) Beijing,Chongqing,Hong Kong,Urumqi”
  4. 關(guān)于UTC時(shí)間的獲?。嚎梢杂玫谌焦ぞ攉@取客觀的UTC時(shí)間,但是出于安全考慮,一般不用;而是直接從服務(wù)器獲取UTC時(shí)間,所以需要保證服務(wù)器的客觀時(shí)間點(diǎn)是正確的,如果服務(wù)器的客觀時(shí)間點(diǎn)有錯(cuò),將會(huì)導(dǎo)致計(jì)算出的時(shí)間有出入。
  5. 有時(shí)候需要自定義一些時(shí)間段供用戶使用,這種需要特別注意夏令時(shí)的影響。

測(cè)試方面

  1. 對(duì)于過去時(shí)間、未來時(shí)間的測(cè)試,一定要測(cè)不同時(shí)區(qū)跨度看是否滿足條件能夠正確使用。
  2. 顯示時(shí)間:本地,不同時(shí)區(qū)切換能正確顯示相應(yīng)時(shí)間;輸入時(shí)間:不同時(shí)區(qū)對(duì)應(yīng)的日期邊界值要重點(diǎn)考慮。如果只能輸入未來時(shí)間,要考慮一些負(fù)時(shí)區(qū)的情況,比如 UTC-12, UTC-13等;如果只能是過去時(shí)間,要考慮UTC+12, UTC+14等。
  3. 定時(shí)任務(wù):如果設(shè)置成固定時(shí)間段(如:每隔一小時(shí))執(zhí)行,與時(shí)區(qū)無關(guān);每天定點(diǎn)執(zhí)行,要考慮不存在的或者多出的時(shí)間段。
  4. 日志文件:時(shí)間戳命名的文件,不會(huì)由于夏令時(shí)導(dǎo)致文件名重復(fù);文件內(nèi)容涉及時(shí)間部分,不同時(shí)區(qū)顯示正確。
  5. 夏令時(shí)跳變時(shí)刻系統(tǒng)功能測(cè)試,對(duì)于多出來的一小時(shí)或者減少的一小時(shí)系統(tǒng)行為是否正常。
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 概念解釋 時(shí)區(qū)(Timezone) 為什么會(huì)將地球分為不同時(shí)區(qū)呢?因?yàn)榈厍蚩偸亲晕飨驏|自轉(zhuǎn),東邊總比西邊先看到太陽...
    黑炭媽閱讀 8,674評(píng)論 0 5
  • 為什么會(huì)有時(shí)區(qū)?一共有多少個(gè)時(shí)區(qū)?時(shí)區(qū)與時(shí)間的關(guān)系?哪個(gè)時(shí)區(qū)的時(shí)間更快一些?東十二區(qū)和西十二區(qū)是不是同一個(gè)時(shí)區(qū)?東...
    特立獨(dú)行的石頭閱讀 1,161評(píng)論 0 0
  • 國(guó)家電網(wǎng)公司企業(yè)標(biāo)準(zhǔn)(Q/GDW)- 面向?qū)ο蟮挠秒娦畔?shù)據(jù)交換協(xié)議 - 報(bào)批稿:20170802 前言: 排版 ...
    庭說閱讀 12,413評(píng)論 6 13
  • SwiftDate概況 從Swift發(fā)布起,我們就沒有放棄使用Swift。 當(dāng)然,我們希望在項(xiàng)目能夠輕松自如地管理...
    Mee_Leo閱讀 10,336評(píng)論 1 13
  • 不知道您是否相信家中房子格局和擺設(shè)的風(fēng)水之說?我猜肯定有人不信,呵呵,我也曾經(jīng)不信,直到…… 話說...
    月下籬閱讀 815評(píng)論 15 3

友情鏈接更多精彩內(nèi)容