在說時(shí)區(qū)問題的時(shí)候,估計(jì)很多人都很不屑。因?yàn)楂@取時(shí)區(qū)的方法真的太簡單了。尤其是很多面向百度編程的iter。
比如,獲取時(shí)區(qū)的方法一句就能搞定:
???????String timeZone =“GMT”+String.valueOf(TimeZone.getDefault().getRawOffset() / (3600 *1000));
當(dāng)時(shí)很不屑這個(gè)問題的時(shí)候。我就知道你肯定會(huì)犯的幾個(gè)你自己都可能不知道的錯(cuò)。就是關(guān)于夏時(shí)令和冬時(shí)令的問題。
那么再說這個(gè)問題之前,我們先說說國際上對(duì)于時(shí)區(qū)的規(guī)定
時(shí)區(qū)
1884年在華盛頓召開的國際經(jīng)度會(huì)議(又稱國際子午線會(huì)議)上,規(guī)定將全球劃分為24個(gè)時(shí)區(qū)(東、西各12個(gè)時(shí)區(qū))。
如下圖所示:
全球同一時(shí)刻不同時(shí)區(qū)的本地時(shí)間不同例如中國時(shí)間:10:00 AM
對(duì)于美國西部時(shí)間:18:00 PM(冬令時(shí))
?17:00 PM(夏令時(shí))。
1. GMT VS UTC
GMT?全稱?Greenwich Mean Time,中文為格林威治標(biāo)準(zhǔn)時(shí)間。
UTC?全稱?Universal Time Coordinated, 中文為協(xié)調(diào)世界時(shí)。
GMT和UTC都是代表0零時(shí)區(qū)的時(shí)間,兩者相等。UTC是1972年之后引入的概念,是GMT的后繼,現(xiàn)廣泛應(yīng)用于科技領(lǐng)域。
2. PST
全球分為24個(gè)時(shí)區(qū)之后,從UTC/GMT 開始往西依次表示為UTC/GMT - 1,-2……,往東表示為UGC/GMT+1,+2……。
除了UTC/GMT之外,還有一個(gè)很常見的時(shí)區(qū):PST。
PST 全稱 Pacific Standard Time,太平洋標(biāo)準(zhǔn)時(shí)間,等同于UTC/GMT -8,既西八區(qū),被北美國家使用。
冬令時(shí)、夏令時(shí)
地球自轉(zhuǎn)方向從西向東,所以東邊更早看到新一天的太陽。各地區(qū)在時(shí)區(qū)概念的基礎(chǔ)上,時(shí)間更接近于太陽時(shí)(最簡單的理解就是太陽直射時(shí),當(dāng)?shù)貢r(shí)間基本接近12點(diǎn))。
晝夜長短會(huì)隨著四季變換,出于減少能源消耗的目的,提出了冬令時(shí)、夏令時(shí)的概念。
在天亮早的夏季人為將時(shí)間提前一小時(shí),可以使人早起早睡,減少照明量,以充分利用光照資源,從而節(jié)約照明用電。
冬令時(shí)通常代表使用當(dāng)?shù)氐臉?biāo)準(zhǔn)時(shí)間,夏令時(shí)實(shí)施期間時(shí)鐘撥快一小時(shí),相當(dāng)于時(shí)區(qū)往前(東)進(jìn)一個(gè)。
每年會(huì)對(duì)時(shí)間進(jìn)行兩次調(diào)整,如下圖所示:
也就是說,地球上并不是每一天都是24小時(shí)的。也有一天23小時(shí)或25小時(shí)的存在。
夏令時(shí)起始和結(jié)束的兩天,其中開始的一天23小時(shí),結(jié)束的一天25小時(shí)。
具體好奇的可以進(jìn)入這個(gè)傳送門看看究竟。博主在這里就不再具體講夏令時(shí)和冬令時(shí)的問題了。小餅干就把項(xiàng)目中遇到的坑跟大家分享一下:
我其中的一個(gè)項(xiàng)目主要服務(wù)歐美客戶,春天,因?yàn)闀r(shí)區(qū)問題,被報(bào)了bug(美國市場(chǎng)部同事報(bào)的),我檢查了代碼,然后沒發(fā)現(xiàn)有問題,但還是改了。然后同年冬天,再次因?yàn)檫@個(gè)問題被報(bào)了bug。我很郁悶,這個(gè)問題明明解決過,并且驗(yàn)證過的啊。為什么又出現(xiàn)了。然后我始終找不到我具體哪里出問題了。后來,我很奇怪美國時(shí)間為什么不對(duì)(因?yàn)檗k公室之前所在地之前相差18個(gè)小時(shí),后來相差17個(gè)小時(shí))。美國人不知道中國時(shí)區(qū)不分夏令時(shí)和冬令時(shí)(備注俄羅斯也不再區(qū)分夏令時(shí)和冬令時(shí),但是目前國際上仍然有超過110個(gè)國家和地區(qū)區(qū)分夏令時(shí)和冬令時(shí))。然后我就查閱了資料,明白了夏令時(shí)和冬令時(shí)的問題。
好了,故事就講到這里,我們說說怎么解決這個(gè)問題吧。我也曾面向百度編程,查閱了這方面的資料,試過其他踩過坑的大佬寫的方法,但是最后都不能達(dá)到隨意切換時(shí)區(qū)和時(shí)令都測(cè)試通過的結(jié)果。(大家可以自行百度嘗試其他方法和各種時(shí)區(qū)切換和時(shí)令切換測(cè)試)。
最后只能靠自己了。我回想為什么會(huì)出現(xiàn)導(dǎo)致時(shí)區(qū)的問題,并且一想,不管系統(tǒng)的時(shí)間怎么變,他都在相應(yīng)時(shí)區(qū)內(nèi)變化。一旦超過,就自動(dòng)出現(xiàn)時(shí)區(qū)也不對(duì)了。所以這個(gè)問題就非常簡單了。只需改一個(gè)地方就解決:
public static String getTimeZone() {
??????? String timezone ;
// 這里注釋的是之前獲取到的時(shí)區(qū),但是不分夏令時(shí)和冬令時(shí)(格林威治時(shí)間劃分的)
//??????? int _t = TimeZone.getDefault().getRawOffset() / (3600 * 1000);
//???????? 改為如下,獲取系統(tǒng)的時(shí)間并且計(jì)算出時(shí)區(qū)就可以了
??????? int _t = TimeZone.getDefault().getOffset(System.currentTimeMillis()) / (3600 * 1000);
timezone = String.valueOf(_t);
timezone = "GMT" + timezone;
??????? return timezone;
}
好了,這樣就解決了同一個(gè)時(shí)區(qū),因?yàn)橄奶旌投欤辉谕粋€(gè)時(shí)區(qū)的問題。就解決了不管怎么切換時(shí)區(qū),都能拿到改時(shí)間應(yīng)該所在的時(shí)區(qū)的問題了。
更多問題討論QQ:578161213。