我有两个任意的日期范围,例如:
2019-01-01 - 2019-01-10
and
2019-01-06 - 2019-01-20
如何在PHP中找出这些日期范围重叠了多少天? (在上面的示例中是5天)
答案 0 :(得分:1)
我不确定您要做什么,但是请检查以下解决方案:
<?php
$date1 = strtotime('2019-01-01');
$date2 = strtotime('2019-01-10');
$date3 = strtotime('2019-01-06');
$date4 = strtotime('2019-01-20');
$dateDiff1 = $date2 - $date1;
$dateDiff2 = $date4 - $date3;
$finalDiff = $dateDiff2 - $dateDiff1;
echo round($finalDiff / (60 * 60 * 24));
返回:
5
的更多信息注意::仅当第二个日期始终大于第一个日期时,此选项才有效。您的问题不清楚。
答案 1 :(得分:1)
这是使用DateTime
和DateInterval
对象的解决方案:
$range1 = '2019-01-01 - 2019-01-10';
$range2 = '2019-01-06 - 2019-01-20';
list($start, $end) = explode(' - ', $range1);
$start1 = new DateTime($start);
$end1 = new DateTime($end);
list($start, $end) = explode(' - ', $range2);
$start2 = new DateTime($start);
$end2 = new DateTime($end);
if ($end1 > $start1) {
$overlap = $end1->diff(min($start2, $end2));
}
else {
$overlap = $start1->diff(min($start2, $end2));
}
echo "overlap is " . ($overlap->format('%a') + 1) . " days";
输出
overlap is 5 days
更新
这是代码的更强大的版本,它允许范围的任意重叠(包括一个完全包含在另一个中):
function range_overlap($range1, $range2) {
list($start, $end) = explode(' - ', $range1);
$start = new DateTime($start);
$end = new DateTime($end);
$start1 = min($start, $end);
$end1 = max($start, $end);
list($start, $end) = explode(' - ', $range2);
$start = new DateTime($start);
$end = new DateTime($end);
$start2 = min($start, $end);
$end2 = max($start, $end);
// check for special cases
if ($start1 >= $start2 && $end1 <= $end2) {
// range1 completely contained inside range2
$overlap = $start1->diff($end1);
}
elseif ($start2 >= $start1 && $end2 <= $end1) {
// range2 completely contained inside range1
$overlap = $start2->diff($end2);
}
elseif ($end2 > $end1) {
// range1 ends first
$overlap = $start2->diff($end1);
}
else {
// range2 ends first
$overlap = $start1->diff($end2);
}
// if overlap is < 0 then there is no overlap
$overlap_days = $overlap->invert ? 0 : ($overlap->format('%a') + 1);
echo "overlap is $overlap_days days\n";
}
可以这样称呼:
range_overlap('2019-01-01 - 2019-01-10', '2019-01-06 - 2019-01-20'); // 5 days
range_overlap('2019-01-01 - 2019-03-20', '2019-05-06 - 2019-04-20'); // no overlap
range_overlap('2019-01-10 - 2019-05-20', '2019-01-01 - 2019-05-20'); // 131 days
range_overlap('2019-01-06 - 2019-01-20', '2019-01-10 - 2019-01-01'); // 5 days
range_overlap('2019-01-30 - 2019-01-10', '2019-01-12 - 2019-01-15'); // 4 days
range_overlap('2019-02-01 - 2019-03-20', '2019-01-10 - 2019-02-28'); // 28 days
答案 2 :(得分:0)
这是我使用的函数:
function nightsInRange(\Datetime $arriveDate, \Datetime $departDate, \Datetime $rangeStart, \Datetime $rangeEnd) : int
{
// just use the Y-m-d portion of date
$arriveDate = clone $arriveDate;
$arriveDate->setTime(0,0,0);
$departDate = clone $departDate;
$departDate->setTime(0,0,0);
$rangeStart = clone $rangeStart;
$rangeStart->setTime(0,0,0);
$rangeEnd = clone $rangeEnd;
$rangeEnd->setTime(0,0,0);
if ($arriveDate >= $departDate) {
throw new \InvalidArgumentException("arriveDate must be BEFORE departDate");
}
if ($rangeStart > $rangeEnd) {
throw new \InvalidArgumentException("rangeEnd must be greater than or equal to rangeStart");
}
$arriveDateInRange = ($arriveDate >= $rangeStart && $arriveDate <= $rangeEnd);
$departDateInRange = ($departDate >= $rangeStart && $departDate <= $rangeEnd);
if ($arriveDateInRange && $departDateInRange) {
// both dates inside range
$nightsInRange = $arriveDate->diff($departDate)->days;
} elseif ($arriveDateInRange && !$departDateInRange) {
// arrive inside, depart outside
$nightsInRange = $arriveDate->diff($rangeEnd)->days + 1;
} elseif (!$arriveDateInRange && $departDateInRange) {
// arrive outside, depart inside
$nightsInRange = $departDate->diff($rangeStart)->days;
} elseif ($arriveDate <= $rangeStart && $departDate >= $rangeEnd) {
// arrive before rangeStart, depart after rangeEnd
//
// Note that we add 1 to the date diff to get the range length. For
// example, the range from 2018-11-01 to 2018-11-30 is 30 days (not 29).
// A range with same start and end dates (e.g. 2018-11-01 to 2018-11-01)
// would have a range length of 1 day.
//
$nightsInRange = $rangeStart->diff($rangeEnd)->days + 1;
} else {
// no overlap
$nightsInRange = 0;
}
return $nightsInRange;
}