diff --git a/src/BusinessTime.php b/src/BusinessTime.php index 93d618c..98ba9e9 100644 --- a/src/BusinessTime.php +++ b/src/BusinessTime.php @@ -46,7 +46,22 @@ public function isBusinessTime(): bool */ public function isBusinessDay(): bool { - return $this->startOfBusinessDay()->isSameDay($this); + // Must be a business day if it's business time right now. + if ($this->isBusinessTime()) { + return true; + } + + // Iterate from the beginning of the day until we hit business time. + $time = $this->copy()->startOfDay(); + $end = $this->copy()->endOfDay(); + while ($time->lt($end)) { + if ($time->isBusinessTime()) { + return true; + } + $time = $time->add($this->precision()); + } + + return false; } /** @@ -106,6 +121,11 @@ public function addBusinessDays(float $businessDaysToAdd): self $next = $next->add($this->precision()); } + // Ensure we always end on a business day. + while (!$next->isBusinessDay()) { + $next = $next->addDay(); + } + return $next; } @@ -161,6 +181,11 @@ public function subBusinessDays(float $businessDaysToSub): self } } + // Ensure we always end on a business day. + while (!$prev->isBusinessDay()) { + $prev = $prev->subDay(); + } + return $prev; } diff --git a/tests/Unit/BusinessTime/AddBusinessDaysTest.php b/tests/Unit/BusinessTime/AddBusinessDaysTest.php index 44bdcb8..76c0f79 100644 --- a/tests/Unit/BusinessTime/AddBusinessDaysTest.php +++ b/tests/Unit/BusinessTime/AddBusinessDaysTest.php @@ -57,6 +57,7 @@ public function addBusinessDayProvider(): array ['Friday 2018-05-18 14:00', 'Monday 2018-05-21 14:00'], ['Saturday 2018-05-19 15:00', 'Monday 2018-05-21 17:00'], ['Sunday 2018-05-20 16:00', 'Monday 2018-05-21 17:00'], + ['Friday 2019-06-28 00:00', 'Monday 2019-07-01 00:00'], ]; } @@ -108,8 +109,14 @@ public function addBusinessDaysProvider(): array ['Monday 2018-05-14 09:00', 1.5, 'Tuesday 2018-05-15 13:00'], ['Monday 2018-05-14 09:00', 1.75, 'Tuesday 2018-05-15 15:00'], ['Monday 2018-05-14 09:00', 2, 'Wednesday 2018-05-16 09:00'], - // From Friday evening. + // From Friday morning. ['Friday 2018-05-18 00:00', 0, 'Friday 2018-05-18 00:00'], + ['Friday 2018-05-18 00:00', 0.25, 'Friday 2018-05-18 11:00'], + ['Friday 2018-05-18 00:00', 0.5, 'Friday 2018-05-18 13:00'], + ['Friday 2018-05-18 00:00', 0.75, 'Friday 2018-05-18 15:00'], + ['Friday 2018-05-18 00:00', 1, 'Monday 2018-05-21 00:00'], + ['Friday 2018-05-18 00:00', 1.25, 'Monday 2018-05-21 11:00'], + // From Friday evening. ['Friday 2018-05-18 17:00', 0, 'Friday 2018-05-18 17:00'], ['Friday 2018-05-18 17:00', 0.25, 'Monday 2018-05-21 11:00'], ['Friday 2018-05-18 17:00', 0.5, 'Monday 2018-05-21 13:00'], @@ -133,4 +140,19 @@ public function addBusinessDaysProvider(): array ['Friday 2018-05-18 17:00', -2, 'Wednesday 2018-05-16 17:00'], ]; } + + /** + * The addBusinessDay method should always return a business day. + */ + public function testAlwaysEndsOnBusinessDay() + { + // Given we have a business time for Friday; + $businessTime = new BusinessTime('Friday'); + + // When we add one business day to it; + $addDay = $businessTime->addBusinessDay(); + + // Then it should be Monday. + self::assertEquals('Monday', $addDay->format('l')); + } } diff --git a/tests/Unit/BusinessTime/SubBusinessDaysTest.php b/tests/Unit/BusinessTime/SubBusinessDaysTest.php index e08c466..c460cca 100644 --- a/tests/Unit/BusinessTime/SubBusinessDaysTest.php +++ b/tests/Unit/BusinessTime/SubBusinessDaysTest.php @@ -58,6 +58,7 @@ public function subBusinessDayProvider(): array ['Monday 2018-05-21 13:00', 'Friday 2018-05-18 13:00'], ['Sunday 2018-05-20 11:00', 'Friday 2018-05-18 09:00'], ['Saturday 2018-05-19 10:00', 'Friday 2018-05-18 09:00'], + ['Monday 2018-05-21 17:00', 'Friday 2018-05-18 17:00'], ]; } @@ -114,6 +115,19 @@ public function subBusinessDaysProvider(): array ['Monday 2018-05-21 09:00', 1.5, 'Thursday 2018-05-17 13:00'], ['Monday 2018-05-21 09:00', 1.75, 'Thursday 2018-05-17 11:00'], ['Monday 2018-05-21 09:00', 2, 'Thursday 2018-05-17 09:00'], + // From Monday evening. + ['Monday 2018-05-21 17:00', 0, 'Monday 2018-05-21 17:00'], + ['Monday 2018-05-21 18:00', 0, 'Monday 2018-05-21 18:00'], + ['Monday 2018-05-21 18:00', 0.25, 'Monday 2018-05-21 15:00'], + ['Monday 2018-05-21 18:00', 0.5, 'Monday 2018-05-21 13:00'], + ['Monday 2018-05-21 18:00', 0.75, 'Monday 2018-05-21 11:00'], + ['Monday 2018-05-21 18:00', 1, 'Friday 2018-05-18 18:00'], + ['Monday 2018-05-21 18:00', 1.25, 'Friday 2018-05-18 15:00'], + ['Monday 2018-05-21 18:00', 1.5, 'Friday 2018-05-18 13:00'], + ['Monday 2018-05-21 18:00', 1.75, 'Friday 2018-05-18 11:00'], + ['Monday 2018-05-21 18:00', 2, 'Friday 2018-05-18 09:00'], + ['Monday 2018-05-21 18:00', 2.5, 'Thursday 2018-05-17 13:00'], + ['Monday 2018-05-21 18:00', 3, 'Thursday 2018-05-17 09:00'], // Negative values. ['Wednesday 2018-05-23 13:00', -0, 'Wednesday 2018-05-23 13:00'], ['Wednesday 2018-05-23 13:00', -0.25, 'Wednesday 2018-05-23 15:00'], @@ -126,4 +140,19 @@ public function subBusinessDaysProvider(): array ['Wednesday 2018-05-23 13:00', -2, 'Friday 2018-05-25 13:00'], ]; } + + /** + * The subBusinessDay method should always return a business day. + */ + public function testAlwaysEndsOnBusinessDay() + { + // Given we have a business time for Monday; + $businessTime = new BusinessTime('Monday'); + + // When we subtract one business day from it; + $addDay = $businessTime->subBusinessDay(); + + // Then it should be Friday. + self::assertEquals('Friday', $addDay->format('l')); + } }