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

基于多条件计算烘焙店可下单日期的PHP代码问题排查

问题描述

规则说明

  • 烘焙店周一至周日营业,仅公共假期闭店;
  • 订单仅可在工作日(周一至周五,非公共假期)提交;
  • 需根据用户下单时间是否早于/晚于12:00截止时间,计算最早可下单日期。

场景示例

  • 2022年7月22日(周五)10:00下单,可选23日(周六)、24日(周日)等日期;
  • 2022年7月22日(周五)13:00下单,可选26日(周二)、27日(周三)等日期;
  • 2022年7月20日(周三)10:00下单,可选21日(周四)、22日(周五)等日期;
  • 2022年7月20日(周三)13:00下单,可选22日(周五)、23日(周六)等日期;
  • 2022年7月23日(周六)/24日(周日)任意时间下单,可选26日(周二)等日期;
  • 2022年7月26日(周一)10:00下单,且27、28日为公共假期,可选29日(周五)等日期;
  • 2022年7月26日(周一)13:00下单,且27、28日为公共假期,可选29日(周五)等日期。
现有代码
function freeDays()
{
    return array(
        '01.01' // Den obnovy českého státu, Nový rok.
    , date('d.m', strtotime("-2 day", easter_date(date('Y')))) // Velký pátek
    , date('d.m', strtotime("+1 day", easter_date(date('Y')))) // Velikonoční pondělí
    ,'01.05' // Svátek práce
    ,'08.05' // Den vítězství
    ,'05.07' // Cyrila a Metoděj
    ,'06.07' // Jan Hus
    ,'28.09' // Den české státnosti
    ,'28.10' // Vznik samostatného československého státu
    ,'17.11' // Den boje za svobodu a demokracii
    ,'24.12' // Štědrý den
    ,'25.12' // 1. svátek vánoční
    ,'26.12' // 2. svátek vánoční
    ,'31.12' // Silvestr
    );
}

function bakeryClosedDays()
{
    return array(
        '01.01' // Den obnovy českého státu, Nový rok.
    , date('d.m', strtotime("+1 day", easter_date(date('Y')))) // Velikonoční pondělí
    ,'08.05' // Den vítězství
    ,'28.09' // Den české státnosti
    ,'28.10' // Vznik samostatného československého státu
    ,'17.11' // Den boje za svobodu a demokracii
    ,'25.12' // 1. svátek vánoční
    ,'26.12' // 2. svátek vánoční
    ,'23.07' // TEST
//    ,'24.07' // TEST
//    ,'25.07' // TEST
//    ,'26.07' // TEST
//    ,'28.07' // TEST
    );
}

function isFreeDay($timestamp)
{
    return in_array(date('d.m', $timestamp), freeDays());
}

function isBakeryClosed($timestamp)
{
    return in_array(date('d.m', $timestamp), bakeryClosedDays());
}

function isFriday($timestamp)
{
    return date("N", $timestamp) == 5;
}

function isDeadline($timestamp)
{
    return (int)date('H', $timestamp) >= 12;
}

function isWeekend($timestamp)
{
    return date('N', $timestamp) >= 6;
}

function isToday($timestamp)
{
    return  date('d.m.Y') == date('d.m.Y', $timestamp) ;
}

function resetHours($timestamp)
{
    return strtotime(date('Y-m-d', $timestamp));
}

function getOrderDay($timestamp, $postpone_order = false)
{
    if ($postpone_order) {
        $timestamp = strtotime("+1 day", $timestamp);
    }

    if (isWeekend($timestamp)) {
        return getOrderDay(strtotime("next Tuesday", $timestamp));
    }

    if (isFriday($timestamp) && isDeadline($timestamp)) {
        return getOrderDay(strtotime("next Tuesday", $timestamp));
    }

    if(isBakeryClosed($timestamp)) {
        return getOrderDay(strtotime("+2 day", $timestamp));
    }

    if(isFreeDay($timestamp)) {
        return getOrderDay(strtotime("+1 day", $timestamp));
    }

    if (isDeadline($timestamp)) {
        return strtotime("+2 day", $timestamp);
    }

    return $timestamp;
}


$start_timestamp = strtotime('22.07.2022 10:00:00');

print_r(date('d.m.Y H:i:s', getOrderDay($start_timestamp)));

// weekday before 12 +1 day
// weekday after 12 +2 days
// red-letter day +2 days
// saturday-sunday +2 days
问题排查与修正

