Moment的feature导致线上bug解决分析


Posted in Javascript onSeptember 23, 2022

bug的出现

这一天,本来是平平淡淡的一天,我正准备一如既往的到点下班,结果qa说线上出了个匪夷所思的bug。

表象为:用户在日期选择器选择了1964-01-01之后,自动变成了1963-12-31

我心里想:这是什么神奇bug,于是我又尝试了一下选择1964-01-02、1963-12-31、1965-01-01、1963-01-01,结果都正常,那么到底是为什么会引发这个bug呢?

bug排查

由于后端把时间、日期类的字段都定义为了时间戳,因此前端是有进行一些处理的,可以看下面这个图

Moment的feature导致线上bug解决分析

从接口中拿到时间戳后,会先存到内存中,格式化后传入antd日期选择器中。每当用户选择日期之后,我会截取日期中的年月日,然后使用moment-timezone去获取到雅加达(印尼首都)当天零点的时间戳,存储到内存中,当用户点击提交的时候,这个时间戳就会被提交到后端去

再来看一下用户选择日期后进行处理的代码

import momentTimeZone from 'moment-timezone';
import moment from 'moment';
import type { Moment } from 'moment';
convert = (value?: Moment | null) => {
        if (value) {
          const valueString = momentTimezone.tz(value.format('YYYY-MM-DD'), 'Asia/Jakarta').format();
          return (moment(valueString).valueOf() / 1000).toFixed();
        }
        return value;
      }

bug的根因

乍一看,没什么问题呀,于是我开始断点,脑溢血的一幕出现了,大家可以去momentjs.com/timezone/do… 这个页面上试一试,百分百复现

Moment的feature导致线上bug解决分析

// 让人大吃一惊的等式
moment.tz('1961-01-01', 'Asia/Jakarta').format() === '1963-12-31T23:30:00+07:00';

这怎么转换之后,日期还给我整错了呢?我的第一反应就是给moment-timezone提issue,结果没想到有人赶在了我的前面 github.com/moment/mome…

官方也解释的很清楚了:由于当地历史原因,雅加达在1964年之前都是按东七半区来计算时区的,1964年开始才按照东七区来计算,总的来说,这个匪夷所思的等式居然是个feature,只是我使用之前没有了解清楚,所以出了bug,这锅是甩不掉了

解决方案

经过一系列的讨论,我们认为其实日期类型的字段用时间戳表达是不准确的,比如元旦这个节日,在全世界任何一个地区都应该是1月1日,可是如果用时间戳表达的话,可能在某些地区的确是1月1日,但是在其他地区却可能是1月2日了,因此正确的设计应该是用日期字符串来进行存储和传输,比如"2022-01-01",这样才能避免类似的bug,于是前端、app和be都进行了对应的修改,并且发布了hotfix

虽然影响范围比较小,但是众所周知虾皮对于质量是看的很重的,特别是线上的质量。。。只是可惜了我的绩效。。

好了以上就是Moment的feature导致线上bug解决分析的详细内容,更多关于Moment feature线上bug的资料请关注三水点靠木其它相关文章!

Javascript 相关文章推荐
script的async属性以非阻塞的模式加载脚本
Jan 15 Javascript
鼠标移到图片上变大显示而不是放大镜效果
Jun 15 Javascript
jquery使用ul模拟select实现表单美化的方法
Aug 18 Javascript
jQuery实现获取table表格第一列值的方法
Mar 01 Javascript
jquery插件格式实例分析
Jun 16 Javascript
JS锚点的设置与使用方法
Sep 05 Javascript
Vue-Access-Control 前端用户权限控制解决方案
Dec 01 Javascript
解决vue项目打包后提示图片文件路径错误的问题
Jul 04 Javascript
Vue表情输入组件 微信face表情组件
Feb 11 Javascript
Javascript通过控制类名更改样式
May 24 Javascript
Vue3 Composition API的使用简介
Mar 29 Vue.js
JavaScript中关于预编译、作用域链和闭包的理解
Mar 31 Javascript
js 实现Material UI点击涟漪效果示例
Sep 23 #Javascript
js 实现验证码输入框示例详解
Sep 23 #Javascript
TypeScript 内置高级类型编程示例
Sep 23 #Javascript
详解Anyscript开发指南绕过typescript类型检查
Sep 23 #Javascript
js基于div丝滑实现贝塞尔曲线
Sep 23 #Javascript
TS 类型兼容教程示例详解
Sep 23 #Javascript
TS 类型收窄教程示例详解
Sep 23 #Javascript
You might like
轻松修复Discuz!数据库
2008/05/03 PHP
PHP 开发环境配置(测试开发环境)
2010/04/28 PHP
PHP的变量总结 新手推荐
2011/04/18 PHP
php动态绑定变量的用法
2015/06/16 PHP
[原创]php集成安装包wampserver修改密码后phpmyadmin无法登陆的解决方法
2016/11/23 PHP
表单的一些基本用法与技巧
2006/07/15 Javascript
Javascript的getYear、getFullYear、getUTCFullYear异同分享
2011/11/30 Javascript
Javascript实现带关闭按钮的网页漂浮广告代码
2014/01/12 Javascript
关于jQuery中的each方法(jQuery到底干了什么)
2014/03/05 Javascript
jQuery中多个元素的Hover事件解决方案
2014/06/12 Javascript
jquery实现带缩略图的全屏图片画廊效果实例
2015/06/25 Javascript
jQuery对checkbox 复选框的全选全不选反选的操作
2016/08/09 Javascript
javascript阻止事件冒泡和浏览器的默认行为
2017/01/21 Javascript
javascript数组去重常用方法实例分析
2017/04/11 Javascript
JS中正则表达式要注意lastIndex属性
2017/08/08 Javascript
详解如何让Express支持async/await
2017/10/09 Javascript
canvas绘制爱心的几种方法总结(推荐)
2017/10/31 Javascript
实现div内部滚动条滚动到底部和顶部的代码
2017/11/15 Javascript
详解node child_process模块学习笔记
2018/01/24 Javascript
Vue中keep-alive组件的深入理解
2020/08/23 Javascript
详解JavaScript 高阶函数
2020/09/14 Javascript
[02:57]DOTA2英雄基础教程 风行者
2014/01/16 DOTA
Python作用域用法实例详解
2016/03/15 Python
Python中绑定与未绑定的类方法用法分析
2016/04/29 Python
浅谈python中的面向对象和类的基本语法
2016/06/13 Python
Python基于opencv实现的简单画板功能示例
2019/03/04 Python
完美解决pyinstaller打包报错找不到依赖pypiwin32或pywin32-ctypes的错误
2020/04/01 Python
python进度条显示-tqmd模块的实现示例
2020/08/23 Python
Python环境搭建过程从安装到Hello World
2021/02/05 Python
英国简约舒适女装品牌:Great Plains
2018/07/27 全球购物
意大利运动服减价商店:ScontoSport
2020/03/10 全球购物
在C中是否有模拟继承等面向对象程序设计特性的好方法
2012/05/22 面试题
实习自我鉴定模板
2013/09/28 职场文书
便利店投资创业计划书
2014/02/08 职场文书
2014年物业管理工作总结
2014/11/21 职场文书
三八妇女节慰问信
2015/02/14 职场文书