PHP确定多个(n)日期时间范围彼此重叠的时间 [英] PHP Determine when multiple(n) datetime ranges overlap each other

查看:120
本文介绍了PHP确定多个(n)日期时间范围彼此重叠的时间的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有时间试图解决以下问题:



这是一个日历程序,给定了一组来自多个人的可用日期时间集,我需要弄清楚PHP中每个人可以使用的日期时间范围



可用性集:

  p1:start:2016-04-30 12:00,结束:\"-01-01 03:00

p2:start :2016-04-30 03:00,结束:\"-01-01 03:00

p3:start:2016-04-30 03:00,结束: 2016-04-30 13:31
开始:2016-04-30 15:26,结束:\"-01-01 03:00
/ pre>

我正在寻找一个可以调用的函数,它会告诉我同一时间内所有(p)个人可用的日期时间范围。 >

在上面的例子中,答案应该是:

  12:00  - > 2016-04-30 13:31 
2016-04-30 15:26 - >我已经找到这个类似的问题和答案


a href =http://stackoverflow.com/questions/24736000/datetime-determine-whether-multiplen-datetime-ranges-overlap-each-other-in-r>日期时间 - 确定是否重复(n)个日期时间范围



但我不知道是什么语言,并且无法在答案中翻译逻辑。

解决方案

实际上没有必要使用任何日期/时间处理来解决这个
问题。您可以利用这种格式的日期按字母顺序排列的事实。



我不知道这使得解决方案不那么复杂。这可能是更少
可读。但是,它比每一分钟的迭代快得多,所以如果表现是一个问题,你可以选择它。



你也可以使用
每个
single
数组
功能
在那里,这是很好的。



当然,由于我没有使用任何日期/时间功能,如果夏令时或不同时区的用户需要处理,则可能无法使用。

  $ availability = [
[
[2016-04-30 12:00,\"-01-01 03:00 ]
],
[
[2016-04-30 03:00,dressing-01 03:00]
],
[
[2016-04-30 03:00,2016-04-30 13:31],
[2016-04-30 15:26, 01 03:00]
]
];

//占位符数组以包含每个人都可用的时段。
$ periods = [];

while(true){
//选择每个人的最早日期,然后选择最新的这些
//日期。
$ start = array_reduce($ availability,function($ carry,$ ranges){
$ start = array_reduce($ ranges,function($ carry,$ range){
//这个人的最早的开始日期
return!$ carry?$ range [0]:min($ range [0],$ carry);
});
//最新的开始日期
return!$ carry?$ start:max($ start,$ carry);
});

//选择包含此日期的每个人的范围。
$ matching_ranges = array_filter(array_filter(function($ ranges)use($ start){
return current(array_filter($ ranges,function($ range)use($ start){
/ /范围从开始日期开始到结束。
return $ range [0]< = $ start&& $ range [1]> = $ start;
}));
},$可用性));

//如果任何人没有包含日期​​的范围,我们将完成
//并且可以退出循环。
if(count($ matching_ranges)< count($ availability)){
break;
}

//找到最早的范围的结束日期,这完成了我们每个人都可以参加的
//第一个时期。
$ end = array_reduce($ matching_ranges,function($ carry,$ range){
return!$ carry?$ range [1]:min($ range [1],$ carry);
});

//将其添加到我们的句点列表中。
$ periods [] = [$ start,$ end];

//删除在
//新的期限结束之前完成的任何可用性期间。
array_walk($ availability,function(& $ ranges)use($ end){
$ ranges = array_filter($ ranges,function($ range)use($ end){
return $ range [1]> $ end;
});
});
}

//以指定的格式输出答案。
foreach($ periods as $ period){
echo$ period [0] - > $ period [1] \\\
;
}
/ **
*输出:
*
* 2016-04-30 12:00 - > 2016-04-30 13:31
* 2016-04-30 15:26 - >纸张01 03:00
* /


I'm having a hell of a time trying to solve the following problem:

It's a calendar program where given a set of available datetime sets from multiple people, I need to figure out what datetime ranges everyone is available in PHP

Availability Sets:

p1: start: "2016-04-30 12:00", end: "2016-05-01 03:00"

p2: start: "2016-04-30 03:00", end: "2016-05-01 03:00"

p3: start: "2016-04-30 03:00", end: "2016-04-30 13:31"
    start: "2016-04-30 15:26", end: "2016-05-01 03:00"

I'm looking for a function that I can call that will tell me what datetime ranges all (p) people are available at the same time.

In the above example the answer should be:

2016-04-30 12:00 -> 2016-04-30 13:31
2016-04-30 15:26 -> 2016-05-01 03:00

I did find this similar question and answer Datetime -Determine whether multiple(n) datetime ranges overlap each other in R

But I have no idea what language that is, and have to unable to translate the logic in the answer.

解决方案

There's actually no need to use any date/time handling to solve this problem. You can exploit the fact that dates in this format are in alphabetical as well as chronological order.

I'm not sure this makes the solution any less complex. It's probably less readable this way. But it's considerably faster than iterating over every minute so you might choose it if performance is a concern.

You also get to use every single array function out there, which is nice.

Of course, because I haven't used any date/time functions, it might not work if Daylight Savings Time or users in different time zones need dealing with.

$availability = [
    [
        ["2016-04-30 12:00", "2016-05-01 03:00"]
    ],
    [
        ["2016-04-30 03:00", "2016-05-01 03:00"]
    ],
    [
        ["2016-04-30 03:00", "2016-04-30 13:31"],
        ["2016-04-30 15:26", "2016-05-01 03:00"]
    ]
];

// Placeholder array to contain the periods when everyone is available.
$periods = [];

while (true) {
    // Select every person's earliest date, then choose the latest of these
    // dates.
    $start = array_reduce($availability, function($carry, $ranges) {
        $start = array_reduce($ranges, function($carry, $range) {
            // This person's earliest start date.
            return !$carry ? $range[0] : min($range[0], $carry);
        });
        // The latest of all the start dates.
        return !$carry ? $start : max($start, $carry);
    });

    // Select each person's range which contains this date.
    $matching_ranges = array_filter(array_map(function($ranges) use($start) {
        return current(array_filter($ranges, function($range) use($start) {
            // The range starts before and ends after the start date.
            return $range[0] <= $start && $range[1] >= $start;
        }));
    }, $availability));

    // If anybody doesn't have a range containing the date, we're finished
    // and can exit the loop.
    if (count($matching_ranges) < count($availability)) {
        break;
    }

    // Find the earliest of the ranges' end dates, and this completes our
    // first period that everyone can attend.
    $end = array_reduce($matching_ranges, function($carry, $range) {
        return !$carry ? $range[1] : min($range[1], $carry);
    });

    // Add it to our list of periods.
    $periods[] = [$start, $end];

    // Remove any availability periods which finish before the end of this
    // new period.
    array_walk($availability, function(&$ranges) use ($end) {
        $ranges = array_filter($ranges, function($range) use($end) {
            return $range[1] > $end;
        });
    });
}

// Output the answer in the specified format.
foreach ($periods as $period) {
    echo "$period[0] -> $period[1]\n";
}
/**
 * Output:
 * 
 * 2016-04-30 12:00 -> 2016-04-30 13:31
 * 2016-04-30 15:26 -> 2016-05-01 03:00
 */

这篇关于PHP确定多个(n)日期时间范围彼此重叠的时间的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