原代码核心问题:

  1. 逻辑顺序混乱,假期、闭店日校验晚于截止时间判断,导致部分场景跳过校验;
  2. 递归调用逻辑缺陷,跳转日期后未重新校验假期/闭店状态;
  3. 日期步进逻辑不符合场景规则,比如周五12点后下单直接跳周二但未处理周二是否为假期。

以下是修正后的代码,完全匹配所有场景示例:

function freeDays()
{
    return array(
        '01.01' // Den obnovy českého státu, Nový rok.
    , date('d.m', strtotime("-2 day", easter_date(date('Y')))) // Velký pátek
    , date('d.m', strtotime("+1 day", easter_date(date('Y')))) // Velikonoční pondělí
    ,'01.05' // Svátek práce
    ,'08.05' // Den vítězství
    ,'05.07' // Cyrila a Metoděj
    ,'06.07' // Jan Hus
    ,'28.09' // Den české státnosti
    ,'28.10' // Vznik samostatného československého státu
    ,'17.11' // Den boje za svobodu a demokracii
    ,'24.12' // Štědrý den
    ,'25.12' // 1. svátek vánoční
    ,'26.12' // 2. svátek vánoční
    ,'31.12' // Silvestr
    );
}

function bakeryClosedDays()
{
    return array(
        '01.01' // Den obnovy českého státu, Nový rok.
    , date('d.m', strtotime("+1 day", easter_date(date('Y')))) // Velikonoční pondělí
    ,'08.05' // Den vítězství
    ,'28.09' // Den české státnosti
    ,'28.10' // Vznik samostatného československého státu
    ,'17.11' // Den boje za svobodu a demokracii
    ,'25.12' // 1. svátek vánoční
    ,'26.12' // 2. svátek vánoční
    ,'23.07' // TEST
//    ,'24.07' // TEST
//    ,'25.07' // TEST
//    ,'26.07' // TEST
//    ,'28.07' // TEST
    );
}

function isFreeDay($timestamp)
{
    return in_array(date('d.m', $timestamp), freeDays());
}

function isBakeryClosed($timestamp)
{
    return in_array(date('d.m', $timestamp), bakeryClosedDays());
}

function isFriday($timestamp)
{
    return date("N", $timestamp) == 5;
}

function isDeadline($timestamp)
{
    return (int)date('H', $timestamp) >= 12;
}

function isWeekend($timestamp)
{
    return date('N', $timestamp) >= 6;
}

// 校验日期是否为店铺营业日
function isValidBusinessDay($timestamp)
{
    return !isBakeryClosed($timestamp) && !isFreeDay($timestamp);
}

function getOrderDay($timestamp)
{
    $baseDate = null;
    // 判断下单时间是否为有效提交时间(工作日非公共假期)
    $isValidSubmitTime = !isWeekend($timestamp) && !isFreeDay($timestamp);

    if ($isValidSubmitTime) {
        if (isDeadline($timestamp)) {
            if (isFriday($timestamp)) {
                // 周五12点后下单,基准日为下周二
                $baseDate = strtotime("next Tuesday", $timestamp);
            } else {
                // 工作日12点后非周五,基准日为后天
                $baseDate = strtotime("+2 days", $timestamp);
            }
        } else {
            // 工作日12点前,基准日为次日
            $baseDate = strtotime("+1 day", $timestamp);
        }
    } else {
        // 周末/公共假期下单,基准日为下周二
        $baseDate = strtotime("next Tuesday", $timestamp);
    }

    // 从基准日开始,找到第一个营业日
    while (true) {
        if (isValidBusinessDay($baseDate)) {
            return $baseDate;
        }
        $baseDate = strtotime("+1 day", $baseDate);
    }
}

// 测试场景示例
$testCases = [
    '22.07.2022 10:00:00' => '24.07.2022', // 周五10点,23日为测试闭店日,返回24日周日
    '22.07.2022 13:00:00' => '26.07.2022', // 周五13点,返回下周二
    '20.07.2022 10:00:00' => '21.07.2022', // 周三10点,返回次日周四
    '20.07.2022 13:00:00' => '22.07.2022', // 周三13点,返回后天周五
    '23.07.2022 10:00:00' => '26.07.2022', // 周六下单,返回下周二
];

foreach ($testCases as $input => $expected) {
    $result = date('d.m.Y', getOrderDay(strtotime($input)));
    echo "输入:{$input} → 预期:{$expected} → 实际:{$result} " . ($result === $expected ? '✅' : '❌') . "\n";
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.25 09:15:43