基于日期计算28天重复周期的周期编号技术问题
解决方案
核心思路
周期编号采用「两位年份+两位周期序号」规则,需完成两点核心逻辑:
- 基于起始日至今的总周期数,定位当前周期所属年份
- 计算该年份内的周期序号,适配每年可能包含13或14个周期的情况
完整实现代码
<?php class CycleCalculator { const REF_ZERO_DATE = '01/27/2022'; const REF_ZERO_YEAR = 2022; const REF_ZERO_CYCLE_NUM = 1; // 起始周期为2022年第1个周期 public static function getCurrentCycleInfo($targetDate = null) { // 若未传入日期,默认使用今日 $today = $targetDate ? new \DateTime($targetDate) : new \DateTime(); $refZero = new \DateTime(self::REF_ZERO_DATE); // 计算起始日到目标日的总天数(取绝对值确保正数) $daysDiff = abs($today->diff($refZero)->format("%a")); // 计算总周期偏移量(起始日为第0个偏移) $totalCycles = floor($daysDiff / 28); // 计算最近的周期日期(使用clone避免修改原起始日对象) $latestCycleDate = clone $refZero; $latestCycleDate->add(new \DateInterval("P" . $totalCycles * 28 . "D")); // 推导周期编号 $cycleYear = self::REF_ZERO_YEAR; while (true) { // 定义当前年份的起止日期 $yearStart = new \DateTime("$cycleYear-01-01"); $yearEnd = new \DateTime("$cycleYear-12-31"); // 计算起始日到当年年初的周期偏移量 $daysToYearStart = abs($yearStart->diff($refZero)->format("%a")); $cyclesBeforeYearStart = max(0, floor($daysToYearStart / 28)); // 计算起始日到当年年末的周期偏移量 $daysToYearEnd = abs($yearEnd->diff($refZero)->format("%a")); $cyclesBeforeYearEnd = floor($daysToYearEnd / 28); // 判断当前总周期偏移量是否落在当前年份范围内 if ($totalCycles <= $cyclesBeforeYearEnd) { // 计算当年的周期序号,格式化为两位数字 $cycleNum = $totalCycles - $cyclesBeforeYearStart + self::REF_ZERO_CYCLE_NUM; $cycleNumStr = str_pad((string)$cycleNum, 2, "0", STR_PAD_LEFT); // 组合年份后两位与周期序号,得到最终编号 $yearStr = substr((string)$cycleYear, 2); $cycleId = $yearStr . $cycleNumStr; break; } // 若不在当前年份,进入下一年继续判断 $cycleYear++; } return [ 'target_date' => $today->format("Y/m/d"), 'latest_cycle_date' => $latestCycleDate->format("Y/m/d"), 'total_cycles_since_start' => $totalCycles, 'cycle_id' => $cycleId ]; } } // 测试调用(可替换传入指定日期,如"2023/12/29") $result = CycleCalculator::getCurrentCycleInfo(); echo "目标日期:" . $result['target_date'] . "\n"; echo "最近周期日期:" . $result['latest_cycle_date'] . "\n"; echo "起始至今总周期数:" . $result['total_cycles_since_start'] . "\n"; echo "周期编号:" . $result['cycle_id'] . "\n"; ?>
关键逻辑说明
- 总周期偏移量计算:通过日期差除以28取整,得到从起始日到目标日的周期偏移数(起始日对应偏移量0)
- 年份周期范围定位:逐年计算每个年份覆盖的周期偏移范围,判断当前总偏移量所属年份
- 周期序号生成:用总偏移量减去当年起始的偏移量,加上起始年份的初始序号(1),得到当年的周期序号并格式化为两位数字
- 编号组合:取年份后两位与两位周期序号拼接,生成符合要求的周期编号(如2201、2314等)
内容的提问来源于stack exchange,提问作者MB.
相关产品推荐
相关产品推荐

