【问题标题】:Merge adjacent events from an array of dates合并日期数组中的相邻事件
【发布时间】:2020-12-15 22:39:36
【问题描述】:

我正在绞尽脑汁研究这个数学,尝试strtotime,添加天数,嵌套foreach,但结果一片空白。希望这里有人能引导我走向正确的方向。

我的用例是将事件添加到日历 (FullCalendar),我可以在其中指定事件的“开始”和“结束”日期。我有持续多天的事件,有时作为一个实心块,有时同一事件被分解成更小的块,但我希望使用“开始”和“结束”将相同变化的所有相邻日期合并为一个事件日期。不过,我的查询只返回天数列表。

结束日期应始终在末尾加上 +1 天,因为它只计算在内(例如,同时在 12 日和 13 日进行的活动的结束日期应为 14 日)。

2020-10-01,2020-10-02,2020-10-03,2020-10-04 应该是一个从 2020-10-01 开始到 2020-10-05 结束的区块。

2020-10-08,2020-10-09,2020-10-11,2020-12-13 应该是两个块,一个以 08 开始,以 10 结束,另一个以 12 开始,以结束14 个。

这是我的代码不起作用(只是为每天创建一个事件):

$finalCourses = array();
$counter = 0;

// Loop through courses
while($allCourses->have_posts()) { $allCourses->the_post();

    // ..and loop over each Courses variations..
    global $post;
    $product = new WC_Product_Variable($post->ID);
    $variations = $product->get_available_variations();

    foreach($variations as $variation) {
        // ..and then store each Course variation in a new array
        $variationID = $variation['variation_id'];
        $coursePrice = '£'.$variation['display_price'];
        $courseTitle = get_the_title().' - '.$coursePrice;

        // Get the comma separated list of dates in Y-m-d (2020-08-27) format
        $dates = explode(',', strip_tags(str_replace(array("\r", "\n"), '', $variation['variation_description'])));
                
        foreach($dates as $date) {
            $start = $date;
            $end = $start;
            
            // Now I'm stuck
            foreach($dates as $endTest) {
                if(date('Y-m-d', strtotime($endTest)) === date('Y-m-d', strtotime($end . "+1 day"))) {
                    $end = $endTest;
                } else {
                    $finalCourses[$counter] = array(
                        'id'     => $variationID,
                        'title'  => (string)$courseTitle,
                        'start'  => $start,
                        'end' => date('Y-m-d', strtotime($end . "+1 day"))
                    );
                    $counter++;
                    break;
                }
            }
        }
    }
}

我将输出编码为 JSON,目前看起来像这样(一门课程和两个变体 ID 541 和 542)。

{
id: 542,
title: "RYA Competent Crew - £300",
start: "2020-09-07",
end: "2020-09-08"
},
{
id: 542,
title: "RYA Competent Crew - £300",
start: "2020-09-08",
end: "2020-09-09"
},
{
id: 542,
title: "RYA Competent Crew - £300",
start: "2020-09-09",
end: "2020-09-10"
},
{
id: 542,
title: "RYA Competent Crew - £300",
start: "2020-09-10",
end: "2020-09-11"
},
{
id: 542,
title: "RYA Competent Crew - £300",
start: "2020-09-12",
end: "2020-09-13"
},
{
id: 541,
title: "RYA Competent Crew - £250",
start: "2020-08-31",
end: "2020-09-01"
},
{
id: 541,
title: "RYA Competent Crew - £250",
start: "2020-09-01",
end: "2020-09-02"
},
{
id: 541,
title: "RYA Competent Crew - £250",
start: "2020-09-02",
end: "2020-09-03"
},
{
id: 541,
title: "RYA Competent Crew - £250",
start: "2020-09-03",
end: "2020-09-04"
},
{
id: 541,
title: "RYA Competent Crew - £250",
start: "2020-09-04",
end: "2020-09-05"
}
]

如您所见,每一天都作为自己的事件输出,但同一变体 ID 的所有相邻日期应合并为一个。

如果有任何提示或指示,我将不胜感激。

非常感谢!

【问题讨论】:

  • $finalCourses 生成后是什么样子的?
  • 谢谢达伦,我已经添加了 JSON 编码 $finalCourses 数组的 JSON 输出。
  • 看起来您的$variationID 在整个循环中始终保持不变,是吗?如果是这样,你的意思是你应该有 2 个事件(作为块)从:#1 - 2020-08-31 to 2020-09-04#2 - 2020-09-07 to 2020-09-13 运行,对吗?
  • 从第一个 foreach 开始,变体 ID 保持不变。第一个while 循环遍历变体,但这应该不是问题。在变体 ID 542 上,2020-09-11 被跳过,将其分成两个块,就像日历屏幕截图中一样。第一周包含 541,第二周包含 542。542 中的间隔应该保留在那里,并且只有相邻的日子连接到一个日历事件。抱歉,这里的术语有点不对劲,我在 CMS 输出范围内工作。
  • ahhhh 所以活动不应该在周末举行 - 因此在2020-09-11 上进行拆分?

标签: php algorithm date sorting php-7


【解决方案1】:

从你所提到的 - 我想你几乎明白了!我能看到的唯一问题是您每次都在创建一个新的“事件”数组项,而不是更新原来的 :)

您最好比较从strtotime() 传递的时间戳,如下所示。

foreach ($dates as $endTest) {
    // compare the new date (if more recent [higher] than previous), should update it..
    if (strtotime($endTest) > strtotime($end . "+1 day")) {
        /**
         * update the event to set the end date, instead of re-creating it.
         */
        $finalCourses[$variationID]['end'] = $endTest;
    } else {
        // create event with the "$variationID" as the id we want to use...
        $finalCourses[$variationID] = array(
            'id' => $variationID,
            'title' => (string) $courseTitle,
            'start' => $start,
            'end' => date('Y-m-d', strtotime($end . "+1 day"))
        );
        $counter++;
        break;
    }
}

请注意;上面的代码仅作为一个示例,供您作为一般思路使用。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2022-10-13
    • 1970-01-01
    • 1970-01-01
    • 2020-05-27
    • 2010-11-18
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多