引子:(转载请注明出处)
今天测试人员向我报了个诡异的bug。在local跑程序的时候 webbrowser的time zone经过服务器端解析后,可以正确的得到GMT+8(Beijing),但是,一旦放到服务器上,跑出来的结果就变成了GMT+7。
开始百思不得其解,后来想想,会不会是夏令时(daylight saving time)引发的问题。
系统将client timezone转换为server 的TimeZone的流程:
1.new Date().getTimezoneOffset()取得browser的offset,并提交
2.服务器端接收到,并转换
int rawOffset = new Date().getTimezoneOffset() * (-1) * 60 * 1000
然后用TimeZone.getTimeZone(TimeZone.availableID)一个个去匹配。
上面两步都会产生daylight saving的误差。
服务器端的解决方案:
根据jdk上所说
1.如果是GMT+(-)xx这种去创建TimeZone,则不会考虑dsv的问题。
2.getRawOffset始终返回不含Dsv的值。
那么,在接收到客户端的offset后
只要offset / -60就可以得到GMT+xx的xx。
客户端的解决方案:
由于夏时令永远是往前播一个小时之类的。所以只需要:
var clientTimeZone = getTimeZone(); alert(clientTimeZone.displayName); alert(clientTimeZone.useDaylightTime); alert(clientTimeZone.inDayLightTime); function getTimeZone() { var date = new Date(); var offset = date.getTimezoneOffset(); date.setDate(1); var dayLightTime = false; var inDayLightTime = false; for (var month = 0; month < 12; month++) { date.setMonth(month); var currentMonthOffset = date.getTimezoneOffset(); if (offset != currentMonthOffset) { dayLightTime = true; if (offset < currentMonthOffset) { offset = currentMonthOffset; inDayLightTime = true; } } } var dispName = "GMT"; var offsetHour = offset / -60; if (offsetHour >= 0) { dispName += "+"; } dispName += offsetHour; return { // 时区名 displayName: dispName, // 和标准的偏移时间 rawOffset: offset, // 是否用了夏时令 useDaylightTime: dayLightTime, // 是否在夏时令的范围内 inDayLightTime: inDayLightTime }; }
即可取得时区名,和标准UTC的offset,是否用了夏时令,现在是否在夏时令的范围内。