今天聊一下时间里面的setTimeOut or setInterval + .getTime() or .parse()
2024/09/06 7 mins read See this issue
# 踩坑记录器
# 陈年老博客
Back
To Top
这两天搞了点对于时间的精度处理的模块功能,大家一起来看看笑话吧:
/**
* 这是一套关于计算时间差函数的部分代码
* 而这里注释掉的.getTime()部分,即是这次的入坑案(⊙_⊙)...
*/
// 获取当前时间
// let nowDateTime = new Date();
// let nowTime = nowDateTime.getTime();
let nowTime = Date.parse(new Date());
// 获取截止时间
// let endDateTime = new Date(deadline);
// let endTime = endDateTime.getTime();
let endTime = Date.parse(deadline);
// 计算时间差
let leftTime = parseInt(endTime - nowTime);
// 定义天、小时、分钟、秒
let d, h, m, s;
if (leftTime >= 0) {
d = Math.floor(leftTime / 1000 / 60 / 60 / 24);
h = Math.floor(leftTime / 1000 / 60 / 60 % 24);
m = Math.floor(leftTime / 1000 / 60 % 60);
s = Math.floor(leftTime / 1000 % 60);
} else return '00:00:00';
// 将0-9的数字前面加上0,例1变为01
d = checkTime(d);
h = checkTime(h);
m = checkTime(m);
s = checkTime(s);
function checkTime(i) {
return i < 10 ? "0" + i : i;
}
好,大家都见笑了,那就解释一下:Date.parse() 与 Date.getTime() 这两兄弟狗东西,来看他家长是怎么说它们的:
# .getTime()
OK,原来这就是一个获取毫秒级时间戳的Date函数:
再看下一个:
# .parse()
好嘛,原来都没差,不都是搞 “毫秒级” 的时间戳函数吗?(其实当时写的时候是理解有误的,Date.parse()是只能获取到秒级)
# 真的没差吗?
# 懂?
没错!他喵的就是这转换的鬼精度问题,导致在配合食用setTimeOut/setInterval时会发生很微妙的变化,比如:
<!-- 此时正常(即.parse())倒计时显示: -->
02:00
01:59
01:58
01:57
...
<!-- 而高精度(.getTime())时,你会发现: -->
02:00
01:59
01:57
01:56
01:54
01:53
...
或
02:00
01:58
01:57
01:56
01:55
01:54
...
# …
这他喵的为啥呀…
按理来说,我们用高精度 .getTime() 的反而应该才会准确读秒,而低精度的 .parse() 才会异常吧?不!这里刚好恰恰相反。
上面说到,在配合食用setTimeOut/setInterval时,食用精度高的.getTime()反而会出现跳秒,而精度低的.parse()却正常。
# 由于在网上查找的相关问题的资料甚少,几乎可以说没有相关的记录,下面这一段说明,为小弟反复测试对比而做出的无责任猜想小结论:
# setTimeOut/setInterval + .getTime():setTimeOut/setInterval本身读秒时,并不是以毫秒级时间戳的单位进行推进时间,而是以秒级的时间戳单位,即我们以为的是1652282191590,实际上却是1652282191000,那么他自己本身在定时器的作用下是正常的表现。当.getTime()和他同时在作用处理一段时间的计算差值时,.getTime()的高精度时间戳干扰了setTimeOut/setInterval的低精度时间戳,或者说有可能污染/阻塞了1000-2000毫秒的时间推进,但同时setTimeOut/setInterval的作用还是存在的,只是线程被阻断了1000-2000毫秒,所以,即会出现上面的跳1-2秒状况,最多也只会跳2秒
# setTimeOut/setInterval + .parse():前者说setTimeOut/setInterval本身读秒时,并不是以毫秒级时间戳的单位进行推进时间,而是以秒级的时间戳单位,即我们以为的是1652282191590,实际上却是1652282191000。所以,在.parse()的搭配使用时,.parse()的时间精度同样也是1652282191000低时间精度,故与定时器的时间推进率相吻合,不会出现跳秒的异常情况。
# 说到这里,开始反思之前在项目上不少用了.getTime()…不过,并不是跟此业务一样搭配了setTimeOut/setInterval去写的…
港真,多少还是有点加深了毫秒级时间戳的一个处理方案,注重使用场景,那此次的掉坑案来说也长进了对DateObj的印象,但也是万万没想到竟会出现这种…小弟猜测这估计是JavaScript的一个bug,在setTimeOut/setInterval中,不应该是以低精度的时间戳去推进时间的,而是以绝对的高精度去推进才更佳吧…至少从目前普遍对时间对象的扩展使用来说…
# 扩展多一个:.valueOf() 也是个获取毫秒级时间戳(高精度)…
好了,就都散了吧o(╥﹏╥)o…