JDK之TimeZone

本来是看到Calendar这个类的,但是发现这个类里面很多地方使用的Time Zone这个类,不是很清楚这个类的作用,所以又跑去看了一下TimeZone。
顾名思义,Time Zone这个类是用来控制时区的,时区的概念初中的时候就学过,什么美国东八区之类的,由于不同时区的时间不同,所以这个类在java时间相关的类中被大量的使用。

先看一下这个类的AP:

static String[]	getAvailableIDs()  获取所有的时区ID,时区id是一个字符串,每一个时区都有一个唯一ID,例如:Etc/GMT+10
static String[]	getAvailableIDs(int rawOffset) 根据时差来获取时区的ID,意思是有哪些时区的时差是给定的值
static TimeZone	getDefault() 获取当前机器所在的时区实例
String	getDisplayName() 获取时区的名字,如:中国标准时间
String	getDisplayName(boolean daylight, int style)
String	getDisplayName(Locale locale)
String	getDisplayName(boolean daylight, int style,Locale locale)以上三个可以根据不同的格式来获取时区的名字
int	getDSTSavings()Returns the amount of time to be added to local standard time to get local wall clock time.,这个方法不懂是干什么的。
String	getID()获取时区实例的ID
abstract int	getOffset(int era, int year, int month, int day, int dayOfWeek, int milliseconds)获取给定时间的时差
int	getOffset(long date)
abstract int	getRawOffset()
static TimeZone	getTimeZone(String ID)
boolean	hasSameRules(TimeZone other)判断给定时区和当前时区时差是否相同
boolean	observesDaylightTime()
static void	setDefault(TimeZone zone)
void	setID(String ID)
abstract void	setRawOffset(int offsetMillis)
abstract boolean	useDaylightTime()

跑个单例:

public static void main(String[] args) {
        TimeZone timeZone=TimeZone.getDefault();
        String[] ids=timeZone.getAvailableIDs();
        for (int i=0,length=ids.length;i<length;i++)
        {
            System.out.println(ids[i]);
        }
        System.out.println(timeZone.getRawOffset());
        System.out.println(timeZone.getDisplayName());
        timeZone=TimeZone.getTimeZone("Australia/Canberra");
        System.out.println(timeZone.getRawOffset());
        System.out.println(timeZone.getDisplayName());
    }
结果是:

....

时区IDS

...

28800000
中国标准时间
36000000
东部标准时间 (新南威尔斯)

这个类最终的实现肯定是需要调用到native方法的,但是目前没必要深究,知道如何使用即可。


再贴一些在其他地方看到的关于Time Zone的描述:

涉及有关时间区域信息时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方法中所设置的值。例如:

1
java -Duser.timezone=Asia /Shanghai DateTest

这个命令启动DateTest类,并设置 user.timezone属性到Asia/Shanghai。你也能够通过使用java.lang.System 类的setProperty方法来设置user.timezone 属性:

1
System.setProperty( "user.timezone" , "Asia/Shanghai" );

如果没有一个可用的时间区域ID适合你,那么就你可以创建一个自定义TimeZone 使用java.util.TimeZone 类的 setDefault 方法将它设置为默认的时间区域----就象我先前在ItsInitializer 类中所做的操作一样。

记住,在J2SE中,大多数日期和时间相关的类都包含时间区域信息,包括那些格式类,如java.text.DateFormat, 因此它们都会被JVM的默认时间区域所影响。然而,在你创建这些类的实例时,你能为它们确保正确的时间区域信息,使得你可以更容易来设置整个JVM的默认时间区域。并且一旦设置好,就可以确保所有的这些类都将使用同一个默认的时间区域。






下面是`Calendar`类的工厂方法模式的代码体现: ```java public abstract class Calendar implements Serializable, Cloneable, Comparable<Calendar> { // 省略其他代码... /** * 获取一个默认的Calendar对象。 * @return 默认的Calendar对象 */ public static Calendar getInstance() { return createCalendar(TimeZone.getDefault(), Locale.getDefault(Locale.Category.FORMAT)); } /** * 根据指定的时区和语言环境获取一个Calendar对象。 * @param zone 时区 * @param aLocale 语言环境 * @return 指定时区和语言环境的Calendar对象 */ public static Calendar getInstance(TimeZone zone, Locale aLocale) { return createCalendar(zone, aLocale); } // 省略其他代码... /** * 创建一个新的Calendar对象,具体的实现由子类实现。 * @param zone 时区 * @param aLocale 语言环境 * @return 新的Calendar对象 */ protected abstract Calendar createCalendar(TimeZone zone, Locale aLocale); // 省略其他代码... } ``` `Calendar`类中的`getInstance()`方法是一个工厂方法,它返回一个`Calendar`对象的实例。具体的实例化操作由`createCalendar()`方法在子类中实现。例如,在`GregorianCalendar`类中,`createCalendar()`方法的实现如下: ```java public class GregorianCalendar extends Calendar implements Cloneable, Serializable { // 省略其他代码... /** * 创建一个新的GregorianCalendar对象。 * @param zone 时区 * @param aLocale 语言环境 * @return 新的GregorianCalendar对象 */ @Override protected Calendar createCalendar(TimeZone zone, Locale aLocale) { return new GregorianCalendar(zone, aLocale); } // 省略其他代码... } ``` 在`GregorianCalendar`类中,`createCalendar()`方法的实现返回一个`GregorianCalendar`对象的实例。这就是工厂方法模式的体现,它把实例化操作推迟到了子类中进行,从而使得客户端代码可以通过`Calendar.getInstance()`方法来获取`Calendar`对象的实例,而不需要知道具体返回的是哪个子类的实例。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值