問題重現:
通過接口從後端獲取時間戳,在前端用JS格式化顯示。發現Chrome在Mac和Windows下,對特定的時間段(1986年至1991年),的處理方式並不相同。
問題產生原因:
查詢資料後發現,原來中國也曾經使用過夏令時。
1986年至1991年,中華人民共和國在全國範圍實行了六年夏令時,每年從4月中旬的第一個星期日2時整(北京時間)到9月中旬第一個星期日的凌晨2時整(北京夏令時)。除1986
年因是實行夏令時的第一年,從5月4日開始到9月14日結束外,其它年份均按規定的時段施行。1992年4月5日後不再實行。
要避免此情況可在後端對時間進行處理,返回格式化後的日期字符串。
1 |
TimeZone.setDefault(TimeZone.getTimeZone("GMT+8:00")); |
或在前端通過getTimezoneOffset檢測夏令時,嘗試網上找到的夏令時檢測算法。(不推薦)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 |
<!DOCTYPE html> <html> <head> <title>DST Calculator</title> <script type="text/javascript">
function DisplayDstSwitchDates() { var year = new Date().getYear(); if (year < 1000) year += 1900;
var firstSwitch = 0; var secondSwitch = 0; var lastOffset = 99;
// Loop through every month of the current year for (i = 0; i < 12; i++) { // Fetch the timezone value for the month var newDate = new Date(Date.UTC(year, i, 0, 0, 0, 0, 0)); var tz = -1 * newDate.getTimezoneOffset() / 60;
// Capture when a timzezone change occurs if (tz > lastOffset) firstSwitch = i-1; else if (tz < lastOffset) secondSwitch = i-1;
lastOffset = tz; }
// Go figure out date/time occurences a minute before // a DST adjustment occurs var secondDstDate = FindDstSwitchDate(year, secondSwitch); var firstDstDate = FindDstSwitchDate(year, firstSwitch);
if (firstDstDate == null && secondDstDate == null) return 'Daylight Savings is not observed in your timezone.'; else return 'Last minute before DST change occurs in ' + year + ': ' + firstDstDate + ' and ' + secondDstDate; }
function FindDstSwitchDate(year, month) { // Set the starting date var baseDate = new Date(Date.UTC(year, month, 0, 0, 0, 0, 0)); var changeDay = 0; var changeMinute = -1; var baseOffset = -1 * baseDate.getTimezoneOffset() / 60; var dstDate;
// Loop to find the exact day a timezone adjust occurs for (day = 0; day < 50; day++) { var tmpDate = new Date(Date.UTC(year, month, day, 0, 0, 0, 0)); var tmpOffset = -1 * tmpDate.getTimezoneOffset() / 60;
// Check if the timezone changed from one day to the next if (tmpOffset != baseOffset) { var minutes = 0; changeDay = day;
// Back-up one day and grap the offset tmpDate = new Date(Date.UTC(year, month, day-1, 0, 0, 0, 0)); tmpOffset = -1 * tmpDate.getTimezoneOffset() / 60;
// Count the minutes until a timezone chnage occurs while (changeMinute == -1) { tmpDate = new Date(Date.UTC(year, month, day-1, 0, minutes, 0, 0)); tmpOffset = -1 * tmpDate.getTimezoneOffset() / 60;
// Determine the exact minute a timezone change // occurs if (tmpOffset != baseOffset) { // Back-up a minute to get the date/time just // before a timezone change occurs tmpOffset = new Date(Date.UTC(year, month, day-1, 0, minutes-1, 0, 0)); changeMinute = minutes; break; } else minutes++; }
// Add a month (for display) since JavaScript counts // months from 0 to 11 dstDate = tmpOffset.getMonth() + 1;
// Pad the month as needed if (dstDate < 10) dstDate = "0" + dstDate;
// Add the day and year dstDate += '/' + tmpOffset.getDate() + '/' + year + ' '; // Capture the time stamp tmpDate = new Date(Date.UTC(year, month, day-1, 0, minutes-1, 0, 0)); dstDate += tmpDate.toTimeString().split(' ')[0]; return dstDate; } } }
</script> </head> <body> <script type="text/javascript"> document.write("Current date/time: " + new Date() + "<br />"); document.write(DisplayDstSwitchDates()); </script> </body> </html> |