阅读 77

又是时间格式化问题,诡异的是只有10月份BUG才出现

背景

十一假期后第一天工作,当大家还沉浸在国庆长假的快乐的时候,我被业务部门急促的电话拉回到现实,生产环境上有页面数据都是空的,而节前还都是好好的。

这就奇了怪了,过了一个国庆,这个bug就闪现出来了?

img

时间格式化的锅

排查原因

从表象上看是后台没有返回数据,实际是前台的时间传递有问题。

下面这个请求,日期字段date应该是20211011,但是怎么会变成2042呢?

难道过了一个国庆,年份2021就变成了2042吗?

image-20211012202112694

又是时间格式化问题

下面省略一万秒,前端开发排查后发现了下面的代码:

 // 这里省略一万行代码  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 复制代码

回忆第一次和时间格式化邂逅

回忆总是让人忧伤。

img

第一次和时间格式化bug的邂逅是2020年元旦。

当很多同事在家喜迎新年的时候,突然业务报问题,说页面上的时间错了。

image-20211012223859800

时间给了我们一个惊喜,这应该是元旦最难忘的礼物。

还是经过了排查问题--定位问题的过程,最后前端开发媛发现了下面的秘密:

 // 先省略一万字码神附体  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:这不是同一个程序员埋的彩蛋。

启示

  1. JavaScript是一个弱类型语言,它不会强制开发者提前指定数据的类型,因此在任何时候,开发人员的疏忽都会导致代码处理走入意想不到的分支,就像上面的代码总是在整数和字符串之间转换。而像Java这样的强类型语言则增加了一些约束,不会随意改变数据类型。除此之外,还要准确使用小括号

  2. 对于新手程序员,不要随便相信网上的代码,多了解每个方法和语法的原理,能用成熟的工具类绝不自己写,要聪明地偷懒。

  3. 人不能两次踏入同一条河流,但是两个程序员可能产生同一种Bug,所以现在读文章的你是否真的学废了时间格式化呢?


作者:Java实用技术
链接:https://juejin.cn/post/7018195800874287118


文章分类
后端
版权声明:本站是系统测试站点,无实际运营。本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 XXXXXXo@163.com 举报,一经查实,本站将立刻删除。
相关推荐