詳解Java中的時(shí)區(qū)類(lèi)TimeZone的用法
一、TimeZone 簡(jiǎn)介
TimeZone 表示時(shí)區(qū)偏移量,也可以計(jì)算夏令時(shí)。
在操作 Date, Calendar等表示日期/時(shí)間的對(duì)象時(shí),經(jīng)常會(huì)用到TimeZone;因?yàn)椴煌臅r(shí)區(qū),時(shí)間不同。
下面說(shuō)說(shuō)TimeZone對(duì)象的 2種常用創(chuàng)建方式。
1.獲取默認(rèn)的TimeZone對(duì)象
使用方法:
TimeZone tz = TimeZone.getDefault()
2.使用 getTimeZone(String id) 方法獲取TimeZone對(duì)象
使用方法:
// 獲取 “GMT+08:00”對(duì)應(yīng)的時(shí)區(qū)
TimeZone china = TimeZone.getTimeZone("GMT+:08:00");
// 獲取 “中國(guó)/重慶”對(duì)應(yīng)的時(shí)區(qū)
TimeZone chongqing = TimeZone.getTimeZone("Asia/Chongqing");
關(guān)于 getTimeZone(String id) 這種方式支持的全部id參數(shù)的取值,可以通過(guò)以下方式查找:
String[] ids = TimeZone.getAvailableIDs(); for (String id:ids) System.out.printf(id+", ");
輸出結(jié)果:
Etc/GMT+12, Etc/GMT+11, Pacific/Midway, Pacific/Niue ....等等
TimeZone tz = TimeZone.getTimeZone("Etc/GMT+11");
TimeZone的函數(shù)接口
// 構(gòu)造函數(shù)
Object clone() synchronized static String[] getAvailableIDs() synchronized static String[] getAvailableIDs(int offsetMillis) int getDSTSavings() synchronized static TimeZone getDefault() final String getDisplayName(Locale locale) String getDisplayName(boolean daylightTime, int style, Locale locale) final String getDisplayName() final String getDisplayName(boolean daylightTime, int style) String getID() abstract int getOffset(int era, int year, int month, int day, int dayOfWeek, int timeOfDayMillis) int getOffset(long time) abstract int getRawOffset() synchronized static TimeZone getTimeZone(String id) boolean hasSameRules(TimeZone timeZone) abstract boolean inDaylightTime(Date time) synchronized static void setDefault(TimeZone timeZone) void setID(String id) abstract void setRawOffset(int offsetMillis) abstract boolean useDaylightTime()
二、TimeZone示例:
下面通過(guò)示例演示在Date中使用TimeZone。
參考代碼如下(TimeZoneTest.java):
import java.text.DateFormat;
import java.util.Date;
import java.util.TimeZone;
/**
* TimeZone的測(cè)試程序
*/
public class TimeZoneTest {
public static void main(String[] args) {
// 測(cè)試創(chuàng)建TimeZone對(duì)象的3種方法
showUsageOfTimeZones() ;
// 測(cè)試TimeZone的其它API
testOtherAPIs() ;
// 打印getTimeZone(String id)支持的所有id
//printAllTimeZones() ;
}
/**
* 測(cè)試創(chuàng)建TimeZone對(duì)象的3種方法
*/
public static void showUsageOfTimeZones() {
TimeZone tz;
// (01) 默認(rèn)時(shí)區(qū)
tz = TimeZone.getDefault();
printDateIn(tz) ;
// (02) 設(shè)置時(shí)區(qū)為"GMT+08:00"
tz = TimeZone.getTimeZone("GMT+08:00");
printDateIn(tz) ;
// (03) 設(shè)置時(shí)區(qū)為""
tz = TimeZone.getTimeZone("Asia/Chongqing");
printDateIn(tz) ;
}
/**
* 打印 tz對(duì)應(yīng)的日期/時(shí)間
*/
private static void printDateIn(TimeZone tz) {
// date為2013-09-19 14:22:30
Date date = new Date(113, 8, 19, 14, 22, 30);
// 獲取默認(rèn)的DateFormat,用于格式化Date
DateFormat df = DateFormat.getInstance();
// 設(shè)置時(shí)區(qū)為tz
df.setTimeZone(tz);
// 獲取格式化后的字符串
String str = df.format(date);
System.out.println(tz.getID()+" :"+str);
}
/**
* 測(cè)試TimeZone的其它API
*/
public static void testOtherAPIs() {
// 默認(rèn)時(shí)區(qū)
TimeZone tz = TimeZone.getDefault();
// 獲取“id”
String id = tz.getID();
// 獲取“顯示名稱(chēng)”
String name = tz.getDisplayName();
// 獲取“時(shí)間偏移”。相對(duì)于“本初子午線”的偏移,單位是ms。
int offset = tz.getRawOffset();
// 獲取“時(shí)間偏移” 對(duì)應(yīng)的小時(shí)
int gmt = offset/(3600*1000);
System.out.printf("id=%s, name=%s, offset=%s(ms), gmt=%s\n",
id, name, offset, gmt);
}
/**
* 打印getTimeZone(String id)支持的所有id
*/
public static void printAllTimeZones() {
String[] ids = TimeZone.getAvailableIDs();
for (String id:ids) {
//int offset = TimeZone.getTimeZone(avaIds[i]).getRawOffset();
//System.out.println(i+" "+avaIds[i]+" "+offset / (3600 * 1000) + "\t");
System.out.printf(id+", ");
}
System.out.println();
}
}
三、關(guān)于TimeZone和時(shí)間校準(zhǔn)
涉及有關(guān)時(shí)間區(qū)域信息時(shí)Java和Solaris很相似。每個(gè)時(shí)間區(qū)域都有一個(gè)時(shí)間區(qū)域ID標(biāo)識(shí)符。在J2SE 1.3 and 1.4中,這個(gè)ID是個(gè)字符串,是由位于J2SE 安裝程序的jre/lib子目錄中的tzmappings文件這些ID列表。 J2SE 1.3 僅僅只包含tzmappings文件,但是 J2SE 1.4包含世界不同地區(qū)的時(shí)間區(qū)域數(shù)據(jù)文件。jre/lib/zi存放著這些文件。在J2SE 1.4里,sun.util.calendar.ZoneInfo從這些文件獲取DST規(guī)則。在Solaris中, 這些時(shí)間區(qū)域數(shù)據(jù)文件是以二進(jìn)制形式存放的,不是文本文件,因此你不能看它們。 在J2SE 1.4中的時(shí)間區(qū)域數(shù)據(jù)文件和在Solaris中是不同的。
java.util.TimeZone類(lèi)中g(shù)etDefault方法的源代碼顯示,它最終是會(huì)調(diào)用sun.util.calendar.ZoneInfo類(lèi)的getTimeZone 方法。這個(gè)方法為需要的時(shí)間區(qū)域返回一個(gè)作為ID的String參數(shù)。這個(gè)默認(rèn)的時(shí)間區(qū)域ID是從 user.timezone (system)屬性那里得到。如果user.timezone沒(méi)有定義,它就會(huì)嘗試從user.country和java.home (System)屬性來(lái)得到ID。 如果它沒(méi)有成功找到一個(gè)時(shí)間區(qū)域ID,它就會(huì)使用一個(gè)"fallback" 的GMT值。換句話說(shuō), 如果它沒(méi)有計(jì)算出你的時(shí)間區(qū)域ID,它將使用GMT作為你默認(rèn)的時(shí)間區(qū)域。
注意,System屬性是在java.lang.System類(lèi)的initProperties方法中被初始化的。這是一個(gè)本地方法。因此源代碼是不可用的----除非你深入到J2SE分發(fā)包中的本地代碼庫(kù)中去研究。然而,在Windows系統(tǒng)中,System 屬性是從Windows注冊(cè)表中被初始化的,而在Linux/Unix中是由環(huán)境變量來(lái)進(jìn)行初始化。initProperties方法的Javadoc聲明,某些屬性"必須保證被定義" 且列出它們。被java.util.TimeZone類(lèi)的getDefault方法使用的三個(gè)System屬性中,只有java.home作為一種“保證的”屬性在Javadoc中被列出。
推薦的解決方案 :
因此,你如何確保JAVA能給你正確的時(shí)間和日期呢?最好的辦法是確認(rèn)JAVA虛擬機(jī)(JVM)的默認(rèn)TimeZone類(lèi)是正確的,且是適合你的地理范圍(Locale)的。你如何來(lái)確保默認(rèn)TimeZone是正確的且適合的呢?這又是一個(gè)新問(wèn)題了。象大多數(shù)處理的問(wèn)題一樣,這個(gè)也有許多解決方案。根據(jù)java.util.TimeZone.getDefault方法的源代碼來(lái)看,最好的辦法是正確地設(shè)置user.timezone屬性。在啟動(dòng)JAVA虛擬機(jī)時(shí),你能很容易的通過(guò)使用 -D 命令 -line 參數(shù)的辦法來(lái)覆蓋(override)在java.lang.System.initProperties方法中所設(shè)置的值。例如:
java -Duser.timezone=Asia/Shanghai DateTest
這個(gè)命令啟動(dòng)DateTest類(lèi),并設(shè)置 user.timezone屬性到Asia/Shanghai。你也能夠通過(guò)使用java.lang.System 類(lèi)的setProperty方法來(lái)設(shè)置user.timezone 屬性:
System.setProperty("user.timezone","Asia/Shanghai");
如果沒(méi)有一個(gè)可用的時(shí)間區(qū)域ID適合你,那么就你可以創(chuàng)建一個(gè)自定義TimeZone 使用java.util.TimeZone 類(lèi)的 setDefault 方法將它設(shè)置為默認(rèn)的時(shí)間區(qū)域----就象我先前在ItsInitializer 類(lèi)中所做的操作一樣。
記住,在J2SE中,大多數(shù)日期和時(shí)間相關(guān)的類(lèi)都包含時(shí)間區(qū)域信息,包括那些格式類(lèi),如java.text.DateFormat, 因此它們都會(huì)被JVM的默認(rèn)時(shí)間區(qū)域所影響。然而,在你創(chuàng)建這些類(lèi)的實(shí)例時(shí),你能為它們確保正確的時(shí)間區(qū)域信息,使得你可以更容易來(lái)設(shè)置整個(gè)JVM的默認(rèn)時(shí)間區(qū)域。并且一旦設(shè)置好,就可以確保所有的這些類(lèi)都將使用同一個(gè)默認(rèn)的時(shí)間區(qū)域。
- Java timezone設(shè)置和mybatis連接數(shù)據(jù)庫(kù)時(shí)區(qū)設(shè)置方式
- 詳解Java時(shí)區(qū)處理之Date,Calendar,TimeZone,SimpleDateFormat
- Java對(duì)世界不同時(shí)區(qū)timezone之間時(shí)間轉(zhuǎn)換的處理方法
- Java Timezone類(lèi)常見(jiàn)問(wèn)題_動(dòng)力節(jié)點(diǎn)Java學(xué)院整理
- java使用TimeZone將中國(guó)標(biāo)準(zhǔn)時(shí)間轉(zhuǎn)成時(shí)區(qū)值
相關(guān)文章
Java對(duì)世界不同時(shí)區(qū)timezone之間時(shí)間轉(zhuǎn)換的處理方法
這篇文章主要介紹了Java對(duì)世界不同時(shí)區(qū)timezone之間時(shí)間轉(zhuǎn)換的處理方法,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2020-07-07
簡(jiǎn)單講解java中throws與throw的區(qū)別
這篇文章主要介紹了簡(jiǎn)單講解java中throws與throw的區(qū)別,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2020-07-07
springboot框架中如何整合mybatis框架思路詳解
這篇文章主要介紹了springboot框架中如何整合mybatis框架,本文通過(guò)示例圖文相結(jié)合給大家介紹的非常詳細(xì),需要的朋友可以參考下2022-12-12
Tomcat?8.5?+mysql?5.7+jdk1.8開(kāi)發(fā)JavaSE的金牌榜小項(xiàng)目
這篇文章主要介紹了Tomcat?8.5?+mysql?5.7+jdk1.8開(kāi)發(fā)JavaSE的金牌榜小項(xiàng)目,本文通過(guò)圖文實(shí)例相結(jié)合給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2022-05-05
SpringBoot和Redis實(shí)現(xiàn)Token權(quán)限認(rèn)證的實(shí)例講解
這篇文章主要介紹了SpringBoot和Redis實(shí)現(xiàn)Token權(quán)限認(rèn)證的實(shí)例講解,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2021-02-02

