一、背景
- 本文章记录一次比较有意思的bug,因为闰年导致的四年才出现一次的bug,并且只出现在二月份。
- 我接手的这个项目是做业务指标的其中有一个销售目标的指标,需要去表中获取当月最后一天target字段的值。比如今天是2025-02-10,那我的筛选条件应该为date='2025-02-28'。否则其他的日期是没有值的。
- 同时该指标还需要获取到同期值,即去年当天的值。比如今天是2025-02-10,那么获取同期值时,我的筛选条件应该为date='2024-02-29'。(因为2024年是闰年2月有29天)
二、原因
- bug的现象就是该指标的同期数没有计算出来。
- 查看代码才发现,当前年的时间计算是通过java代码中lastDayOfMonth方法实现的(比如今天是2025-02-10转换后的时间为2025-02-28)然后塞到SQL中进行计算。
- 计算同期数时,是根据转换后的当前年(2025-02-28)直接在SQL中进行年份减一,得到的时间是2024-02-28,所以计算出来的同期数为空。(该字段只在每月最后一天有数据)
- 源代码为:
date = DATE_FORMAT(DATE_SUB(STR_TO_DATE('2025-02-28', '%Y-%m-%d'), INTERVAL 1 YEAR), '%Y-%m-%d')
三、解决
- 时间的操作应该都放到同一个地方,要么都在代码中操作、要么就统一在SQL中进行操作。多个地方可能会引起时间的不统一。
- 临近解决方案,在计算同期的SQL中添加LAST_DAY()函数,强制转换为每月最后一天。
date = LAST_DAY(DATE_FORMAT(DATE_SUB(STR_TO_DATE(#{endTime}, '%Y-%m-%d'), INTERVAL 1 YEAR), '%Y-%m-%d'))