Skip to content

Commit

Permalink
Merge pull request #429 from cakephp/add-dateperiod-options
Browse files Browse the repository at this point in the history
Allow passing DatePeriod options to diffFiltered()
  • Loading branch information
othercorey authored Sep 25, 2023
2 parents 7ffdb16 + 60fc7f4 commit 900cfbd
Show file tree
Hide file tree
Showing 4 changed files with 64 additions and 18 deletions.
28 changes: 18 additions & 10 deletions src/Chronos.php
Original file line number Diff line number Diff line change
Expand Up @@ -2302,13 +2302,15 @@ public function isWithinNext(string|int $timeInterval): bool
* @param callable $callback The callback to use for filtering.
* @param \DateTimeInterface|null $other The instance to difference from.
* @param bool $absolute Get the absolute of the difference
* @param int $options DatePeriod options, {@see https://www.php.net/manual/en/class.dateperiod.php}
* @return int
*/
public function diffFiltered(
DateInterval $interval,
callable $callback,
?DateTimeInterface $other = null,
bool $absolute = true
bool $absolute = true,
int $options = 0
): int {
$start = $this;
$end = $other ?? static::now($this->tz);
Expand All @@ -2320,7 +2322,7 @@ public function diffFiltered(
$inverse = true;
}

$period = new DatePeriod($start, $interval, $end);
$period = new DatePeriod($start, $interval, $end, $options);
$vals = array_filter(iterator_to_array($period), function (DateTimeInterface $date) use ($callback) {
return $callback(static::instance($date));
});
Expand Down Expand Up @@ -2414,14 +2416,16 @@ public function diffInDays(?DateTimeInterface $other = null, bool $absolute = tr
* @param callable $callback The callback to use for filtering.
* @param \DateTimeInterface|null $other The instance to difference from.
* @param bool $absolute Get the absolute of the difference
* @param int $options DatePeriod options, {@see https://www.php.net/manual/en/class.dateperiod.php}
* @return int
*/
public function diffInDaysFiltered(
callable $callback,
?DateTimeInterface $other = null,
bool $absolute = true
bool $absolute = true,
int $options = 0
): int {
return $this->diffFiltered(new DateInterval('P1D'), $callback, $other, $absolute);
return $this->diffFiltered(new DateInterval('P1D'), $callback, $other, $absolute, $options);
}

/**
Expand All @@ -2430,42 +2434,46 @@ public function diffInDaysFiltered(
* @param callable $callback The callback to use for filtering.
* @param \DateTimeInterface|null $other The instance to difference from.
* @param bool $absolute Get the absolute of the difference
* @param int $options DatePeriod options, {@see https://www.php.net/manual/en/class.dateperiod.php}
* @return int
*/
public function diffInHoursFiltered(
callable $callback,
?DateTimeInterface $other = null,
bool $absolute = true
bool $absolute = true,
int $options = 0
): int {
return $this->diffFiltered(new DateInterval('PT1H'), $callback, $other, $absolute);
return $this->diffFiltered(new DateInterval('PT1H'), $callback, $other, $absolute, $options);
}

/**
* Get the difference in weekdays
*
* @param \DateTimeInterface|null $other The instance to difference from.
* @param bool $absolute Get the absolute of the difference
* @param int $options DatePeriod options, {@see https://www.php.net/manual/en/class.dateperiod.php}
* @return int
*/
public function diffInWeekdays(?DateTimeInterface $other = null, bool $absolute = true): int
public function diffInWeekdays(?DateTimeInterface $other = null, bool $absolute = true, int $options = 0): int
{
return $this->diffInDaysFiltered(function (Chronos $date) {
return $date->isWeekday();
}, $other, $absolute);
}, $other, $absolute, $options);
}

/**
* Get the difference in weekend days using a filter
*
* @param \DateTimeInterface|null $other The instance to difference from.
* @param bool $absolute Get the absolute of the difference
* @param int $options DatePeriod options, {@see https://www.php.net/manual/en/class.dateperiod.php}
* @return int
*/
public function diffInWeekendDays(?DateTimeInterface $other = null, bool $absolute = true): int
public function diffInWeekendDays(?DateTimeInterface $other = null, bool $absolute = true, int $options = 0): int
{
return $this->diffInDaysFiltered(function (Chronos $date) {
return $date->isWeekend();
}, $other, $absolute);
}, $other, $absolute, $options);
}

