记JS的toLocaleDateString()引发的一次生产事故

312 阅读4分钟

记JS的Date对象中的toLocaleDateString()引发的一次生产事故

js的new Date().toLocaleDateString()就是把Date对象的日期部分转换为字符串,并返回结果

背景

业务小伙伴收到用户反馈,AU站点的一个已订阅用户,在进行页面刷新和页面跳转时,订阅弹窗会一直弹出来,很影响购物体验。

排查过程

  1. 首先测试同学复现
    • 测试同学收到bug单后,尝试复现,拉了好几个测试,复现了好几天,没有复现出来。
  2. 拉代码排查
    • 梳理了一下自动弹出的逻辑,可能导致出现的这个诡异问题的只有记录弹窗弹出时间的逻辑。
  3. 初步定位问题
    • 在弹窗自动弹出之前,新增一个监测埋点,记录弹窗弹出时间与用户当前时间。
  4. 发现问题
    • 历经一晚上的等待,拿到了埋点数据,一个10月9号访问的用户,记录的弹窗自动时间却是9月10号,问题应该就出现在这里了。

复现问题

代码中时间戳的转换方式为+new Date(new Date().toLocaleDateString()),单独执行new Date().toLocaleDateString(),会得到'2024/10/09',也符合我们的年月日的阅读习惯。

然而,当我把系统语言调整到美国的时候,我在浏览器执行new Date().toLocaleDateString()时,会得到10/09/2024,这个时间格式就是月/日/年,转换成时间戳就是1728403200000,通过时间戳转换成日期,如图:

image.png

看上去好像没什么问题。

但是当我把语言切换到英语(澳大利亚)的时候,有趣的事情发生了,同样是执行new Date().toLocaleDateString(),控制台会返回09/10/2024,本地化的时间是日/月/年,如果只是澳大利亚本土用户,显示日/月/年,是不会有问题的,问题点在于,这个方法叠加了一层时间戳的计算,+new Date(new Date().toLocaleDateString()),打印出来的时间戳是1725897600000,同样的,时间戳转换成日期,如图:

image.png

涨知识了

toLocaleDateString()这个api本身没有什么兼容性问题,但是这个api仅限于纯展示的场景,一旦进行时间戳转换,就会出现这个问题。询问了一下gpt,提供了一些常用的显示格式:

new Date().toLocaleDateString() 方法返回日期的格式取决于浏览器的语言环境用户的区域设置。这个方法会根据用户的本地化设置,动态地生成不同的日期格式。因此,输出结果可能会有所不同。

常见的日期格式:

MM/DD/YYYY(月/日/年):

-   **国家/地区**: 美国、加拿大(英语)、菲律宾等。
-   示例: `10/11/2024` (2024年10月11日)

DD/MM/YYYY(日/月/年):

-   **国家/地区**: 英国、澳大利亚、新西兰、加拿大(法语)、印度、南非等。
-   示例: `11/10/2024` (2024年10月11日)

YYYY/MM/DD(年/月/日):

-   **国家/地区**: 中国、日本、韩国等东亚国家。
-   示例: `2024/10/11` (2024年10月11日)

YYYY年MM月DD日(年/月/日,以汉字分隔):

-   **国家/地区**: 中文地区(中国大陆、台湾、香港等)。
-   示例: `2024年10月11日`

D. MMMM YYYY(日. 月份全名 年):

-   **国家/地区**: 德国、瑞士、奥地利等。
-   示例: `11. Oktober 2024` (2024年10月11日)

DD MMM YYYY(日 月缩写 年):

-   **国家/地区**: 英国、澳大利亚、新西兰等部分英语国家。
-   示例: `11 Oct 2024` (2024年10月11日)

DD de MMMM de YYYY(日 月全名 年):

-   **国家/地区**: 西班牙、墨西哥、阿根廷等西班牙语国家。
-   示例: `11 de octubre de 2024` (2024年10月11日)

YYYY년 MM월 DD일(年 月 日,以韩语分隔):

-   **国家/地区**: 韩国
-   示例: `2024년 10월 11일` (2024年10月11日)

YYYY年MM月DD日(以中文分隔):

-   **国家/地区**: 中文环境,比如台湾、香港。
-   示例: `2024年10月11日`