0

I want to find the amount of overlapping minutes given two DatePeriods.

For example,

  • I have $startDate1 and $endDate1 as the first date range.
  • I have $startDate2 and $endDate2 as the second date range.

(For demonstration sake, the format is 'Y-m-d H:i'. )

  • Suppose $startDate1 = '2015-09-11 09:15' and $endDate1 = '2015-09-13 11:30'.

  • Suppose $startDate2 = '2015-09-13 10:45' and $endDate2 = '2015-09-14 12:00'.

I expect a result of 45 minutes overlap. How can this be achieved?

This question was marked as duplicate but they are not the same. I'm looking for the amount of overlapping time in two DatePeriods not the difference between two dates. A "DatePeriod" consists of two dates and I'm looking for the amount of overlap (not difference) between two DatePeriods.

Sheepy
  • 17,324
  • 4
  • 45
  • 69
Luke James
  • 121
  • 13
  • 2
    This has already been answered: http://stackoverflow.com/questions/365191/how-to-get-time-difference-in-minutes-in-php – Andrew Coder Oct 21 '15 at 21:29
  • This does not answer my question. The example you gave me was not using two date periods it was only using two dates. A date period consists of two dates. – Luke James Oct 21 '15 at 21:38
  • Also, I'm not looking for the difference, I'm looking for the amount of overlapping time. – Luke James Oct 21 '15 at 21:42
  • @LukeJames surely you could use the answers in the linked topic to formulate your own solution using some logic e.g. if endDate1 > startDate2 then get the diff of them – scrowler Oct 22 '15 at 02:47

1 Answers1

0

Here is class DatePeriodsOverlap, which represent overlap of two periods. It's result is overlapping DatePeriod or Exception if there is no intersection.

Note: DatePeriod is traversable object, PT1M is duration of step to iterate. PT1M means one minute interval. Details about DateInterval object.

Example of usage and answer to the question, how to get overlapping in minutes:

<?php
$d1 = new DatePeriod(
    new DateTime('2015-09-11 09:15:00'),
    new DateInterval('PT1M'),
    new DateTime('2015-09-13 11:30:00')
);


$d2 = new DatePeriod(
    new DateTime('2015-09-13 10:45:00'), 
    new DateInterval('PT1M'),
    new DateTime('2015-09-14 12:00:00')
);

$overlapPeriod = (new DatePeriodsOverlap(
    $d1, 
    $d2, 
    new DateInterval('PT1M')) // PT1M - 1 minute interval, 
                              // P1D - 1 day interval
)->overlap();


$minutes = iterator_count($overlapPeriod); // 45 minutes

// interval in minutes without iterating
$overlapPeriod->getEndDate()
    ->diff($overlapPeriod->getStartDate())
    ->i; // is interval in minutes (H:i:s)


/**
 * Overlap of two periods
 */
class DatePeriodsOverlap {
  private $d1;
  private $d2;
  private $di; // DateInterval, default is 1 day

  /**
   * @param DatePeriod $d1 first period
   * @param DatePeriod $d2 second period
   * @param DateInterval $di interval measurement
   */
  public function __construct(
    DatePeriod $d1, 
    DatePeriod $d2, 
    DateInterval $di = null) 
  {
    $this->d1 = $d1;
    $this->d2 = $d2;
    $this->di = $di ?? new DateInterval('P1D');
  }

  /**
   * Returns new overlapping period
   *
   * @throws Exception if not overlapped
   * @return DatePeriod 
   */
  public function overlap() : DatePeriod 
  {
    $startOne = $this->d1->getStartDate();
    $endOne = $this->d1->getEndDate();

    $startTwo = $this->d2->getStartDate();
    $endTwo = $this->d2->getEndDate();

    //If the dates overlap
    if ($startOne < $endTwo && $endOne > $startTwo) 
    {
      return new DatePeriod(
        max($startTwo,$startOne), 
        $this->di,
        min($endOne,$endTwo)
      );
    }

    throw new Exception(
      "No overlap " .
      "[{$this->d1->getStartDate()->format('Y-m-d H:i:s')}-{$this->d1->getEndDate()->format('Y-m-d H:i:s')}] and " .
      "[{$this->d2->getStartDate()->format('Y-m-d H:i:s')}-{$this->d2->getEndDate()->format('Y-m-d H:i:s')}]"
    );
  }
}
agorlov
  • 1
  • 1