PHP:如何获取用户创建日起的年度日期范围以限制任务次数
解决用户任务额度统计的日期范围问题
嘿,这个问题的核心就是精准计算用户的周年统计周期,我来一步步给你捋清楚怎么实现:
核心逻辑
用户的任务额度在每年的创建周年日重置,所以统计范围要满足:
- 起始日期:最近一次已经过去的周年日(比如用户2014-04-12创建,当前是2019-05-01,起始就是2019-04-12;如果当前是2019-03-01,起始就是2018-04-12)
- 结束日期:下一个周年日的零点前(用
<下周年日的方式匹配,比BETWEEN更严谨,能覆盖周期内所有时间点的任务)
具体代码实现
先修正原代码里的小语法错误,再实现日期计算的核心部分:
function runJob($user) { $nbRemainingJob = findRemainingJobs($user); if ($nbRemainingJob > 0) { // 注意原函数名重复,改成实际执行任务的函数,比如executeJob() executeJob($user); } else { die("no more credits"); } } function findRemainingJobs($user) { // 1. 将用户创建日期转为DateTime对象,方便日期运算 $creationDate = new DateTime($user->creation_date); $today = new DateTime(); // 2. 计算当前年份的周年日 $currentYearAnniversary = (clone $creationDate)->setDate( $today->format('Y'), $creationDate->format('m'), $creationDate->format('d') ); // 3. 确定统计起始日期:如果今天已过今年周年日,用今年的;否则用去年的 if ($today >= $currentYearAnniversary) { $dateRangeStart = $currentYearAnniversary; } else { $dateRangeStart = (clone $currentYearAnniversary)->sub(new DateInterval('P1Y')); } // 4. 统计结束日期:起始日期加一年(用<这个日期覆盖到下周年日零点前) $dateRangeEnd = (clone $dateRangeStart)->add(new DateInterval('P1Y')); // 5. 格式化为SQL可识别的字符串(若job_created_at带时间,用'Y-m-d H:i:s') $startStr = $dateRangeStart->format('Y-m-d'); $endStr = $dateRangeEnd->format('Y-m-d'); // 6. 构造SQL并执行查询 $sql = "SELECT count(*) FROM jobs WHERE user_id = ? AND job_created_at >= ? AND job_created_at < ?"; $stmt = $pdo->prepare($sql); $stmt->execute([$user->id, $startStr, $endStr]); $done = $stmt->fetchColumn(); return $user->max_jobs - $done; }
关键细节说明
- 用
DateTime和DateInterval处理日期,避免手动拼接字符串带来的闰年、月份天数差异等错误 - 不用
BETWEEN的原因:如果job_created_at包含时间戳(比如2019-04-11 23:59:59),BETWEEN会漏掉这个时间点的任务;而>= 起始日 AND < 下周年日能完整覆盖整个统计周期 - 克隆
DateTime对象是因为setDate、sub、add会修改原对象,克隆可避免污染原始的创建日期数据
内容的提问来源于stack exchange,提问作者Dany M
相关产品推荐
相关产品推荐

