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

PHP中如何将带IsBlocked标记的日期数组转为可用区间数组?

合并可用日期为连续区间需求

我有一个覆盖2023年11月1日至11月30日的日期数组,其中11月3日至6日、11月15日至20日的日期标记为已锁定(IsBlocked=true)。需要将其中可用日期(IsBlocked=false)合并为连续的日期区间,输出包含start_date和end_date的目标数组。

原日期数组

Array
(
    [0] => Array
        (
            [date] => 2023-11-01
            [IsBlocked] => false
        )

    [1] => Array
        (
            [date] => 2023-11-02
            [IsBlocked] => false
        )

    [2] => Array
        (
            [date] => 2023-11-03
            [IsBlocked] => true
        )

    [3] => Array
        (
            [date] => 2023-11-04
            [IsBlocked] => true
        )

    [4] => Array
        (
            [date] => 2023-11-05
            [IsBlocked] => true
        )

    [5] => Array
        (
            [date] => 2023-11-06
            [IsBlocked] => true
        )

    [6] => Array
        (
            [date] => 2023-11-07
            [IsBlocked] => false
        )

    [7] => Array
        (
            [date] => 2023-11-08
            [IsBlocked] => false
        )

    [8] => Array
        (
            [date] => 2023-11-09
            [IsBlocked] => false
        )

    [9] => Array
        (
            [date] => 2023-11-10
            [IsBlocked] => false
        )

    [10] => Array
        (
            [date] => 2023-11-11
            [IsBlocked] => false
        )

    [11] => Array
        (
            [date] => 2023-11-12
            [IsBlocked] => false
        )

    [12] => Array
        (
            [date] => 2023-11-13
            [IsBlocked] => false
        )

    [13] => Array
        (
            [date] => 2023-11-14
            [IsBlocked] => false
        )

    [14] => Array
        (
            [date] => 2023-11-15
            [IsBlocked] => true
        )

    [15] => Array
        (
            [date] => 2023-11-16
            [IsBlocked] => true
        )

    [16] => Array
        (
            [date] => 2023-11-17
            [IsBlocked] => true
        )

    [17] => Array
        (
            [date] => 2023-11-18
            [IsBlocked] => true
        )

    [18] => Array
        (
            [date] => 2023-11-19
            [IsBlocked] => true
        )

    [19] => Array
        (
            [date] => 2023-11-20
            [IsBlocked] => true
        )

    [20] => Array
        (
            [date] => 2023-11-21
            [IsBlocked] => false
        )

    [21] => Array
        (
            [date] => 2023-11-22
            [IsBlocked] => false
        )

    [22] => Array
        (
            [date] => 2023-11-23
            [IsBlocked] => false
        )

    [23] => Array
        (
            [date] => 2023-11-24
            [IsBlocked] => false
        )

    [24] => Array
        (
            [date] => 2023-11-25
            [IsBlocked] => false
        )

    [25] => Array
        (
            [date] => 2023-11-26
            [IsBlocked] => false
        )

    [26] => Array
        (
            [date] => 2023-11-27
            [IsBlocked] => false
        )

    [27] => Array
        (
            [date] => 2023-11-28
            [IsBlocked] => false
        )

    [28] => Array
        (
            [date] => 2023-11-29
            [IsBlocked] => false
        )

    [29] => Array
        (
            [date] => 2023-11-30
            [IsBlocked] => false
        )

)

期望输出数组

Array
(
    [0] => Array
        (
            [start_date] => 2023-11-01
            [end_date] => 2023-11-02
        )
        
    [1] => Array
    (
        [start_date] => 2023-11-07
        [end_date] => 2023-11-14
    )

    [2] => Array
        (
            [start_date] => 2023-11-21
            [end_date] => 2023-11-30
        )
)

尝试过的代码(未实现需求)

foreach($dates as $calDay) {
   if($calDay['IsBlocked'] == "true") {
       $closeDates[] = $calDay['date'];
   } else {
       $openDates[] = $calDay['date'];
   }
}

解决方案

核心思路是遍历日期数组时,维护一个临时的连续区间,当遇到不可用日期或日期不连续时,将当前区间存入结果并开启新的区间。

实现代码

$dates = [
    // 此处放入你的原日期数组内容
];

$result = [];
$currentInterval = null;

foreach ($dates as $day) {
    // 跳过锁定的日期
    if ($day['IsBlocked'] === true) {
        // 如果当前有未完成的区间,先存入结果
        if ($currentInterval !== null) {
            $result[] = $currentInterval;
            $currentInterval = null;
        }
        continue;
    }

    $currentDate = new DateTime($day['date']);
    
    if ($currentInterval === null) {
        // 初始化新的区间
        $currentInterval = [
            'start_date' => $day['date'],
            'end_date' => $day['date']
        ];
    } else {
        // 检查当前日期是否是区间结束日期的下一天
        $nextDay = (new DateTime($currentInterval['end_date']))->modify('+1 day');
        if ($currentDate->format('Y-m-d') === $nextDay->format('Y-m-d')) {
            // 更新区间结束日期
            $currentInterval['end_date'] = $day['date'];
        } else {
            // 日期不连续,存入当前区间并开启新的
            $result[] = $currentInterval;
            $currentInterval = [
                'start_date' => $day['date'],
                'end_date' => $day['date']
            ];
        }
    }
}

// 遍历结束后,把最后一个未存入的区间加入结果
if ($currentInterval !== null) {
    $result[] = $currentInterval;
}

// 输出结果
print_r($result);

代码说明

  1. 初始化$result存储最终区间数组,$currentInterval存储当前正在构建的连续区间
  2. 遍历每个日期,遇到锁定日期时,若当前有未完成的区间则存入结果,然后跳过
  3. 对于可用日期:
    • 如果当前没有正在构建的区间,初始化新的区间
    • 如果有,检查当前日期是否是区间结束日期的下一天,是则更新结束日期;否则存入当前区间并开启新的
  4. 遍历结束后,确保最后一个区间被存入结果

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.16 06:52:02