最近项目中实现了一个课程表的功能,核心功能如下:
1、需要记录一周里每天每个时段的课程安排,后台录入
2、课程开始前,需要自动给课程关注者以各种提醒
于是采用了这样的实现方案:
1、录入时间只记录当天的时分秒对应的毫秒数(这样入库的时间实际上是1970-01-01 HH:mm:ss)
2、定时任务根据当天所在的周数查询当天的课程安排,并将课程时间换算成当天的时间(2015-09-08 HH:mm:ss),然后执行提醒的业务
很简单的一个功能,但是因为时区问题出现了以下奇葩现象:
比如1970-01-01 10:00:00被最终换算成了1970-01-01 10:30:00
也就是说每一个入库时间取出后都增加了不多不少半个小时
于是开始看java.util.Date源码,一探究竟,发现有这样一段:
BaseCalendar cal = getCalendarSystem(year);
if (tzoffset == -1) { // no time zone specified, have to use local
BaseCalendar.Date ldate = (BaseCalendar.Date) cal.newCalendarDate(TimeZone.getDefaultRef());
注意到TimeZone.getDefaultRef(),源码如下:
public static TimeZone getDefault() {
return (TimeZone) getDefaultRef().clone();
}
/**
* Returns the reference to the default TimeZone object. This
* method doesn't create a clone.
*/
static TimeZone getDefaultRef() {
TimeZone defaultZone = defaultZoneTL.get();
if (defaultZone == null) {
defaultZone = defaultTimeZone;
if (defaultZone == null) {
// Need to initialize the default time zone.
defaultZone = setDefaultZone();
assert defaultZone != null;
}
}
// Don't clone here.
return defaultZone;
}
推测很有可能问题出在时区的选择设置上,于是打印出来结果如下:
sun.util.calendar.ZoneInfo[id="Asia/Harbin",offset=28800000,dstSavings=0,useDaylight=false,transitions=19,lastRule=null]
果然如此,服务器时区错误,于是指出这个错误,让运维修正的。
不过还是担心运维层面带来类似的错误,于是手动设置了时区:
TimeZone.setDefault(TimeZone.getTimeZone("Asia/Shanghai"));
logger.info("the default timezone info [{}]", TimeZone.getDefault());
技术文章收藏站点