本文介紹Java API 中 Date, Calendar, TimeZone和DateFormat的使用,以及不同時區(qū)時間相互轉(zhuǎn)化的方法和原理。
問題描述:
向處于不同時區(qū)的服務(wù)器發(fā)請求時需要考慮時區(qū)轉(zhuǎn)換的問題。譬如,服務(wù)器位于東八區(qū)(北京時間,GMT+8:00),而身處東四區(qū)的用戶想要查詢當天的銷售記錄。則需把東四區(qū)的“今天”這個時間范圍轉(zhuǎn)換為服務(wù)器所在時區(qū)的時間范圍。
Tips1. GMT時間:即格林威治平時(Greenwich Mean Time)。平太陽時是與視太陽時對應(yīng)的,由于地球軌道非圓形,運行速度歲地球與太陽距離改變而出現(xiàn)變化,因此視太陽時欠缺均勻性。為了糾正這種不均勻性,天文學(xué)家計算地球非圓形軌跡與極軸傾斜對視太陽時的效應(yīng)。平太陽時就是指經(jīng)修訂之后的視太陽時。在格林威治子午線上的平太陽時稱為世界時(UTC),又叫格林威治平時(GMT)。
類Date表示特定的瞬間,精確到毫秒。獲得一個表示當前時間的Date對象有兩種方式:
Date對象本身所存儲的毫秒數(shù)可以通過date.getTime()方法得到;該函數(shù)返回自1970年1月1日 00:00:00 GMT以來此對象表示的毫秒數(shù)。
Calendar的getInstance()方法有參數(shù)為TimeZone和Locale的重載,可以使用指定時區(qū)和語言環(huán)境獲得一個日歷。無參則使用默認時區(qū)和語言環(huán)境獲得日歷。
TimeZone表示時區(qū)偏移量,本質(zhì)上以毫秒數(shù)保存與GMT的差值。獲取TimeZone可以通過時區(qū)ID,如"America/New_York",也可以通過GMT+/-hh:mm來設(shè)定。例如北京時間可以表示為GMT+8:00。
TimeZone.getRawOffset()方法可以用來得到當前時區(qū)的標準時間到GMT的偏移量。上段提到的"America/New_York"和"GMT+8:00"兩個時區(qū)的偏移量分別為-18000000和28800000。
于是問題就簡單了,在時區(qū)間轉(zhuǎn)換時間時,首先用原時間減掉原時間所在時區(qū)相對于GMT的偏移量,得到原時間相對與GMT的值,再加上目標時區(qū)相對GMT的偏移量即可。
這樣得到的結(jié)果依然是毫秒數(shù),需要按照指定日期格式重新轉(zhuǎn)換成Date對象。
Tips2. 字面大數(shù)字賦值給long類型變量的問題
上面函數(shù)中的targetTime是計算得來的,測試用例中我們可能需要通過毫秒數(shù)來構(gòu)建幾個日期對象,但是在賦值long time = 1374004799999 時會提示錯誤“The literal1374004799999 of type int is out of range”。代碼中的數(shù)字字面值是int類型,因此超出了長度。在大數(shù)字后面加個'L',long time = 1374004799999L即可正確賦值。
DateFormat是是日期/時間格式化子類的抽象類,它以與語言無關(guān)的方式格式化并解析日期或時間。日期/時間格式化子類(如 SimpleDateFormat)允許進行格式化(也就是日期 -> 文本)、解析(文本-> 日期)和標準化。將日期表示為 Date 對象,或者表示為從 GMT(格林尼治標準時間)1970 年 1 月 1 日 00:00:00 這一刻開始的毫秒數(shù)。SimpleDateFormat則是一個以與語言環(huán)境有關(guān)的方式來格式化和解析日期的具體類,可以以“日期和時間模式”字符串指定日期和時間格式。我們函數(shù)中所用模式字符串為"MM/dd/yyyy HH:mm:ss",則輸出日期:"07/16/2013 04:00:00"
其他常見的模式字母定義如下:
G | Era 標志符 | Text | AD |
y | 年 | Year | 1996 ; 96 |
M | 年中的月份 | Month | July ; Jul ; 07 |
w | 年中的周數(shù) | Number | 27 |
W | 月份中的周數(shù) | Number | 2 |
D | 年中的天數(shù) | Number | 189 |
d | 月份中的天數(shù) | Number | 10 |
F | 月份中的星期 | Number | 2 |
E | 星期中的天數(shù) | Text | Tuesday ; Tue |
a | Am/pm 標記 | Text | PM |
H | 一天中的小時數(shù)(0-23) | Number | 0 |
k | 一天中的小時數(shù)(1-24) | Number | 24 |
K | am/pm 中的小時數(shù)(0-11) | Number | 0 |
h | am/pm 中的小時數(shù)(1-12) | Number | 12 |
m | 小時中的分鐘數(shù) | Number | 30 |
s | 分鐘中的秒數(shù) | Number | 55 |
S | 毫秒數(shù) | Number | 978 |
z | 時區(qū) | General time zone | Pacific Standard Time ; PST ; GMT-08:00 |
Z | 時區(qū) | RFC 822 time zone | -0800 |
References:
1. Java API 1.6