You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于日期计算28天重复周期的周期编号技术问题

解决方案

核心思路

周期编号采用「两位年份+两位周期序号」规则,需完成两点核心逻辑:

  1. 基于起始日至今的总周期数,定位当前周期所属年份
  2. 计算该年份内的周期序号,适配每年可能包含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";
?>

关键逻辑说明

  1. 总周期偏移量计算:通过日期差除以28取整,得到从起始日到目标日的周期偏移数(起始日对应偏移量0)
  2. 年份周期范围定位:逐年计算每个年份覆盖的周期偏移范围,判断当前总偏移量所属年份
  3. 周期序号生成:用总偏移量减去当年起始的偏移量,加上起始年份的初始序号(1),得到当年的周期序号并格式化为两位数字
  4. 编号组合:取年份后两位与两位周期序号拼接,生成符合要求的周期编号(如2201、2314等)

内容的提问来源于stack exchange,提问作者MB.

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.11 10:20:41