From 60fc7f4a3e561063c3eb7e6685e0224f969624a7 Mon Sep 17 00:00:00 2001 From: Corey Taylor Date: Sun, 24 Sep 2023 03:50:17 -0500 Subject: [PATCH] Allow passing DatePeriod options to diffFiltered() --- src/Chronos.php | 28 ++++++++++++++++++---------- src/ChronosDate.php | 22 ++++++++++++++-------- tests/TestCase/Date/DiffTest.php | 16 ++++++++++++++++ tests/TestCase/DateTime/DiffTest.php | 16 ++++++++++++++++ 4 files changed, 64 insertions(+), 18 deletions(-) diff --git a/src/Chronos.php b/src/Chronos.php index 3cc8bad..9579eae 100644 --- a/src/Chronos.php +++ b/src/Chronos.php @@ -2301,13 +2301,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); @@ -2319,7 +2321,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)); }); @@ -2413,14 +2415,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); } /** @@ -2429,14 +2433,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); } /** @@ -2444,13 +2450,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); } /** @@ -2458,13 +2465,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 2c0730d..b2495e7 100644 --- a/src/ChronosDate.php +++ b/src/ChronosDate.php @@ -1409,13 +1409,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()); @@ -1430,7 +1432,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)); }); @@ -1501,14 +1503,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); } /** @@ -1516,13 +1520,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); } /** @@ -1530,13 +1535,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);