Php 涵盖输入日期范围内所有日期的日期范围组合
我想找到与输入日期范围重叠的所有可能的日期范围组合。例如,如果用户输入2013/01/10至2013/01/25,我有以下日期范围:Php 涵盖输入日期范围内所有日期的日期范围组合,php,algorithm,Php,Algorithm,我想找到与输入日期范围重叠的所有可能的日期范围组合。例如,如果用户输入2013/01/10至2013/01/25,我有以下日期范围: 2013/01/08 to 2013/01/10 2013/01/09 to 2013/01/15 2013/01/10 to 2013/01/20 2013/01/18 to 2013/01/27 2013/01/14 to 2013/01/19 2013/01/19 to 2013/01/25 2013/01/14 to 2013/01/26 2013/01/
2013/01/08 to 2013/01/10
2013/01/09 to 2013/01/15
2013/01/10 to 2013/01/20
2013/01/18 to 2013/01/27
2013/01/14 to 2013/01/19
2013/01/19 to 2013/01/25
2013/01/14 to 2013/01/26
2013/01/10 to 2013/01/26
我想找出与输入日期(2013/01/10至2013/01/25)重叠的上述日期的所有可能组合
与输入日期重叠的日期范围有两个示例:
{2013/01/09 to 2013/01/15, 2013/01/14 to 2013/01/26}
{2013/01/09 to 2013/01/15, 2013/01/14 to 2013/01/19, 2013/01/19 to 2013/01/25}
我没有列出与输入日期范围重叠的所有可能的日期范围我想找到涵盖输入日期范围内所有日期的日期范围组合!,如果你看两个例子,我将日期范围合并为涵盖输入日期的所有日期
我不想检查输入日期范围为2的一个日期,如果日期范围包括输入日期的所有日期,或者是否!,我想组合日期范围,以查找所有可能的日期范围组合,这些组合涵盖输入日期范围的所有日期。
我想要一个算法来找到所有可能的日期组合,覆盖输入日期范围内的所有日期。
有什么快速算法可以解决这个问题吗?我又添加了几个数据项,使它更有趣:
$start = strtotime('2013/01/10');
$end = strtotime('2013/01/25');
$range[0]['start'] = "2013/01/08";
$range[0]['end'] = "2013/01/10";
$range[1]['start'] = "2013/01/09";
$range[1]['end'] = "2013/01/15";
$range[2]['start'] = "2013/01/10";
$range[2]['end'] = "2013/01/20";
$range[3]['start'] = "2013/01/18";
$range[3]['end'] = "2013/01/27";
$range[4]['start'] = "2013/01/14";
$range[4]['end'] = "2013/01/19";
$range[5]['start'] = "2013/01/19";
$range[5]['end'] = "2013/01/25";
$range[6]['start'] = "2013/01/14";
$range[6]['end'] = "2013/01/26";
$range[7]['start'] = "2013/01/10";
$range[7]['end'] = "2013/01/26";
$range[8]['start'] = "2013/01/9";
$range[8]['end'] = "2013/01/15";
$range[9]['start'] = "2013/01/13";
$range[9]['end'] = "2013/01/19";
$heads = array();
$tails = array();
$combos = array();
$h = 0;
foreach ($range as $key => $value){
$r1 = strtotime($value['start']);
$r2 = strtotime($value['end']);
if ($r1 <= $start && $r2 >= $end){
$combos[] = $key;
} elseif($r1 <= $start && $r2 > $start) {
$heads[$h]['r1'] = $r1;
$heads[$h]['r2'] = $r2;
$heads[$h]['seq'] = $key;
$h++;
} elseif($r1 > $start && $r1 < $end && $r1 < $r2) {
$tails[$key]['r1'] = $r1;
$tails[$key]['r2'] = $r2;
$tails[$key]['seq'] = $key;
}
}
while (count($tails) > 0){
$heads2 = array();
$tails2 = array();
$h2 = 0;
foreach ($heads as $key1 => $value1){
foreach ($tails as $key2 => $value2){
if (($value1['r1'] < $value2['r1']) && ($value1['r2'] >= $value2['r1']) && ($value1['r2'] < $value2['r2'])){
$seq = $value1['seq'].':'.$value2['seq'];
//keep tail alive, but don't change key
$tails2[$key2]['r1'] = $value2['r1'];
$tails2[$key2]['r2'] = $value2['r2'];
$tails2[$key2]['seq'] = $key2;
if ($value2['r2'] >= $end){
$combos[] = $seq;
} else {
$heads2[$h2]['r1'] = $value1['r2'];
$heads2[$h2]['r2'] = $value2['r2'];
$heads2[$h2]['seq'] = $seq;
$h2++;
}
}
}
}
$heads = $heads2;
$tails = $tails2;
}
这将显示以下内容:
2013/01/10 - 2013/01/26
2013/01/09 - 2013/01/15; 2013/01/14 - 2013/01/26
2013/01/10 - 2013/01/20; 2013/01/18 - 2013/01/27
2013/01/10 - 2013/01/20; 2013/01/19 - 2013/01/25
2013/01/10 - 2013/01/20; 2013/01/14 - 2013/01/26
2013/01/9 - 2013/01/15; 2013/01/14 - 2013/01/26
2013/01/09 - 2013/01/15; 2013/01/14 - 2013/01/19; 2013/01/18 - 2013/01/27
2013/01/09 - 2013/01/15; 2013/01/14 - 2013/01/19; 2013/01/19 - 2013/01/25
2013/01/09 - 2013/01/15; 2013/01/13 - 2013/01/19; 2013/01/18 - 2013/01/27
2013/01/09 - 2013/01/15; 2013/01/13 - 2013/01/19; 2013/01/19 - 2013/01/25
2013/01/9 - 2013/01/15; 2013/01/14 - 2013/01/19; 2013/01/18 - 2013/01/27
2013/01/9 - 2013/01/15; 2013/01/14 - 2013/01/19; 2013/01/19 - 2013/01/25
2013/01/9 - 2013/01/15; 2013/01/13 - 2013/01/19; 2013/01/18 - 2013/01/27
2013/01/9 - 2013/01/15; 2013/01/13 - 2013/01/19; 2013/01/19 - 2013/01/25
如果您可以找到
2013-01-09至2013-01-15
,我不确定为什么列表中缺少2013-01-09至2013-01-15
,但您可以根据需要修改下面的此类
$range = [
new DateManager("2013/01/08", "2013/01/10"),
new DateManager("2013/01/09", "2013/01/15"),
new DateManager("2013/01/10", "2013/01/20"),
new DateManager("2013/01/18", "2013/01/27"),
new DateManager("2013/01/14", "2013/01/19"),
new DateManager("2013/01/19", "2013/01/25"),
new DateManager("2013/01/14", "2013/01/26"),
new DateManager("2013/01/10", "2013/01/26")
];
$find = new DateManager("2013/01/10", "2013/01/25");
foreach($range as $date) {
$find->overlap($date) && print($date->getRange() . PHP_EOL);
}
输出
2013/01/09 to 2013/01/15
2013/01/10 to 2013/01/20
2013/01/14 to 2013/01/19
2013/01/19 to 2013/01/25
阶级
class DateManager {
private $start, $end;
function __construct($start, $end, $format = "Y/m/d") {
$this->start = $start instanceof DateTime ? $start : DateTime::createFromFormat($format, $start);
$this->end = $end instanceof DateTime ? $end : DateTime::createFromFormat($format, $end);
}
function getStart() {
return $this->start;
}
function getEnd() {
return $this->end;
}
function getRange($format = "Y/m/d") {
return sprintf("%s to %s ", $this->start->format($format), $this->end->format($format));
}
function between(DateManager $date) {
return $date->getStart() >= $this->getStart() && $this->getEnd() <= $date->end;
}
function overlap(DateManager $date) {
return (($date->getStart() >= $this->getStart() || $date->getEnd() > $this->getStart()) && $this->getEnd() >= $date->getEnd());
}
}
类数据管理器{
私人$开始$结束;
函数构造($start,$end,$format=“Y/m/d”){
$this->start=$start instanceof DateTime?$start:DateTime::createFromFormat($format,$start);
$this->end=$end instanceof DateTime?$end:DateTime::createFromFormat($format,$end);
}
函数getStart(){
返回$this->start;
}
函数getEnd(){
返回$this->end;
}
函数getRange($format=“Y/m/d”){
返回sprintf(“%s到%s”,$this->start->format($format),$this->end->format($format));
}
函数介于(DateManager$date){
返回$date->getStart()>=$this->getStart()&&&$this->getEnd()end;
}
函数重叠(DateManager$date){
return(($date->getStart()>=$this->getStart()|124;$date->getEnd()>$this->getStart())和&$this->getEnd()>=$date->getEnd());
}
}
将两个(开始、结束)日期转换为系统时间(从1/1/70开始,步长为1s),然后-运行步长为24*60*60的循环。如果需要,将每个值解码为可打印的形式。到目前为止你做了什么?对我来说,这似乎是区间树的一个合适的用例。为什么列表中缺少2013/01/10到2013/01/20
?@Baba-我认为这些只是示例,不包括所有示例。请注意,列表中有14到26个字符,超过了25个字符。因此,唯一可能不合格的是8到10,但这取决于重叠的定义。如果会议在10号结束,而乔在10号会议的最后一分钟出现,这是重叠吗?@Baba,因为我没有列出所有可能与输入日期范围重叠的日期范围。我只给出了两个与输入日期范围重叠的日期范围的示例。我想合并覆盖所有输入日期范围的所有日期范围。我想找到所有可能的日期范围组合,涵盖输入日期范围的所有日期。找到所有可能的组合是这个postfor(time_t i1=start;i1class DateManager {
private $start, $end;
function __construct($start, $end, $format = "Y/m/d") {
$this->start = $start instanceof DateTime ? $start : DateTime::createFromFormat($format, $start);
$this->end = $end instanceof DateTime ? $end : DateTime::createFromFormat($format, $end);
}
function getStart() {
return $this->start;
}
function getEnd() {
return $this->end;
}
function getRange($format = "Y/m/d") {
return sprintf("%s to %s ", $this->start->format($format), $this->end->format($format));
}
function between(DateManager $date) {
return $date->getStart() >= $this->getStart() && $this->getEnd() <= $date->end;
}
function overlap(DateManager $date) {
return (($date->getStart() >= $this->getStart() || $date->getEnd() > $this->getStart()) && $this->getEnd() >= $date->getEnd());
}
}