Devin Y
Devin Y

Reputation: 137

Getting non overlapping between two dates with Carbon

UseCase: Admin assigns tasks to People. Before we assign them we can see their tasks in a gantt chart. According to the task assign date and deadline, conflict days (overlap days) are generated between tasks.

enter image description here

I wrote this function to get overlapping dates between two dates. But now I need to get non overlapping days between two dates, below is the function I wrote.

$tasks = Assign_review_tasks::where('assigned_to', $employee)
                ->where('is_active', \Constants::$REVIEW_ACTIVE)
                ->whereNotNull('permit_id')->get();
            
            $obj['task'] = count($tasks);
            //  count($tasks));
            if (count($tasks) > 0) {
                if (count($tasks) > 1) {
                    $start_one = $tasks[count($tasks) - 1]->start_date;
                    $end_one = $tasks[count($tasks) - 1]->end_date;
                    $end_two = $tasks[count($tasks) - 2]->end_date;
                    $start_two = $tasks[count($tasks) - 2]->start_date;

                    if ($start_one <= $end_two && $end_one >= $start_two) { //If the dates overlap
                        $obj['day'] = Carbon::parse(min($end_one, $end_two))->diff(Carbon::parse(max($start_two, $start_one)))->days + 1; //return how many days overlap
                    } else {
                        $obj['day'] = 0;
                    }
                    // $arr[] = $obj;
                } else {
                    $obj['day'] = 0;
                }
            } else {
                $obj['day'] = 0;
            }
            $arr[] = $obj;

start_date and end_date are taken from database,

I tried modifying it to,

(Carbon::parse((min($end_one, $end_two))->add(Carbon::parse(max($start_two, $start_one))))->days)->diff(Carbon::parse(min($end_one, $end_two))->diff(Carbon::parse(max($start_two, $start_one)))->days + 1);

But it didn't work, in simple terms this is what I want,

Non conflicting days = (end1-start1 + end2-start2)- Current overlapping days

I'm having trouble translate this expression . Could you help me? Thanks in advance

Upvotes: 1

Views: 1200

Answers (1)

KyleK
KyleK

Reputation: 5056

before trying to reimplement complex stuff I recommend you take a look at enhanced-period for Carbon

composer require cmixin/enhanced-period

CarbonPeriod::diff macro method is what I think you're looking for:

use Carbon\CarbonPeriod;
use Cmixin\EnhancedPeriod;

CarbonPeriod::mixin(EnhancedPeriod::class);

$a = CarbonPeriod::create('2018-01-01', '2018-01-31');
$b = CarbonPeriod::create('2018-02-10', '2018-02-20');
$c = CarbonPeriod::create('2018-02-11', '2018-03-31');

$current = CarbonPeriod::create('2018-01-20', '2018-03-15');

foreach ($current->diff($a, $b, $c) as $period) {
  foreach ($period as $day) {
    echo $day . "\n";
  }
}

This will output all the days that are in $current but not in any of the other periods. (E.g. non-conflicting days)

Upvotes: 1

Related Questions