最近項(xiàng)目中實(shí)現(xiàn)了一個(gè)課程表的功能,核心功能如下:
1、需要記錄一周里每天每個(gè)時(shí)段的課程安排,后臺(tái)錄入
2、課程開(kāi)始前,需要自動(dòng)給課程關(guān)注者以各種提醒
于是采用了這樣的實(shí)現(xiàn)方案:
1、錄入時(shí)間只記錄當(dāng)天的時(shí)分秒對(duì)應(yīng)的毫秒數(shù)(這樣入庫(kù)的時(shí)間實(shí)際上是1970-01-01 HH:mm:ss)
2、定時(shí)任務(wù)根據(jù)當(dāng)天所在的周數(shù)查詢當(dāng)天的課程安排,并將課程時(shí)間換算成當(dāng)天的時(shí)間(2015-09-08 HH:mm:ss),然后執(zhí)行提醒的業(yè)務(wù)
很簡(jiǎn)單的一個(gè)功能,但是因?yàn)闀r(shí)區(qū)問(wèn)題出現(xiàn)了以下奇葩現(xiàn)象:
比如1970-01-01 10:00:00被最終換算成了1970-01-01 10:30:00
也就是說(shuō)每一個(gè)入庫(kù)時(shí)間取出后都增加了不多不少半個(gè)小時(shí)
于是開(kāi)始看java.util.Date源碼,一探究竟,發(fā)現(xiàn)有這樣一段:
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;
}
推測(cè)很有可能問(wèn)題出在時(shí)區(qū)的選擇設(shè)置上,于是打印出來(lái)結(jié)果如下:
sun.util.calendar.ZoneInfo[id="Asia/Harbin",offset=28800000,dstSavings=0,useDaylight=false,transitions=19,lastRule=null]
果然如此,服務(wù)器時(shí)區(qū)錯(cuò)誤,于是指出這個(gè)錯(cuò)誤,讓運(yùn)維修正的。
不過(guò)還是擔(dān)心運(yùn)維層面帶來(lái)類(lèi)似的錯(cuò)誤,于是手動(dòng)設(shè)置了時(shí)區(qū):
TimeZone.setDefault(TimeZone.getTimeZone("Asia/Shanghai"));
logger.info("the default timezone info [{}]", TimeZone.getDefault());
技術(shù)文章收藏站點(diǎn)