「这是我参与2022首次更文挑战的第1天,活动详情查看:2022首次更文挑战」
场景
前端有个列表展示,产品要根据日期倒叙展示。上线一天后,突然反馈,苹果浏览器排序无效。 what 谷歌浏览没问题啊,借个苹果电脑看看,天啊,排序真的无效。 大概代码如下
const list = ['2021-1-12', '2021-1-13', '2021-1-14', '2021-1-15'];
list.sort((a, b) => new Date(b).getTime() - new Date(a).getTime());
这段代码没问题好说的,普通的在没法普通了。
排查问题
先看看接口返回数据的格式有没有问题,没问题,而且谷歌浏览器没问题。
可能是Array.sort 问题
测试代码
const list=[1,2,3,4,5,6];
list.sort((a,b)=>b-a);
console.log(list); # [6,5,4,3,2,1]
chrome 和Safari 都问题, sort方法没问题。
可能是new Date 问题
测试代码
console.log(new Date('2021-1-12'));
console.log(new Date('2021-1-12').getTime());
chrome下一切正常。safari下竟然是 Invalid Date 和 NaN 那问题就很明显了。safari 浏览器new Date()有问题,仔细观察这个时间字符串后发现,和我们常用略微有点差异 ,我们平时用的是YYYY-MM-DD,这个后台返回的是YYYY-M-DD,当月份是个位的时候前面没有补0.
上完成测试代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
</body>
<script src="https://cdn.bootcdn.net/ajax/libs/dayjs/1.10.7/dayjs.min.js"></script>
<script>
console.log(new Date('2021-1-12'));
console.log(new Date('2021-1-12').getTime());
const list = ['2021-1-12', '2021-1-13', '2021-1-14', '2021-1-15'];
list.sort((a, b) => new Date(b).getTime() - new Date(a).getTime());
console.log(list);
// dayjs
const day = dayjs('2021-1-12').format('YYYY-MM-DD');
console.log(day);
console.log(new Date(day));
</script>
</html>
chrome下一切正常。来看看safari下
通过上图我们能看出来,在使用dayjs格式化日期后就可以了。到这个地方解决问题的办法就有很多了,项目中可以使用dayjs来做日期格式化,也可以自己用判断字符串然后月份补0
为啥会出现这个问题
Date
创建一个 JavaScript Date 实例,该实例呈现时间中的某个时刻。Date 对象则基于 Unix Time Stamp,即自1970年1月1日(UTC)起经过的毫秒数。
时间戳字符串
dateString
表示日期的字符串值。该字符串应该能被 Date.parse() 正确方法识别(即符合 IETF-compliant RFC 2822 timestamps 或 version of ISO8601)。
- 注意: 由于浏览器之间的差异与不一致性,强烈不推荐使用
Date构造函数来解析日期字符串 (或使用与其等价的Date.parse)。对 RFC 2822 格式的日期仅有约定俗成的支持。 对 ISO 8601 格式的支持中,仅有日期的串 (例如 "1970-01-01") 会被处理为 UTC 而不是本地时间,与其他格式的串的处理不同。
上文介绍到了Date.parse我们在safari下测试使用试试
Date.parse('2021-1-12'); # NaN
好吧,这个不行。
ECMAScript 规范规定:如果一个字符串不符合标准格式,则函数可以使用任何由引擎决定的策略或解析算法。 Date.parse() 对于因包含有无效元素而无法识别的 ISO 格式字符串或者日期应该返回 NaN 。
但是, 在如 ECMA-262 规范中定义的情况,如果因为无效值而导致日期字符串不能被识别为 ISO 格式时,根据浏览器和给定的值不同,返回值可以是,也可以不是 NaN
总结
此次问题的出现是由于后台格式化日期字符串,没有按照YYYY-MM-DD来格式化,前端处理的时候没有考虑浏览器差异。和后台达成共识,以后日期要么严格按照YYYY-MM-DD,要么就转成时间戳。至于有人问,为啥这么简单的排序后端不做。鬼知道