事件回顾:

  因为我们的产品会有与时间转换这部分,并且流量主要集中在小程序。

  emmm~  获取用户出生的年/月/日/时  我们和后台协商的是换算用户选择后的时间为  年/月/日/时/分/秒  所以我们会给用户默认时1分1秒...

  但是,因为小时的关系  部分用户反馈和浏览器产品的显示不准

  当然,接到反馈的产品当然会和我们沟通,是不是代码出了bug ?

问题复现:

  我在小程序时间选择器 选择到 1989/5/14 任意小时的时候使用 new Date(年,月-1,日,时,分,秒).getTime()  和 https://tool.lu/timestamp/ 换算回来的日期与用户竟然会有一个小时的差距...

  这我就很纳闷了,到底是什么问题...

  于是我用node跑了一个脚本

// main.js

let fs = require('fs');

let rightTime = 673023661000; // https://tool.lu/timestamp/ 取你要对比的正确的时间戳;
let year = 1991; // 对比的年份
let arr = [];
let diffArr = [];
let mon = [31,28,31,30,31,30,31,31,30,31,30,31] // 当年的月份对应的多少天
let signNum = 0;
for(let i = 0; i < 12; i++){
if(i+1 == 5){
for(let j=0; j<mon[i]; j++){
for(let k=0; k<24; k++){
let currentTime = year + '/' + (i+1) + '/' + (j+1) + '/ ' + k + ':1:1+08:00'
let getJsTime = new Date(year, i, j+1, k, 1, 1);
let obj = '\r\n' + currentTime + " ---> " + getJsTime+ "<-->" + getJsTime.getTimezoneOffset() +" ---"+ getJsTime.getTime();
diffArr.push(getJsTime.getTime())
arr.push(obj)
signNum++
}
}
}
} for(let i=0; i<arr.length; i++){
let currentComNum = rightTime + i * 1000 * 3600;
let sign = ''
if(diffArr[i] == currentComNum){
sign = 'yes'
}else{
sign = 'no';
}
arr[i] = arr[i] + '--->' + currentComNum + ' ---> ' + sign;
console.log(arr[i] + '--->' + currentComNum + ' ---> ' + sign)
} fs.writeFile('对比.txt', arr, (err) => {
if (err) throw err;
console.log('文件已保存');
});

  运行   这个js文件   node  main.js

  然后我发现 时间偏移 getJsTime.getTimezoneOffset() 这部分值一直是-480  其实读者看完可以直接跑一次就可以在main.js同级目录下看到

突然想起来Node.js和浏览器的运行环境不一样,会不会在浏览器表现不一致?所以,我只能再粘贴复制代码到浏览器 开发者工具。复制的代码去掉以下部分:

let fs = require('fs');
fs.writeFile('对比.txt', arr, (err) => {
if (err) throw err;
console.log('文件已保存');
});

  去掉之后,在浏览器中的表现瞬间清晰,因为, 时间偏移 getJsTime.getTimezoneOffset()  这个值已经成了 -540 。此时你就会想为什么会这样子?接下来开始解密阶段。

揭秘部分年份出现的1小时偏差

1986年4月,我国采取夏令时,具体作法是:每年从四月中旬第一个星期日的凌晨2时整(北京时间),将时钟拨快一小时,即将表针由2时拨至3时,夏令时开始;到九月中旬第一个星期日的凌晨2时整(北京夏令时),再将时钟拨回一小时,即将表针由2时拨至1时,夏令时结束。从1986年到1991年的六个年度,除1986年因是实行夏时制的第一年,从5月4日开始到9月14日结束外,其它年份均按规定的时段施行。在夏令时开始和结束前几天,新闻媒体均刊登有关部门的通告。1992年起,夏令时暂停实行。

  看到这里,你会不会恍然大悟。但是,别高兴得太早...

  你会说,为什么不能高兴? 这原因都找到了,你不就可以根据这个偏移值计算回正常的日期吗?

  emm~  道理是这样的   确实,浏览器可以这样子,但是小程序是根源所在,还得在小程序实验验证才行!!!

小程序验证

  emm~~  经过一系列的操作,最后我得到的结果和Node.js跑出来的一样,偏移值一直是-480!!!

  好吧,这个找了一系列的原因竟然找到了,小程序没有做对夏令时的处理

  emm~~  所以我在微信开发者社区报备这个bug

  

  最后的最后,我还是得在微信修改之前自己手动判断夏令时区间。。。

附图:

