Skip to content

Commit

Permalink
New feature: split() with backwards option
Browse files Browse the repository at this point in the history
  • Loading branch information
bpolaszek committed Sep 6, 2017
1 parent 2ccf17c commit f02248f
Show file tree
Hide file tree
Showing 2 changed files with 92 additions and 1 deletion.
31 changes: 30 additions & 1 deletion src/Period.php
Original file line number Diff line number Diff line change
Expand Up @@ -877,7 +877,7 @@ public function merge(Period $arg)
}

/**
* Split a Period by a given interval
* Split a Period by a given interval (from start to end)
*
* The interval can be
* <ul>
Expand Down Expand Up @@ -905,6 +905,35 @@ public function split($interval)
} while ($startDate < $this->endDate);
}

/**
* Split a Period by a given interval (from end to start)
*
* The interval can be
* <ul>
* <li>a DateInterval object</li>
* <li>an int interpreted as the duration expressed in seconds.</li>
* <li>a string in a format supported by DateInterval::createFromDateString</li>
* </ul>
*
* @param DateInterval|int|string $interval The interval
*
* @return Generator|Period[]
*/
public function splitBackwards($interval)
{
$endDate = $this->endDate;
$interval = static::filterDateInterval($interval);
do {
$startDate = $endDate->sub($interval);
if ($startDate < $this->startDate) {
$startDate = $this->startDate;
}
yield new static($startDate, $endDate);

$endDate = $startDate;
} while ($endDate > $this->startDate);
}

/**
* Computes the intersection between two Period objects.
*
Expand Down
62 changes: 62 additions & 0 deletions test/PeriodTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,68 @@ public function testSplitWithInconsistentInterval()
$this->assertEquals(14400, $last->getTimestampInterval());
}

public function testSplitData()
{
$period = Period::createFromDuration(new DateTime('2015-01-01'), '3 days');
$range = $period->split('1 day');
$result = array_map(function (Period $range) {
return [
'start' => $range->getStartDate()->format('Y-m-d H:i:s'),
'end' => $range->getEndDate()->format('Y-m-d H:i:s')
];
}, iterator_to_array($range));
$expected = [
[
'start' => '2015-01-01 00:00:00',
'end' => '2015-01-02 00:00:00',
],
[
'start' => '2015-01-02 00:00:00',
'end' => '2015-01-03 00:00:00',
],
[
'start' => '2015-01-03 00:00:00',
'end' => '2015-01-04 00:00:00',
],
];
$this->assertSame($expected, $result);
}

public function testSplitDataBackwards()
{
$period = Period::createFromDuration(new DateTime('2015-01-01'), '3 days');
$range = $period->splitBackwards('1 day');
$result = array_map(function (Period $range) {
return [
'start' => $range->getStartDate()->format('Y-m-d H:i:s'),
'end' => $range->getEndDate()->format('Y-m-d H:i:s')
];
}, iterator_to_array($range));
$expected = [
[
'start' => '2015-01-03 00:00:00',
'end' => '2015-01-04 00:00:00',
],
[
'start' => '2015-01-02 00:00:00',
'end' => '2015-01-03 00:00:00',
],
[
'start' => '2015-01-01 00:00:00',
'end' => '2015-01-02 00:00:00',
],
];
$this->assertSame($expected, $result);
}

public function testSplitBackwardsWithInconsistentInterval()
{
$period = Period::createFromDuration('2010-01-01', '1 DAY');
$range = iterator_to_array($period->splitBackwards('10 HOURS'));
$last = array_pop($range);
$this->assertEquals(14400, $last->getTimestampInterval());
}

public function testSetState()
{
if (!method_exists(DateTimeImmutable::class, '__set_state')) {
Expand Down

0 comments on commit f02248f

Please sign in to comment.