diff --git a/src/Chronos.php b/src/Chronos.php index 2c531b1..088f3e9 100644 --- a/src/Chronos.php +++ b/src/Chronos.php @@ -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); @@ -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)); }); @@ -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); } /** @@ -2430,14 +2434,16 @@ 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); } /** @@ -2445,13 +2451,14 @@ public function diffInHoursFiltered( * * @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); } /** @@ -2459,13 +2466,14 @@ public function diffInWeekdays(?DateTimeInterface $other = null, bool $absolute * * @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); } /** diff --git a/src/ChronosDate.php b/src/ChronosDate.php index b4d9cfe..8245df8 100644 --- a/src/ChronosDate.php +++ b/src/ChronosDate.php @@ -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()); @@ -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)); }); @@ -1509,14 +1511,16 @@ 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); } /** @@ -1524,13 +1528,14 @@ public function diffInDaysFiltered( * * @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); } /** @@ -1538,13 +1543,14 @@ public function diffInWeekdays(?ChronosDate $other = null, bool $absolute = true * * @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); } /** diff --git a/tests/TestCase/Date/DiffTest.php b/tests/TestCase/Date/DiffTest.php index b313409..ffa06bd 100644 --- a/tests/TestCase/Date/DiffTest.php +++ b/tests/TestCase/Date/DiffTest.php @@ -18,6 +18,7 @@ use Cake\Chronos\ChronosDate; use Cake\Chronos\Test\TestCase\TestCase; use Closure; +use DatePeriod; class DiffTest extends TestCase { @@ -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); diff --git a/tests/TestCase/DateTime/DiffTest.php b/tests/TestCase/DateTime/DiffTest.php index 15d5484..a82b0e7 100644 --- a/tests/TestCase/DateTime/DiffTest.php +++ b/tests/TestCase/DateTime/DiffTest.php @@ -18,6 +18,7 @@ use Cake\Chronos\DifferenceFormatter; use Cake\Chronos\Test\TestCase\TestCase; use Closure; +use DatePeriod; use DateTimeZone; class DiffTest extends TestCase @@ -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);