详解Java中的时区类TimeZone的用法
Posted miaow
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了详解Java中的时区类TimeZone的用法相关的知识,希望对你有一定的参考价值。
一、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 ",
-
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) + " ");
-
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
以上是关于详解Java中的时区类TimeZone的用法的主要内容,如果未能解决你的问题,请参考以下文章
未来日期/年份的 Java 夏令时 (TimeZone/ZoneId) 支持
怎么实时同步java虚拟机与操作系统时区 及JVM启动后再更改操作系统时区或时间也能保持其同步? new date() 时差8个小时的解决方案