小程序选择器 选完后的结果是[86, 4, 3, 2] // 年,月,日,时
其中月/日都是 +1 才能对应到对应的月和日
timeArr = [86, 4, 3, 2]
year = 1986 // 这里已经函数处理过 所以直接显示1986
 let alraedySummaryTimeObj = [
  { dayStart: 4, dayEnd: 14 }, { dayStart: 12, dayEnd: 13 }, { dayStart: 10, dayEnd: 11 }, { dayStart: 16, dayEnd: 17 }, { dayStart: 15, dayEnd: 16 }, { dayStart: 14, dayEnd: 15 }
 ] // 夏令时中对应的起始日和结束日 86年特殊  5/4 - 9/14
checkYear(timeArr, year)
function checkYear(timeArr, year){
switch (year){
case 1986:
check86day(timeArr);
break;
case 1987:
case 1988:
case 1989:
case 1990:
case 1991:
checkDay(timeArr, year);
break;
default:
outNormalTime();
break;
}
}
function check86day(timeArr){
let startSign = alraedySummaryTimeObj[0].dayStart;
let endSign = alraedySummaryTimeObj[0].dayEnd;
switch(timeArr[1]+1){
case 5:
case 9:
checkHour(timeArr, 5, 9, startSign, endSign)
break;
case 6:
case 7:
case 8:
addOffsetTime();
break;
default:
outNormalTime();
break;
};
}
function checkDay(timeArr, year){
let alreadySummaryTime = [1986, 1987, 1988, 1989, 1990, 1991];
let startSign = alraedySummaryTimeObj[alreadySummaryTime.indexOf(year)].dayStart;
let endSign = alraedySummaryTimeObj[alreadySummaryTime.indexOf(year)].dayEnd;
switch (timeArr[1] + 1) {
case 4:
case 9:
checkHour(timeArr, 4, 9, startSign, endSign)
break;
case 5:
case 6:
case 7:
case 8:
addOffsetTime();
break;
default:
outNormalTime();
break;
};
}
function checkHour(timeArr, mon1, mon2, startSign, endSign){
if (((timeArr[1] + 1 == mon1) && ((timeArr[2] + 1) > startSign)) || ((timeArr[1] + 1 == mon2) && ((timeArr[2] + 1) < endSign))){
addOffsetTime();
} else if (((timeArr[1] + 1 == mon1) && ((timeArr[2] + 1) == startSign)) || ((timeArr[1] + 1 == mon2) && ((timeArr[2] + 1) == endSign))){
checkDetailHour(timeArr, mon1, mon2);
}else{
outNormalTime();
}
}
function checkDetailHour(timeArr, mon1, mon2){
if ((((timeArr[1] + 1 == mon1) && (timeArr[3] > 2))) || ((timeArr[1] + 1 == mon2) && (timeArr[3] < 1))){
addOffsetTime();
} else{
outNormalTime();
}
} // 时间戳进行对应的加减操作
function outNormalTime(){
时间戳 -= 0
}
function addOffsetTime() {
时间戳 -= 3600 * 1000
}

  当我写完这些回头看,一把辛酸泪~~~

  因为我在真机上测试的时候,emm  时区偏移是正常的可以看到-540  也就是说  微信开发者工具是 跑的node.js   所以一直是-480  因为es6有过改动...

  而真机测试是浏览器环境  只能说踩坑踩得心累

  最后的改动回复偏移值的代码是这样子的

  微信....

let d = new Date(timeStr);
if (d.getTimezoneOffset() !== -480){
itsBirth = d.getTime() - (-480 - d.getTimezoneOffset()) * 60 * 1000
}else{
  itsBirth = d.getTime()
}

  记录这次的小程序采坑记~~

