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

PHP时间判断公交服务类型异常问题及简化方案咨询

问题:PHP时间判断客运服务类型不符合预期

我希望根据页面当前时间输出客运公司的服务类型,服务类型包括“Semidirecte (sd)”、“Pobles (p)”和“Exprés (e)”。我编写了基于DateTime类的PHP时间判断代码,但线上站点的显示结果不符合预期。以下是我的代码:

<?php 
$now = new DateTime(); 
$v0600 = new DateTime('6:00'); 
$v0630 = new DateTime('6:30'); 
$v0650 = new DateTime('6:50'); 
$v0705 = new DateTime('7:05'); 
$v0725 = new DateTime('7:25'); 
$v0755 = new DateTime('7:55'); 
$v0825 = new DateTime('8:25'); 
$v0840 = new DateTime('8:40'); 
$v0900 = new DateTime('9:00'); 
$v0925 = new DateTime('9:25'); 
$v1000 = new DateTime('10:00'); 
$v1020 = new DateTime('10:20'); 
$v1030 = new DateTime('10:30'); 
$v1115 = new DateTime('11:15'); 
$v1200 = new DateTime('12:00'); 
$v1210 = new DateTime('12:10'); 
$v1230 = new DateTime('12:30'); 
$v1300 = new DateTime('13:00'); 
$v1325 = new DateTime('13:25'); 
$v1400 = new DateTime('14:00'); 
$v1435 = new DateTime('14:35'); 
$v1450 = new DateTime('14:50'); 
$v1505 = new DateTime('15:05'); 
$v1525 = new DateTime('15:25'); 
$v1600 = new DateTime('16:00'); 
$v1620 = new DateTime('16:20'); 
$v1635 = new DateTime('16:35'); 
$v1700 = new DateTime('17:00'); 
$v1725 = new DateTime('17:25'); 
$v1805 = new DateTime('18:05'); 
$v1820 = new DateTime('18:20'); 
$v1835 = new DateTime('18:35'); 
$v1910 = new DateTime('19:10'); 
$v2000 = new DateTime('20:00'); 
$v2100 = new DateTime('21:00'); 
$v2125 = new DateTime('21:25'); 
$v2155 = new DateTime('21:55'); 
$v2210 = new DateTime('22:10'); 
$v2305 = new DateTime('23:05'); 
$v0500 = new DateTime('05:00'); 
$sd = Semidirecte; 
$p = Pobles; 
$e = Exprés; 
if ($now > $v0500 && $now < $v0600 or $now > $v0630 && $now < $v0650 or $now > $v0840 && $now < $v0900 or $now > $v0925 && $now < $v1000 or $now > $v1115 && $now < $v1200 or $now > $v1325 && $now < $v1400 or $now > $v1525 && $now < $v1600 or $now > $v1635 && $now < $v1700 or $now > $v1725 && $now < $v1805 or $now > $v1910 && $now < $v2000 or $now > $v2035 && $now < $v2100 or $now > $v2125 && $now < $v2155){ 
    echo $sd; 
} elseif ($now > $v0650 && $now < $v0705 or $now > $v0825 && $now < $v0840 or $now > $v1000 && $now < $v1020 or $now > $v1200 && $now < $v1210 or $now > $v1230 && $now < $v1300 or $now > $v1435 && $now < $v1450 or $now > $v1450 && $now < $v1505 or $now > $v1600 && $now < $v1620 or $now > $v1805 && $now < $v1820 or $now > $v2000 && $now < $v2010 or $now > $v2155 && $now < $v2210){ 
    echo $e; 
} elseif ($now > $v0600 && $now < $v0630 or $now > $v0705 && $now < $v0725 or $now > $v0725 && $now < $v0755 or $now > $v0755 && $now < $v0825 or $now > $v0900 && $now < $v0925 or $now > $v1020 && $now < $v1030 or $now > $v1030 && $now < $v1115 or $now > $v1210 && $now < $v1230 or $now > $v1300 && $now < $v1325 or $now > $v1400 && $now < $v1435 or $now > $v1505 && $now < $v1525 or $now > $v1620 && $now < $v1635 or $now > $v1700 && $now < $v1725 or $now > $v1820 && $now < $v1835 or $now > $v1835 && $now < $v1910 or $now > $v2010 && $now < $v2035 or $now > $v2100 && $now < $v2125 or $now > $v2210 && $now < $v2305){ 
    echo $p; 
} else { 
    echo "No data"; 
} 
?>

请问我的代码存在什么问题?是否有更简洁的实现方案?


问题分析与解决方案

一、你的代码存在的几个关键问题

  1. 字符串未加引号,触发常量解析错误
    你定义服务类型时直接写了$sd = Semidirecte;,这里的Semidirecte会被PHP当作常量处理,如果没有提前定义这个常量,PHP会抛出警告并将其当作字符串字面量处理(这是历史兼容行为,但非常不可靠)。正确的写法应该给字符串加上单引号或双引号:

    $sd = 'Semidirecte (sd)';
    $p = 'Pobles (p)';
    $e = 'Exprés (e)';
    
  2. 逻辑运算符优先级错误
    or的优先级比&&低,导致你的条件判断逻辑会出现意外结果。比如$now > $v0500 && $now < $v0600 or $now > $v0630 && $now < $v0650虽然看起来没问题,但复杂组合下容易出错。建议统一使用||替代or,或者给每个时间区间的条件加上括号,确保逻辑符合预期。

  3. 未定义的时间变量
    你的条件中用到了$v2035和$v2010,但代码里并没有初始化这两个DateTime对象,这会导致PHP抛出“Undefined variable”的错误,直接影响判断结果。

  4. 时间区间覆盖不全、存在重叠

    • 边界时间点(比如刚好6:00、6:30)没有被包含在任何区间内,会直接落到else分支输出"No data"。
    • 部分区间存在重复判断,比如$now > $v0725 && $now < $v0755和前面的$now > $v0705 && $now < $v0725是连续区间,但写法冗余,还可能出现遗漏。
  5. 代码冗余,维护成本高
    定义了几十个单独的DateTime变量,后续如果要调整时间区间,需要逐个修改,非常容易出错。

