有个ticket是关于time zone的,在本地测总是ok的,但是在国外客户那边总是fail,原来就是在获取time zone的方法中,在不同的环境中,取得time zone是不一样的。
比如这个time zone是中国的,
TimeZone timeZone = TimeZone.getTimeZone("Asia/Shanghai");
Calendar cal = CalendarFactoryUtil.getCalendar(timeZone);
cal .set(Calendar.MONTH, 5);
cal .set(Calendar.DATE, 12);
cal .set(Calendar.YEAR, 2013);
cal .set(Calendar.HOUR_OF_DAY, 10);
cal .set(Calendar.MINUTE, 0);
这个当前时间 cal 的timezone就是中国的。 GMT +8
但是 cal.getTime() 确不一定是取得是中国timezone的时间, 这得根据这段code运行的web 容器的jvm timezone来决定的。
比如jvm的timezone是"Europe Paris" GMT+1,
cal.getTime()的值就是2013-5-12 3:00:00 (10 - 7)
jvm设置的timezone. 在bin目录下setenv.bat文件中,-Duser.timezone=, 如果不设,就默认是当前jvm机器系统的timezone。
TimeZoneUtil.getDefault() 取得portal timezone。
CalendarFactoryUtil.getCalendar().getTimeZone 取得的是jvm的timezone。
TimeZone.getDefault() 取得是 当前jvm的timezone,如果jvm没有设置,就是操作系统的time zone。
关键点就是你要知道这个获得timezone 是来自哪里。
那如何从源码知道方法是从什么地方获取time zone的呢? 且听下回分解。
源码分析1:
TimeZoneUtil.getDefault() -->
private TimeZone getDefault() {
TimeZone timeZone = TimeZoneThreadLocal.getDefaultTimeZone();
if (timeZone != null) {
return timeZone;
}
return _timeZone; // TimeZone.getTimeZone("UTC");
}
-->
在Tomcat启动阶段初始化Company时:
LocaleThreadLocal.setDefaultLocale(company.getLocale());
// 可以看出,设置的是portal级别的time zone,所以TimeZoneUtil.getDefault取portal time zone.
TimeZoneThreadLocal.setDefaultTimeZone(company.getTimeZone());
在TimeZoneThreadLocal类中,用ThreadLocal来存放default time zone. 是因为在初始化多个Company时,
会有线程安全问题。
String[] webIds = PortalInstances.getWebIds();
for (String webId : webIds) {
PortalInstances.initCompany(servletContext, webId);
}
源码分析2:
为什么TimeZone.getDefault()获取的是jvm的timezone。
String zoneID = AccessController.doPrivileged(new GetPropertyAction("user.timezone"));
可以看到是从jvm的启动参数user.timezone 来获取的。
if (zoneID == null || zoneID.equals("")) { //如果,jvm中没有设置timezone参数
String country = AccessController.doPrivileged(
new GetPropertyAction("user.country"));
String javaHome = AccessController.doPrivileged(
new GetPropertyAction("java.home"));
try {
zoneID = getSystemTimeZoneID(javaHome, country);//它就会取操作系统的timezone
if (zoneID == null) {
zoneID = GMT_ID; // 如果还是获取不到,就默认是GMT timezone
}
} catch (NullPointerException e) {
zoneID = GMT_ID;
}
}