javascript中new Date()会存在偏差一小时的bug的更多相关文章

  1. javascript中的Date数据类型

    javascript中,Date代表日期对象,其常见的用法如下: 一.Date的构造函数 有四种形式的Date构造函数,详见下面代码的注释: //1.构造函数没有参数,则返回当前日期的Date对象 v ...

  2. IOS:Safari不兼容Javascript中的Date问题

    在IOS5以上版本(不包含IOS5)中的Safari浏览器能正确解释出Javascript中的 new Date('2013-10-21') 的日期对象. 但是在IOS5版本里面的Safari解释ne ...

  3. IOS5中的Safari不兼容Javascript中的Date问题,做下笔录吧!奶奶的,折腾我半天!

    在做Mobile终端的Website开发中,我遇到一个很懊恼的问题. 在IOS5以上版本(不包含IOS5)中的Safari浏览器能正确解释出Javascript中的 new Date('2013-10 ...

  4. IOS5中的Safari不兼容Javascript中的Date问题

    在IOS5以上版本(不包含IOS5)中的Safari浏览器能正确解释出Javascript中的 new Date('2016-06-07') 的日期对象. 但是在IOS5版本里面的Safari解释ne ...

  5. JavaScript中的Date对象在IOS中的“大坑”

    在IOS5以上版本(不包含IOS5)中的Safari浏览器能正确解释出Javascript中的 new Date('2013-10-21') 的日期对象. 但是在IOS5版本里面的Safari解释ne ...

  6. Safari不兼容Javascript中的Date问题

    在IOS5以上版本(不包含IOS5)中的Safari浏览器能正确解释出Javascript中的 new Date('2013-10-21') 的日期对象,但是在IOS5版本里面的Safari解释new ...

  7. JavaScript中的Date类型

    ECMAScript中的Date类型是在早起Java中的java.util.Date类基础上构建的.为此,Date类型使用自UTC(Coordinated Universal Time,国际协调时间) ...

  8. javascript中new Date浏览器兼容性处理

    看下面的代码 <script type="text/javascript"> var dt1 = new Date('2016-3-4 11:06:12'); aler ...

  9. javascript中的Date对象和Math对象

    1.Date对象 1.创建Date对象 var time1=new Date() 方法1:不指定参数 var time1=new Date(); alert(time1.toLocaleString( ...

随机推荐

  1. Monkey Tradition---LightOj1319(中国剩余定理模板)

    题目链接:http://lightoj.com/volume_showproblem.php?problem=1319 题意:有 n 个猴子,n 棵树,树的高度为 L ,每个猴子刚开始的时候都在树的底 ...

  2. Zabbix设置自定义监控

    [zabbix]自定义监控项key值   说明: zabbix自带的默认模版里包括了很多监控项,有时候为了满足业务需求,需要根据自己的监控项目自定义监控项,这里介绍一种自定义监控项的方式. 1,首先编 ...

  3. centos7上安装php5.6

    配置yum源 追加CentOS 6.5的epel及remi源. # rpm -Uvh http://ftp.iij.ad.jp/pub/linux/fedora/epel/6/x86_64/epel- ...

  4. WHCTF2017线上小记

    第四届XCTF开始,首战因素,加上团队刚加入了两个新人的原因,还是决定一块参与一下.水了3题.2个RE和1个MISC,照顾新人,写的比较啰嗦. [MISC] PY-PY-PY 下载题目之后是一个pyc ...

  5. 使用jackson工具类把对象或集合转为JSON格式

    jackson使用方法: 1.加入jar包: jackson-annotations-2.2.2.jar jackson-core-2.2.2.jar jackson-databind-2.2.2.j ...

  6. Saltstack数据系统

    1.grainsgrains 是在 minion(客户端)启动时收集到的一些信息,比如操作系统类型.网卡ip等.强调是minion启动时收集到的数据,所以如果改了什么硬件啥的,要重启minion才能收 ...

  7. 制造抽象基类--《C++必知必会》 条款33

    抽象类,含有纯虚函数的类,不可以创建对象. 然而,有时我们并不需要某个函数定义为纯虚函数,但是任然希望此类像抽象类一样,不可以创建对象. 方法1:通过确保类中不存在共有构造函数来模拟抽象基类的性质.意 ...

  8. 运行javac 报告javac不是内部或外部命令,但是运行java、java-version正常

    以前装jdk 从来没遇到过今天这种情况,各种解决办法试了一下午,终于出来了,说一下解决的办法: JAVA_HOME .classpath 都在系统变量中建立好: java_home 添加jdk的安装目 ...

  9. fedora修改主目录文件名为英文

           在gnome-terminal里面能够显示中文的,但是在文本终端里面中文都是不能显示的,是一个小小的正方形.因此可以只把主目录文件名换成英文的,方便文本终端命令输入,而其他的一些地方还是 ...

  10. VS2010/MFC编程入门之十二(对话框:非模态对话框的创建及显示)

    上一节鸡啄米讲了模态对话框及其弹出过程,本节接着讲另一种对话框--非模态对话框的创建及显示. 鸡啄米已经说过,非模态对话框显示后,程序其他窗口仍能正常运行,可以响应用户输入,还可以相互切换.鸡啄米会将 ...