一、問題描述
當軟件需要國際化的時候,我們不得不考慮時間的問題。不同的地方有不同的時區(qū),從而顯示的時間是不一樣的。而且很多國家在某一段時間還可能會實行夏令時,顯示的時間又不一樣。為了保證時間的正確性,必須有統(tǒng)一的基線,從而不得不考慮下列時間之間的轉(zhuǎn)換。
a、long timeToUTC(time,timezone) //把給定的時間根據(jù)給定的時區(qū)轉(zhuǎn)化為UTC
b、String UTCToTime(long,timezone) //把給定的UTC轉(zhuǎn)化為制定時區(qū)的時間
c、timeToTime(time,timezone1,timezone2) //把給定的時間根據(jù)制定的時區(qū)轉(zhuǎn)化為另指定時區(qū)的時間
//考慮到數(shù)據(jù)的存儲,還必須考慮數(shù)據(jù)庫對于時間字段的格式。
二、解決方法
顯示時間的不同,主要原因的是時區(qū)不同。如果不考慮自定義時區(qū)的問題,JODA包就能很好解決上面的問題,但是如果考慮自定義時區(qū)(很多軟件由于考慮夏令時,從而增加了自定義時區(qū)的功能來設(shè)置夏令時),則我們必須自己來寫轉(zhuǎn)換函數(shù)。
a、JODA
1
public long timeToUTC(String theSourceTime, int sourceWbxTZID)
2
throws Exception
{
3
DateTime targDate;
4
if (sourceWbxTZID == (-1))
{ //UTC
5
//mdyFormatter:org.joda.time.format.DateTimeFormatter
6
targDate = mdyFormatter.withZone(DateTimeZone.UTC).parseDateTime(theSourceTime);//
7
} else
{
8
targDate = mdyFormatter.withZone(
9
DateTimeZone.forID(convertTimezone(sourceWbxTZID)))
10
.parseDateTime(theSourceTime);
11
}
12
return targDate.getMillis();
13
}
14
public String UTCToTime(long theUTCTime, int targetWbxTZID)
15
throws Exception
{
16
DateTime theSourceTime = new DateTime(theUTCTime);
17
if (targetWbxTZID == (-1))
{
18
return mdyFormatter.withZone(DateTimeZone.UTC).print(theSourceTime);
19
} else
{
20
return mdyFormatter.withZone(
21
DateTimeZone.forID(convertTimezone(targetWbxTZID))).print(
22
theSourceTime);
23
}
24
}
b、自編寫
1
/** *//**
2
*sourceDate:需要轉(zhuǎn)換的日期,此日期必須是居于GMT的時間。
3
*timezone:
4
*gMT:是否是GMT時間
5
*isConsiderDayLight:是否考慮夏令時
6
*/
7
private long convert(Date sourceDate, Timezone timezone, boolean gMT, boolean isConsiderDayLight) throws Exception
{
8
int gMTOffSet = (int) timezone.getGmtOffset();//獲取偏移量
9
long sourceTime = sourceDate.getTime();
10
if (gMT)
{
11
targetTime = sourceTime + gMTOffSet * 60 * 1000;
12
} else
{
13
targetTime = sourceTime + ( -1) * gMTOffSet * 60 * 1000;//北京偏移8個小時,如是:-8*60*1000
14
}
15
//下面是考慮夏令時
16


17
return targetTime;
18
19
}
20
public long timeToUTC(String theSourceTime, int sourceWbxTZID)
21
throws Exception
{
22
SimpleDateFormat sdf = new SimpleDateFormat("MM/dd/yyyy HH:mm:ss");
23
sdf.setTimeZone(TimeZone.getTimeZone("GMT"));
24
Date date=sdf.parse(theSourceTime);
25
Timezone timezone=(Timezone)keyedByWbxTZID.get(String.valueOf(sourceWbxTZID));//此函數(shù)主要是獲取Timezone相關(guān)的數(shù)據(jù)
26
return convert(date,timezone,false,true);
27
}
28
public String UTCToTime(long theUTCTime, int targetWbxTZID)
29
throws Exception
{
30
Date date=new Date();
31
date.setTime(theUTCTime);
32
Timezone timezone=(Timezone)keyedByWbxTZID.get(String.valueOf(targetWbxTZID));//此函數(shù)主要是獲取Timezone相關(guān)的數(shù)據(jù)
33
long time=convert(date,timezone,true,true);
34
SimpleDateFormat sdf = new SimpleDateFormat("MM/dd/yyyy HH:mm:ss");
35
sdf.setTimeZone(TimeZone.getTimeZone("GMT"));
36
return sdf.format(new Date(time));
37
}
三、相關(guān)的一些時間概念
GMT:就是格林威治標準時間的英文縮寫,格林威治是倫敦泰晤士河南岸的一個地方,由于從19世紀開始,因為世界各國來往頻繁,而歐洲大陸、美洲大陸和亞洲大陸都有各自的時區(qū),所以為免混亂,各國的代表就在1884 年在美國華盛頓召開了國際大會,通過協(xié)議選出倫敦的格林威治,作為全球時間的中心點,格林威治標準時間因而誕生。所以有GMT功能的腕表就是說腕表擁有其中的小時表盤可以顯示GMT時間。
UTC:短波傳送很遠,可能經(jīng)過許多國家、許多不同時區(qū),所以需要有一統(tǒng)時間作標準, 這個標準時間Co-ordinated Universal Time 縮寫UTC 或稱 UT。過去稱為格林威治時間(GMT),雖然有些地方有冬令時間或夏令時間,但UTC時間是不會改的,大家都以它為標準。
DST:Daylight saving time .(夏令時,各個國家開始和結(jié)束時間的計算方法是不一樣的)
美國,加拿大夏令時起止時間:每年3月份第二個星期天到11月份第一個星期天(亞利桑那州、夏威夷、波多黎各、維爾京群島和美屬薩摩亞除外)。
德國、意大利等多數(shù)歐洲國家夏令時起止時間:每年3月份最后一個星期天到10月份最后一個星期天。
MST:Mountain Standard Time
PST:Pacific Standard Time
EST:Eastern Standard Time
很多朋友對于美劇官方網(wǎng)站上的時間表達方式不是很理解。
這里說明一下,以Prison Break為例:Monday 8/7c
它指的是:星期一 東部時間8點 中部時間7點。兩地同時播放,不過因為時差問題,鐘表上顯示的時間有一個小時的差別。
盡管官網(wǎng)的播放時間對于美國以外的朋友來說意義不大,不過如果你愿意查出相對應(yīng)的北京時間,可以使用http://www.worldtimeserver.com 的服務(wù),我相信國內(nèi)也有很多類似的時間轉(zhuǎn)換網(wǎng)站,包括google,百度都可以,這里就不再羅嗦了。至少目前來說,美東時間和北京時間相差12小時,也就是說,我們比美東快12個小時。Prison Break的播放時間就是北京時間第二天的早上8點,也就是星期二 8:00AM.
相對于美國,我們國家的時區(qū)劃分相對簡單很多,特別是取消夏令時后,不出國,我們基本上不用考慮時差問題。
美國本土大陸地區(qū)采用的時區(qū)自東向西為:
東岸標準時區(qū) (Eastern Standard Time; EST; UTC-5; R區(qū)),包括大西洋沿岸各州、墨西哥灣及密西西比河以東地區(qū)。
中部標準時區(qū) (Central Standard Time; CST; UTC-6; S區(qū)),包括密西西比河沿岸以及以西州份的大部份。
山部標準時區(qū) (Mountain Standard Time; MST; UTC-7; T區(qū)), 沿大陸分水嶺—洛磯山一線的州份、大盆地及科羅拉多河流淢。
太平洋標準時區(qū) (Pacific Standard Time; PST; UTC-8; U區(qū)),包括太平洋沿岸地區(qū)及內(nèi)華達州。
美國本土大陸地區(qū)以外地區(qū)采用的時區(qū)
阿拉斯加標準時區(qū) (Alaska Standard Time; AKST; UTC-9; V區(qū)) 包括阿拉斯加州大部份地區(qū)。
夏威夷—阿留申時區(qū) (Hawaii-Aleutian Standard Time,非正式:夏威夷標準時 Hawaii Standard Time; HST; UTC-10; W區(qū)),包括夏威夷州及169°30'W以西的阿留申群島。
美國屬土采用的時區(qū)
大西洋標準時區(qū) (Atlantic Standard Time; AST, UTC-4; Q區(qū)) 包括波多黎各及美屬處女島。
薩摩亞時區(qū) (Samoa Standard Time; UTC-11, X區(qū))包括美屬薩摩亞。
查莫羅時區(qū) (Chamorro Standard Time; UTC+10, Zone K)包括關(guān)島及北馬里亞納群島。
中國的時區(qū):我們使用北京時間,以前稱中原標準時間,現(xiàn)在臺灣依然使用這個名稱,是中國大陸、香港、澳門和臺灣的標準時間。在時區(qū)劃分上,屬東八區(qū),比世界協(xié)調(diào)時早8小時,記為UTC+8。
嚴格地講,北京時間并不是北京(東經(jīng)116°)地方的時間,而是東經(jīng)120°度地方的地方時間。而北京時間也不是在北京確定的,而是由位于中國版圖幾何中心位置陜西臨潼的中國科學(xué)院國家授時中心的9臺銫原子鐘和2臺氫原子鐘組通過精密比對和計算實現(xiàn),并通過衛(wèi)星與世界各國授時部門進行實時比對。
清光緒28年(公元1902年),中國海關(guān)曾制定海岸時,以東經(jīng)120度之時刻為標準。公元1912年,位于北京的中央觀象臺將全國分為五個時區(qū),民國28年3月9日中華民國內(nèi)政部召集標準時間會議,確認1912年劃分之時區(qū)為中華民國標準時區(qū)。分別為:
1昆侖時區(qū) UTC+5.5 新疆西部與部分西藏
2新藏時區(qū) UTC+6 新疆及西藏
3隴蜀時區(qū) UTC+7 中國中部
4中原標準時區(qū) UTC+8 中國海岸
5長白時區(qū) UTC+9 中國東北
1949年之后,中國大陸將“中原標準時間”改稱“北京時間”,并在全國統(tǒng)一使用該時間作為標準時間。臺灣則維持“中原標準時間”之名稱,也有稱“臺北時間”或“國家標準時間”。
由于中國大陸全境都采用北京時間作為標準時,因此在中國西部的陜西、甘肅、新疆等省和自治區(qū)造成了生活不便,比如在烏魯木齊,北京時間比當?shù)貢r間提前兩個小時,北京時間早8時30分(中國大陸公務(wù)機關(guān)通行的上班時間)相當于當?shù)貢r間早晨6時30分。作為解決措施,一些新疆地區(qū)居民使用烏魯木齊時間,即東六區(qū)(UTC+6)時間。
2005年,一些中華人民共和國全國人民代表大會代表提出將中國大陸時區(qū)加以細分的建議,提議分為以北京時間為基礎(chǔ)的東部時間(UTC+8)、以陜西地區(qū)時間為基礎(chǔ)的中部時間(UTC+7)和以新疆、西藏地區(qū)時間為基礎(chǔ)的西部時間(UTC+6)。后又將該提議改為分為兩個時區(qū),即UTC+8和UTC+7兩個時區(qū),陜西、四川、重慶、貴州、云南及以西各省采用UTC+7的西部時間。但該提案尚未赴諸表決。