/**
Expand Down
22 changes: 14 additions & 8 deletions src/ChronosDate.php
Original file line number Diff line number Diff line change
Expand Up @@ -1417,13 +1417,15 @@ public function isWithinNext(string|int $timeInterval): bool
* @param callable $callback The callback to use for filtering.
* @param \Cake\Chronos\ChronosDate|null $other The instance to difference from.
* @param bool $absolute Get the absolute of the difference
* @param int $options DatePeriod options, {@see https://www.php.net/manual/en/class.dateperiod.php}
* @return int
*/
public function diffFiltered(
DateInterval $interval,
callable $callback,
?ChronosDate $other = null,
bool $absolute = true
bool $absolute = true,
int $options = 0
): int {
$start = $this;
$end = $other ?? new ChronosDate(Chronos::now());
Expand All @@ -1438,7 +1440,7 @@ public function diffFiltered(
// within the range. Sadly INCLUDE_END_DATE doesn't land until 8.2
$endTime = $end->native->modify('+1 second');

$period = new DatePeriod($start->native, $interval, $endTime);
$period = new DatePeriod($start->native, $interval, $endTime, $options);
$vals = array_filter(iterator_to_array($period), function (DateTimeInterface $date) use ($callback) {
return $callback(static::parse($date));
});
Expand Down Expand Up @@ -1509,42 +1511,46 @@ public function diffInDays(?ChronosDate $other = null, bool $absolute = true): i
* @param callable $callback The callback to use for filtering.
* @param \Cake\Chronos\ChronosDate|null $other The instance to difference from.
* @param bool $absolute Get the absolute of the difference
* @param int $options DatePeriod options, {@see https://www.php.net/manual/en/class.dateperiod.php}
* @return int
*/
public function diffInDaysFiltered(
callable $callback,
?ChronosDate $other = null,
bool $absolute = true
bool $absolute = true,
int $options = 0
): int {
return $this->diffFiltered(new DateInterval('P1D'), $callback, $other, $absolute);
return $this->diffFiltered(new DateInterval('P1D'), $callback, $other, $absolute, $options);
}

/**
* Get the difference in weekdays
*
* @param \Cake\Chronos\ChronosDate|null $other The instance to difference from.
* @param bool $absolute Get the absolute of the difference
* @param int $options DatePeriod options, {@see https://www.php.net/manual/en/class.dateperiod.php}
* @return int
*/
public function diffInWeekdays(?ChronosDate $other = null, bool $absolute = true): int
public function diffInWeekdays(?ChronosDate $other = null, bool $absolute = true, int $options = 0): int
{
return $this->diffInDaysFiltered(function (ChronosDate $date) {
return $date->isWeekday();
}, $other, $absolute);
}, $other, $absolute, $options);
}

/**
* Get the difference in weekend days using a filter
*
* @param \Cake\Chronos\ChronosDate|null $other The instance to difference from.
* @param bool $absolute Get the absolute of the difference
* @param int $options DatePeriod options, {@see https://www.php.net/manual/en/class.dateperiod.php}
* @return int
*/
public function diffInWeekendDays(?ChronosDate $other = null, bool $absolute = true): int
public function diffInWeekendDays(?ChronosDate $other = null, bool $absolute = true, int $options = 0): int
{
return $this->diffInDaysFiltered(function (ChronosDate $date) {
return $date->isWeekend();
}, $other, $absolute);
}, $other, $absolute, $options);
}

/**
Expand Down
16 changes: 16 additions & 0 deletions tests/TestCase/Date/DiffTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
use Cake\Chronos\ChronosDate;
use Cake\Chronos\Test\TestCase\TestCase;
use Closure;
use DatePeriod;

class DiffTest extends TestCase
{
Expand Down Expand Up @@ -209,6 +210,21 @@ public function testDiffFilteredNegativeWithSignWithSecondObject()
}, $dt2, false));
}

public function testDiffFilteredWithOptions()
{
$dt1 = ChronosDate::create(2000, 1, 1);
$dt2 = ChronosDate::create(2000, 1, 2);
$interval = Chronos::createInterval(days: 1);

$this->assertSame(1, $dt1->diffFiltered($interval, function ($dt) {
return $dt->day === 1;
}, $dt2));

$this->assertSame(0, $dt1->diffFiltered($interval, function ($dt) {
return $dt->day === 1;
}, $dt2, options: DatePeriod::EXCLUDE_START_DATE));
}

public function testDiffInWeekdaysPositive()
{
$dt = ChronosDate::create(2000, 1, 1);
Expand Down
16 changes: 16 additions & 0 deletions tests/TestCase/DateTime/DiffTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
use Cake\Chronos\DifferenceFormatter;
use Cake\Chronos\Test\TestCase\TestCase;
use Closure;
use DatePeriod;
use DateTimeZone;

class DiffTest extends TestCase
Expand Down Expand Up @@ -285,6 +286,21 @@ public function testDiffFilteredNegativeWithSignWithSecondObject()
}, $dt2, false));
}

public function testDiffFilteredWithOptions()
{
$dt1 = Chronos::create(2000, 1, 1);
$dt2 = Chronos::create(2000, 1, 2);
$interval = Chronos::createInterval(days: 1);

$this->assertSame(1, $dt1->diffFiltered($interval, function ($dt) {
return $dt->day === 1;
}, $dt2));

$this->assertSame(0, $dt1->diffFiltered($interval, function ($dt) {
return $dt->day === 1;
}, $dt2, options: DatePeriod::EXCLUDE_START_DATE));
}

public function testBug188DiffWithSameDates()
{
$start = Chronos::create(2014, 10, 8, 15, 20, 0);
Expand Down

0 comments on commit 900cfbd

Please sign in to comment.