二、更简洁的实现方案

我们可以把时间区间和对应的服务类型整理成一个二维数组,然后遍历数组判断当前时间属于哪个区间,这样代码更清晰、易维护:

<?php
// 定义时间区间与服务类型的映射关系
$serviceIntervals = [
    ['start' => '05:00', 'end' => '06:00', 'type' => 'Semidirecte (sd)'],
    ['start' => '06:30', 'end' => '06:50', 'type' => 'Semidirecte (sd)'],
    ['start' => '08:40', 'end' => '09:00', 'type' => 'Semidirecte (sd)'],
    ['start' => '09:25', 'end' => '10:00', 'type' => 'Semidirecte (sd)'],
    ['start' => '11:15', 'end' => '12:00', 'type' => 'Semidirecte (sd)'],
    ['start' => '13:25', 'end' => '14:00', 'type' => 'Semidirecte (sd)'],
    ['start' => '15:25', 'end' => '16:00', 'type' => 'Semidirecte (sd)'],
    ['start' => '16:35', 'end' => '17:00', 'type' => 'Semidirecte (sd)'],
    ['start' => '17:25', 'end' => '18:05', 'type' => 'Semidirecte (sd)'],
    ['start' => '19:10', 'end' => '20:00', 'type' => 'Semidirecte (sd)'],
    ['start' => '20:35', 'end' => '21:00', 'type' => 'Semidirecte (sd)'],
    ['start' => '21:25', 'end' => '21:55', 'type' => 'Semidirecte (sd)'],
    
    ['start' => '06:50', 'end' => '07:05', 'type' => 'Exprés (e)'],
    ['start' => '08:25', 'end' => '08:40', 'type' => 'Exprés (e)'],
    ['start' => '10:00', 'end' => '10:20', 'type' => 'Exprés (e)'],
    ['start' => '12:00', 'end' => '12:10', 'type' => 'Exprés (e)'],
    ['start' => '12:30', 'end' => '13:00', 'type' => 'Exprés (e)'],
    ['start' => '14:35', 'end' => '14:50', 'type' => 'Exprés (e)'],
    ['start' => '14:50', 'end' => '15:05', 'type' => 'Exprés (e)'],
    ['start' => '16:00', 'end' => '16:20', 'type' => 'Exprés (e)'],
    ['start' => '18:05', 'end' => '18:20', 'type' => 'Exprés (e)'],
    ['start' => '20:00', 'end' => '20:10', 'type' => 'Exprés (e)'],
    ['start' => '21:55', 'end' => '22:10', 'type' => 'Exprés (e)'],
    
    ['start' => '06:00', 'end' => '06:30', 'type' => 'Pobles (p)'],
    ['start' => '07:05', 'end' => '07:25', 'type' => 'Pobles (p)'],
    ['start' => '07:25', 'end' => '07:55', 'type' => 'Pobles (p)'],
    ['start' => '07:55', 'end' => '08:25', 'type' => 'Pobles (p)'],
    ['start' => '09:00', 'end' => '09:25', 'type' => 'Pobles (p)'],
    ['start' => '10:20', 'end' => '10:30', 'type' => 'Pobles (p)'],
    ['start' => '10:30', 'end' => '11:15', 'type' => 'Pobles (p)'],
    ['start' => '12:10', 'end' => '12:30', 'type' => 'Pobles (p)'],
    ['start' => '13:00', 'end' => '13:25', 'type' => 'Pobles (p)'],
    ['start' => '14:00', 'end' => '14:35', 'type' => 'Pobles (p)'],
    ['start' => '15:05', 'end' => '15:25', 'type' => 'Pobles (p)'],
    ['start' => '16:20', 'end' => '16:35', 'type' => 'Pobles (p)'],
    ['start' => '17:00', 'end' => '17:25', 'type' => 'Pobles (p)'],
    ['start' => '18:20', 'end' => '18:35', 'type' => 'Pobles (p)'],
    ['start' => '18:35', 'end' => '19:10', 'type' => 'Pobles (p)'],
    ['start' => '20:10', 'end' => '20:35', 'type' => 'Pobles (p)'],
    ['start' => '21:00', 'end' => '21:25', 'type' => 'Pobles (p)'],
    ['start' => '22:10', 'end' => '23:05', 'type' => 'Pobles (p)'],
];

$now = new DateTime();
$serviceType = "No data";

// 遍历区间判断
foreach ($serviceIntervals as $interval) {
    $start = new DateTime($interval['start']);
    $end = new DateTime($interval['end']);
    // 包含边界时间点,比如刚好等于start或end时也匹配
    if ($now >= $start && $now <= $end) {
        $serviceType = $interval['type'];
        break; // 找到匹配的区间就停止遍历
    }
}

echo $serviceType;
?>

这个方案的优势:

  • 可读性强:所有时间区间和对应服务类型一目了然,后续调整只需修改数组即可。
  • 逻辑清晰:遍历判断避免了复杂的多条件组合,减少逻辑错误概率。
  • 易维护:新增或修改时间区间时,只需在数组中添加或修改一行数据,无需调整大量条件判断。
  • 覆盖边界:使用>=和<=确保边界时间点也能被正确匹配,不会落到else分支。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 06:44:09