又是时间格式化问题,诡异的是只有10月份BUG才出现
背景
十一假期后第一天工作,当大家还沉浸在国庆长假的快乐的时候,我被业务部门急促的电话拉回到现实,生产环境上有页面数据都是空的,而节前还都是好好的。
这就奇了怪了,过了一个国庆,这个bug就闪现出来了?
时间格式化的锅
排查原因
从表象上看是后台没有返回数据,实际是前台的时间传递有问题。
下面这个请求,日期字段date应该是20211011,但是怎么会变成2042呢?
难道过了一个国庆,年份2021就变成了2042吗?
又是时间格式化问题
下面省略一万秒,前端开发排查后发现了下面的代码:
// 这里省略一万行代码 let str = "" let endDateTime = new Date() str += endDateTime.getFullYear() + (endDateTime.getMonth() + 1 < 10 ? '0' + (endDateTime.getMonth() + 1) : endDateTime.getMonth() + 1) + (endDateTime.getDate() < 10 ? '0' + endDateTime.getDate() : endDateTime.getDate()) let opt = {date: str, productNo: productNo}; // 这里省略一万头牛 复制代码
前端大神们看了上面的代码,能一眼看出哪里出问题了吗?
如果你能很看看出问题,说明你的基本功非常扎实。
如果不能一看看出,甚至还要调试一下,说明你基础要加强,你也可能出现类似错误。
这个代码似曾相似,后面会说和时间格式化的第一次邂逅。
解析
endDateTime.getMonth()
代码返回的是月份索引(10月份对应9),9+1=10 < 10 是三元表达式条件
三元表达式: (endDateTime.getMonth() + 1 < 10 ? '0' + (endDateTime.getMonth() + 1) : endDateTime.getMonth() + 1) 在10月份代码变成了:endDateTime.getMonth() + 1 所以: str = 2021 + 9 + 1 + 11 = 2042 复制代码
为什么10月份之前没有问题呢?
因为9月份的时候三元表达式变成了:'0' + (endDateTime.getMonth() + 1) JS会把结果转成字符串 '09' 复制代码
不得不佩服开发同学成功地在9月份避开了BUG,导致大家和测试同学都无法在之前测出问题,而10月份问题暴露。
问题解决
开发给的最快解决方案是增加一个操作把年份变成字符串,这样就不存在数字累计导致年月日错误。
// 解决BUG str += endDateTime.getFullYear() + '' // 这里增加空字符串 + (endDateTime.getMonth() + 1 < 10 ? '0' + (endDateTime.getMonth() + 1) : endDateTime.getMonth() + 1) + (endDateTime.getDate() < 10 ? '0' + endDateTime.getDate() : endDateTime.getDate()) 复制代码
当然我们不建议上面的操作,我建议要么写一个健壮的公共的时间格式化工具类,要么引用外部成熟的时间工具类,比如moment.js
// import http://cdn.staticfile.org/moment.js/2.24.0/moment.js this.date = moment().format('YYYYMMDD'); // 输出:20211011 复制代码
回忆第一次和时间格式化邂逅
回忆总是让人忧伤。
第一次和时间格式化bug的邂逅是2020年元旦。
当很多同事在家喜迎新年的时候,突然业务报问题,说页面上的时间错了。
时间给了我们一个惊喜,这应该是元旦最难忘的礼物。
还是经过了排查问题--定位问题的过程,最后前端开发媛发现了下面的秘密:
// 先省略一万字码神附体 let mydate = new Date() let date = mydate.getFullYear() + '-' + (mydate.getMonth() + 1 >= 10 ? mydate.getMonth() + 1 : '0' + mydate.getMonth() + 1) this.setData({ mydate: date }) 复制代码
对于这次bug的解析,欢迎小伙伴们在评论区给出自己的见解。
「 掘金官方将在掘力星计划活动结束后,在评论区抽送100份掘金周边奖品,抽奖详情见活动文章 」
历史总是惊人的相似,没想到这次又碰到了这个时间格式化bug。
PS:这不是同一个程序员埋的彩蛋。
启示
JavaScript是一个弱类型语言,它不会强制开发者提前指定数据的类型,因此在任何时候,开发人员的疏忽都会导致代码处理走入意想不到的分支,就像上面的代码总是在整数和字符串之间转换。而像Java这样的强类型语言则增加了一些约束,不会随意改变数据类型。除此之外,还要准确使用小括号。
对于新手程序员,不要随便相信网上的代码,多了解每个方法和语法的原理,能用成熟的工具类绝不自己写,要聪明地偷懒。
人不能两次踏入同一条河流
,但是两个程序员可能产生同一种Bug,所以现在读文章的你是否真的学废了时间格式化呢?
作者:Java实用技术
链接:https://juejin.cn/post/7018195800874287118