
本文讲解如何在 php 中根据用户预付金额、单杯果汁单价和起始服务日期,自动计算可享受的服务天数(即玻璃数)、剩余余额及下次缴费到期日。核心涉及日期加法运算与整除取整逻辑。
本文讲解如何在 php 中根据用户预付金额、单杯果汁单价和起始服务日期,自动计算可享受的服务天数(即玻璃数)、剩余余额及下次缴费到期日。核心涉及日期加法运算与整除取整逻辑。
在果汁订阅类服务场景中,用户一次性支付固定金额(如 $200),商家按日提供固定单价的果汁(如每杯 $30),服务从指定起始日期开始,持续若干天直至预付款耗尽。此时需动态计算:最多能提供多少杯果汁?剩余多少钱?服务截止到哪一天?
✅ 核心逻辑拆解
-
玻璃数量 = 总金额 ÷ 单价(向下取整)
使用floor($total_amt / $rate)确保不超出预算; -
剩余余额 = 总金额 % 单价
利用取模运算直接获取找零; -
到期日期 = 起始日期 + 玻璃数量(天)
使用DateTime::createFromFormat()解析自定义格式日期,再通过DateInterval和add()方法安全加天数。
? 完整可运行示例代码
<?php $rate = 30; // 每杯果汁价格(元)
$total_amt = 200; // 用户预付总金额(元)
$start_date = "19-08-2022"; // 服务起始日期(d-m-Y 格式)
// 1. 计算可购买玻璃数(向下取整)
$glass_count = floor($total_amt / $rate);
// 2. 计算剩余余额
$balance = $total_amt % $rate;
// 3. 计算到期日期(起始日 + glass_count 天)
$startDateObj = DateTime::createFromFormat('d-m-Y', $start_date);
if (!$startDateObj) {
die("日期格式错误,请使用 d-m-Y 格式(如 19-08-2022)");
}
$dueDateObj = $startDateObj->add(new DateInterval("P{$glass_count}D"));
$due_date = $dueDateObj->format('d-m-Y');
// 输出结果
echo "Number of glass in \${$total_amt} is: {$glass_count}\n";
echo "returning balance : \${$balance}\n";
echo "next due date: {$due_date}\n";
?>
输出结果:
Number of glass in $200 is: 6 returning balance : $20 next due date: 25-08-2022
⚠️ 注意事项
-
日期格式必须严格匹配:
DateTime::createFromFormat()对输入格式敏感,若传入2022-08-19却用'd-m-Y'解析,将返回false;建议统一使用'd-m-Y'并确保前端/输入层校验。 -
避免浮点误差:使用
floor()而非(int)强转,防止因浮点精度导致计数偏差(如200/30 ≈ 6.666...→(int)6.666仍为6,但语义更清晰)。 - 业务扩展建议:若需支持“每周固定天数供应”(如仅周一至周五供汁),应改用循环+工作日判断,而非简单加天数。
该方案简洁、健壮、符合财务逻辑,适用于预付费周期性服务类系统的后端计算模块。











