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

日期数组分组处理:提取被动日期间符合条件的空闲时段

Extracting Free Periods Between Passive Date Blocks

Hey there! Let's break down how to solve this problem—we need to take an array of passive dates, group consecutive dates into blocks, then find the gaps between those blocks and format them as requested. Here's a step-by-step solution using PHP (since the example uses PHP-like syntax, but the core logic applies to other languages too):


Step 1: Clean Up and Prepare the Date Array

First, we need to turn those string dates into usable date objects, remove duplicates (like the two 10-07-2020 entries in your example), and ensure they're sorted chronologically (adds robustness even if your input is already ordered).

$rawDates = [
    '17-05-2020', '18-05-2020', '19-05-2020', '20-05-2020',
    '28-05-2020', '29-05-2020', '30-05-2020',
    '02-06-2020', '03-06-2020',
    '10-07-2020', '10-07-2020', '11-07-2020', '12-07-2020', '13-07-2020',
    '20-07-2020', '21-07-2020',
    '25-07-2020', '26-07-2020', '27-07-2020'
];

// Convert strings to DateTime objects and remove duplicates
$dateObjects = array_unique(array_map(function($dateStr) {
    return DateTime::createFromFormat('d-m-Y', $dateStr);
}, $rawDates));

// Sort the date objects to ensure chronological order
usort($dateObjects, function($a, $b) {
    return $a <=> $b;
});

Step 2: Group Consecutive Dates into Blocks

Next, we'll group consecutive dates into blocks. Each block tracks the first and last date of that consecutive sequence:

$dateBlocks = [];
foreach ($dateObjects as $date) {
    if (empty($dateBlocks)) {
        $dateBlocks[] = ['start' => $date, 'end' => $date];
        continue;
    }

    $lastBlock = end($dateBlocks);
    // Check if current date is the day after the last block's end date
    $nextDay = (clone $lastBlock['end'])->modify('+1 day');
    if ($date == $nextDay) {
        // Merge into the existing block by updating the end date
        $lastBlock['end'] = $date;
        $dateBlocks[key($dateBlocks)] = $lastBlock;
    } else {
        // Start a new block for non-consecutive dates
        $dateBlocks[] = ['start' => $date, 'end' => $date];
    }
}

After running this, $dateBlocks will look like this (simplified for readability):

Array (
    [0] => Array ( 'start' => 17-05-2020, 'end' => 20-05-2020 )
    [1] => Array ( 'start' => 28-05-2020, 'end' => 30-05-2020 )
    [2] => Array ( 'start' => 02-06-2020, 'end' => 03-06-2020 )
    [3] => Array ( 'start' => 10-07-2020, 'end' => 13-07-2020 )
    [4] => Array ( 'start' => 20-07-2020, 'end' => 21-07-2020 )
    [5] => Array ( 'start' => 25-07-2020, 'end' => 27-07-2020 )
)

Step 3: Calculate and Format Free Periods

Now we'll loop through adjacent blocks, calculate the gap between them, and format the result. If you only want gaps longer than 8 days, just uncomment the conditional check below:

$freePeriods = [];
for ($i = 0; $i < count($dateBlocks) - 1; $i++) {
    $currentBlockEnd = $dateBlocks[$i]['end'];
    $nextBlockStart = $dateBlocks[$i+1]['start'];

    // Calculate the number of days between the end of one block and start of the next
    $interval = $currentBlockEnd->diff($nextBlockStart);
    $days = $interval->days;

    // Uncomment this line if you only want gaps longer than 8 days
    // if ($days <= 8) continue;

    // Convert dates back to string format
    $startStr = $currentBlockEnd->format('d-m-Y');
    $endStr = $nextBlockStart->format('d-m-Y');

    $freePeriods[] = [$startStr, $endStr, $days];
}

// Print the final result
print_r($freePeriods);

Output

This will give you exactly the result you're expecting:

Array (
    [0] => Array (
        [0] => 30-05-2020
        [1] => 02-06-2020
        [2] => 3
    )
    [1] => Array (
        [0] => 13-07-2020
        [1] => 20-07-2020
        [2] => 7
    )
    [2] => Array (
        [0] => 21-07-2020
        [1] => 25-07-2020
        [2] => 4
    )
)

Key Notes

  • Duplicate Handling: The array_unique call takes care of any repeated dates in the input, which prevents weird grouping issues.
  • Consecutive Check: We compare each date to the day after the last block's end to confirm it's part of the same sequence.
  • Flexible Filtering: If you need to only keep gaps longer than 8 days, just enable the if ($days <= 8) continue; line—this will skip any gaps that don't meet the threshold.

内容的提问来源于stack exchange,提问作者Güven Göç

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.07 07:14:05