Java基于上映日期计算电影租赁价格的逻辑Bug排查
问题原因
你写的逻辑永远按首档定价,核心是两个错误:
- 最致命的错误:误用
Period类的getDays()方法。Period.between()返回的是年、月、日拆分后的时间差对象,getDays()只会返回差值中「天」这个单独字段的数值,不会返回两个日期之间的总天数。比如影片已经上映3年整,Period.between(LocalDate.now(), movie.getReleaseDate())得到的结果是P-3Y0M0D,调用getDays()只会返回0,乘-1后还是0,永远落在「上映不满364天」的分支,自然始终按5.00的单价计算。 - 跨档位判断条件写反,哪怕天数计算正确,遇到跨档场景也会算错价格。
修复代码
直接替换成以下实现即可,兼容跨1档/跨2档的租赁场景,同时避免浮点计算精度问题:
import java.time.LocalDate; import java.time.temporal.ChronoUnit; static Double getPrice(Movie movie, Integer weeksToRent) { double totalPrice = 0d; // 直接计算两个日期的总天数差,参数顺序为(起始日期, 结束日期),无需手动取反 long daysSinceReleased = ChronoUnit.DAYS.between(movie.getReleaseDate(), LocalDate.now()); int totalRentDays = weeksToRent * 7; long uncountedDays = totalRentDays; long currentReleaseDays = daysSinceReleased; while (uncountedDays > 0) { double weeklyRate; long daysToNextTier; if (currentReleaseDays < 364) { weeklyRate = 5.00d; daysToNextTier = 364 - currentReleaseDays; } else if (currentReleaseDays < 1092) { weeklyRate = 3.49d; daysToNextTier = 1092 - currentReleaseDays; } else { weeklyRate = 1.99d; daysToNextTier = Long.MAX_VALUE; } // 计算当前档位内需要计费的天数 long daysInCurrentTier = Math.min(uncountedDays, daysToNextTier); // 按天折算单价累加费用 totalPrice += (weeklyRate / 7) * daysInCurrentTier; // 更新剩余未计费天数、当前累计上映时长,进入下一档位判断 uncountedDays -= daysInCurrentTier; currentReleaseDays += daysInCurrentTier; } // 四舍五入保留两位小数,避免浮点运算出现异常尾值 return Math.round(totalPrice * 100) / 100.0; }
修复说明
- 用
ChronoUnit.DAYS.between()替代Period计算总上映天数,从根源解决天数计算错误的问题。 - 采用逐档位循环核算的逻辑,不管租赁期跨1个价格节点还是2个价格节点,都能正确拆分不同单价的计费天数,不会出现条件判断写反的问题。
- 简化分段计费的计算逻辑,直接按天折算单天租金,减少冗余的乘除运算,降低浮点误差出现的概率。
- 增加结果四舍五入逻辑,避免返回类似
17.4499999999这类不符合金额展示规则的结果。
内容的提问来源于stack exchange,提问作者ErikVM
相关产品推荐
相关产品推荐

