一、TimeZone 簡介
TimeZone 表示時區偏移量,也可以計算夏令時。
在操作 Date, Calendar等表示日期/時間的對象時,經常會用到TimeZone;因為不同的時區,時間不同。
下面說說TimeZone對象的 2種常用創建方式。
1.獲取默認的TimeZone對象
使用方法:
TimeZone tz = TimeZone.getDefault()
2.使用 getTimeZone(String id) 方法獲取TimeZone對象
使用方法:
-
// 獲取 “GMT+08:00”對應的時區
-
TimeZone china = TimeZone.getTimeZone( "GMT+:08:00");
-
// 獲取 “中國/重慶”對應的時區
-
TimeZone chongqing = TimeZone.getTimeZone( "Asia/Chongqing");
關於 getTimeZone(String id) 這種方式支持的全部id參數的取值,可以通過以下方式查找:
-
String[] ids = TimeZone.getAvailableIDs();
-
for (String id:ids)
-
System.out.printf(id+ ", ");
輸出結果:
Etc/GMT+12, Etc/GMT+11, Pacific/Midway, Pacific/Niue ....等等
-
TimeZone tz = TimeZone.getTimeZone( "Etc/GMT+11");
-
TimeZone的函數接口
-
// 構造函數
-
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示例:
下面通過示例演示在Date中使用TimeZone。
參考代碼如下(TimeZoneTest.java):
-
import java.text.DateFormat;
-
import java.util.Date;
-
import java.util.TimeZone;
-
-
/**
-
* TimeZone的測試程序
-
*/
-
public class TimeZoneTest {
-
-
public static void main(String[] args) {
-
-
// 測試創建TimeZone對象的3種方法
-
showUsageOfTimeZones() ;
-
-
// 測試TimeZone的其它API
-
testOtherAPIs() ;
-
-
// 打印getTimeZone(String id)支持的所有id
-
//printAllTimeZones() ;
-
}
-
-
-
/**
-
* 測試創建TimeZone對象的3種方法
-
*/
-
public static void showUsageOfTimeZones() {
-
TimeZone tz;
-
-
// (01) 默認時區
-
tz = TimeZone.getDefault();
-
printDateIn(tz) ;
-
-
// (02) 設置時區為"GMT+08:00"
-
tz = TimeZone.getTimeZone( "GMT+08:00");
-
printDateIn(tz) ;
-
-
// (03) 設置時區為""
-
tz = TimeZone.getTimeZone( "Asia/Chongqing");
-
printDateIn(tz) ;
-
}
-
-
/**
-
* 打印 tz對應的日期/時間
-
*/
-
private static void printDateIn(TimeZone tz) {
-
// date為2013-09-19 14:22:30
-
Date date = new Date(113, 8, 19, 14, 22, 30);
-
// 獲取默認的DateFormat,用於格式化Date
-
DateFormat df = DateFormat.getInstance();
-
// 設置時區為tz
-
df.setTimeZone(tz);
-
// 獲取格式化后的字符串
-
String str = df.format(date);
-
-
System.out.println(tz.getID()+ " :"+str);
-
}
-
-
/**
-
* 測試TimeZone的其它API
-
*/
-
public static void testOtherAPIs() {
-
// 默認時區
-
TimeZone tz = TimeZone.getDefault();
-
-
// 獲取“id”
-
String id = tz.getID();
-
-
// 獲取“顯示名稱”
-
String name = tz.getDisplayName();
-
-
// 獲取“時間偏移”。相對於“本初子午線”的偏移,單位是ms。
-
int offset = tz.getRawOffset();
-
// 獲取“時間偏移” 對應的小時
-
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();
-
}
-
}
-
三、關於TimeZone和時間校准
涉及有關時間區域信息時Java和Solaris很相似。每個時間區域都有一個時間區域ID標識符。在J2SE 1.3 and 1.4中,這個ID是個字符串,是由位於J2SE 安裝程序的jre/lib子目錄中的tzmappings文件這些ID列表。 J2SE 1.3 僅僅只包含tzmappings文件,但是 J2SE 1.4包含世界不同地區的時間區域數據文件。jre/lib/zi存放着這些文件。在J2SE 1.4里,sun.util.calendar.ZoneInfo從這些文件獲取DST規則。在Solaris中, 這些時間區域數據文件是以二進制形式存放的,不是文本文件,因此你不能看它們。 在J2SE 1.4中的時間區域數據文件和在Solaris中是不同的。
java.util.TimeZone類中getDefault方法的源代碼顯示,它最終是會調用sun.util.calendar.ZoneInfo類的getTimeZone 方法。這個方法為需要的時間區域返回一個作為ID的String參數。這個默認的時間區域ID是從 user.timezone (system)屬性那里得到。如果user.timezone沒有定義,它就會嘗試從user.country和java.home (System)屬性來得到ID。 如果它沒有成功找到一個時間區域ID,它就會使用一個"fallback" 的GMT值。換句話說, 如果它沒有計算出你的時間區域ID,它將使用GMT作為你默認的時間區域。
注意,System屬性是在java.lang.System類的initProperties方法中被初始化的。這是一個本地方法。因此源代碼是不可用的----除非你深入到J2SE分發包中的本地代碼庫中去研究。然而,在Windows系統中,System 屬性是從Windows注冊表中被初始化的,而在Linux/Unix中是由環境變量來進行初始化。initProperties方法的Javadoc聲明,某些屬性"必須保證被定義" 且列出它們。被java.util.TimeZone類的getDefault方法使用的三個System屬性中,只有java.home作為一種“保證的”屬性在Javadoc中被列出。
推薦的解決方案 :
因此,你如何確保JAVA能給你正確的時間和日期呢?最好的辦法是確認JAVA虛擬機(JVM)的默認TimeZone類是正確的,且是適合你的地理范圍(Locale)的。你如何來確保默認TimeZone是正確的且適合的呢?這又是一個新問題了。象大多數處理的問題一樣,這個也有許多解決方案。根據java.util.TimeZone.getDefault方法的源代碼來看,最好的辦法是正確地設置user.timezone屬性。在啟動JAVA虛擬機時,你能很容易的通過使用 -D 命令 -line 參數的辦法來覆蓋(override)在java.lang.System.initProperties方法中所設置的值。例如:
java -Duser.timezone=Asia/Shanghai DateTest
這個命令啟動DateTest類,並設置 user.timezone屬性到Asia/Shanghai。你也能夠通過使用java.lang.System 類的setProperty方法來設置user.timezone 屬性:
System.setProperty("user.timezone","Asia/Shanghai");
如果沒有一個可用的時間區域ID適合你,那么就你可以創建一個自定義TimeZone 使用java.util.TimeZone 類的 setDefault 方法將它設置為默認的時間區域----就象我先前在ItsInitializer 類中所做的操作一樣。
記住,在J2SE中,大多數日期和時間相關的類都包含時間區域信息,包括那些格式類,如java.text.DateFormat, 因此它們都會被JVM的默認時間區域所影響。然而,在你創建這些類的實例時,你能為它們確保正確的時間區域信息,使得你可以更容易來設置整個JVM的默認時間區域。並且一旦設置好,就可以確保所有的這些類都將使用同一個默認的時間區域。
--------------------- 本文來自 earthchinagl 的CSDN 博客 ,全文地址請點擊:https://blog.csdn.net/earthchinagl/article/details/71404061?utm_source=copy