JS按月统计支出时每月1号日期被错误归类到上月的问题
问题原因
存储的支出日期字段是UTC零时区的零点时间,格式末尾的Z就是UTC时区标识。而Date.prototype.getMonth()返回的是代码运行环境本地时区对应的月份值:当本地时区为UTC负偏移时区(比如北美东部时区UTC-5、太平洋时区UTC-8)时,UTC时间的每月1日0点换算成本地时间是上月最后一天的下午/晚上,会被识别为上一个月,直接导致7月1日的支出被错误统计到6月的结果中。
修复方案
存储的日期本身是UTC标准格式,直接使用getUTCMonth()方法取UTC标准时间对应的月份即可,完全绕过时区偏差影响。同时可以优化原逻辑的遍历效率,把map+reduce两次遍历合并为一次reduce完成过滤+累加,增加空值兜底避免接口未返回数据时的运行报错:
const expensesData = useSelector((state)=>state?.financialsReducer?.expenses) const monthlyExpenses = (m) => { if (!Array.isArray(expensesData)) return (0).toFixed(2) const total = expensesData.reduce((accumulator, currentExpense) => { // 替换原getMonth为getUTCMonth,匹配存储日期的UTC时区月份 if(new Date(currentExpense.date).getUTCMonth() === m) { return accumulator + Number(currentExpense.amount) } return accumulator }, 0) return total.toFixed(2) } const juneExpenses = monthlyExpenses(5) const julyExpenses = monthlyExpenses(6)
注意事项
- 累加金额时显式用
Number()转换金额字段,避免接口返回字符串类型金额时,出现字符串拼接而非数值累加的异常 - 如果业务要求按用户本地所在时区统计月度支出,不建议直接存储UTC零点时间,可在日期入库时携带对应时区偏移,或解析时手动补全本地时区差值,避免跨天、跨月统计误差
内容的提问来源于stack exchange,提问作者Cip
相关产品推荐
相关产品推荐

