问题重现:
通过接口从后端获取时间戳,在前端用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 |
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; } } }
document.write("Current date/time: " + new Date() + " document.write(DisplayDstSwitchDates());
|