Skip to content

Commit

Permalink
Add LocalDate::plusWeekdays() / minusWeekDays()
Browse files Browse the repository at this point in the history
  • Loading branch information
BenMorel committed Jun 30, 2021
1 parent da6c257 commit b4e45bf
Show file tree
Hide file tree
Showing 2 changed files with 222 additions and 0 deletions.
44 changes: 44 additions & 0 deletions src/LocalDate.php
Original file line number Diff line number Diff line change
Expand Up @@ -457,6 +457,50 @@ public function plusDays(int $days) : LocalDate
return LocalDate::ofEpochDay($this->toEpochDay() + $days);
}

/**
* Returns a copy of this LocalDate with the specified period in weekdays (Monday-Friday) added.
* If the current date is on a weekend and the number of days is zero, the result is the current date.
* This is a slightly different behaviour from PHP DateTime's "+ n weekdays", that would return the next monday.
*
* Note: this is currently a naive implementation that could be greatly improved.
*/
public function plusWeekdays(int $days) : LocalDate
{
$result = $this;

if ($days < 0) {
$subtractedDays = 0;

while ($subtractedDays < -$days) {
$result = $result->minusDays(1);
if ($result->getDayOfWeek()->isWeekday()) {
$subtractedDays++;
}
}
} else {
$addedDays = 0;

while ($addedDays < $days) {
$result = $result->plusDays(1);
if ($result->getDayOfWeek()->isWeekday()) {
$addedDays++;
}
}
}

return $result;
}

/**
* Returns a copy of this LocalDate with the specified period in weekdays (Monday-Friday) subtracted.
* If the current date is on a weekend and the number of days is zero, the result is the current date.
* This is a slightly different behaviour from PHP DateTime's "- n weekdays", that would return the next monday.
*/
public function minusWeekdays(int $days) : LocalDate
{
return $this->plusWeekdays(-$days);
}

/**
* Returns a copy of this LocalDate with the specified Period subtracted.
*/
Expand Down
178 changes: 178 additions & 0 deletions tests/LocalDateTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -788,6 +788,184 @@ public function providerPlusDays() : array
];
}

/**
* @dataProvider providerPlusWeekdays
*/
public function testPlusWeekdays(string $date, int $days, string $expectedDate): void
{
$this->assertSame($expectedDate, (string) LocalDate::parse($date)->plusWeekdays($days));
}

/**
* @dataProvider providerPlusWeekdays
*/
public function testMinusWeekdays(string $date, int $days, string $expectedDate): void
{
$this->assertSame($expectedDate, (string) LocalDate::parse($date)->minusWeekdays(-$days));
}

public function providerPlusWeekdays(): array
{
return [
['2020-11-02', -10, '2020-10-19'],
['2020-11-02', -9, '2020-10-20'],
['2020-11-02', -8, '2020-10-21'],
['2020-11-02', -7, '2020-10-22'],
['2020-11-02', -6, '2020-10-23'],
['2020-11-02', -5, '2020-10-26'],
['2020-11-02', -4, '2020-10-27'],
['2020-11-02', -3, '2020-10-28'],
['2020-11-02', -2, '2020-10-29'],
['2020-11-02', -1, '2020-10-30'],
['2020-11-02', 0, '2020-11-02'],
['2020-11-02', 1, '2020-11-03'],
['2020-11-02', 2, '2020-11-04'],
['2020-11-02', 3, '2020-11-05'],
['2020-11-02', 4, '2020-11-06'],
['2020-11-02', 5, '2020-11-09'],
['2020-11-02', 6, '2020-11-10'],
['2020-11-02', 7, '2020-11-11'],
['2020-11-02', 8, '2020-11-12'],
['2020-11-02', 9, '2020-11-13'],
['2020-11-02', 10, '2020-11-16'],

['2020-11-03', -10, '2020-10-20'],
['2020-11-03', -9, '2020-10-21'],
['2020-11-03', -8, '2020-10-22'],
['2020-11-03', -7, '2020-10-23'],
['2020-11-03', -6, '2020-10-26'],
['2020-11-03', -5, '2020-10-27'],
['2020-11-03', -4, '2020-10-28'],
['2020-11-03', -3, '2020-10-29'],
['2020-11-03', -2, '2020-10-30'],
['2020-11-03', -1, '2020-11-02'],
['2020-11-03', 0, '2020-11-03'],
['2020-11-03', 1, '2020-11-04'],
['2020-11-03', 2, '2020-11-05'],
['2020-11-03', 3, '2020-11-06'],
['2020-11-03', 4, '2020-11-09'],
['2020-11-03', 5, '2020-11-10'],
['2020-11-03', 6, '2020-11-11'],
['2020-11-03', 7, '2020-11-12'],
['2020-11-03', 8, '2020-11-13'],
['2020-11-03', 9, '2020-11-16'],
['2020-11-03', 10, '2020-11-17'],

['2020-11-04', -10, '2020-10-21'],
['2020-11-04', -9, '2020-10-22'],
['2020-11-04', -8, '2020-10-23'],
['2020-11-04', -7, '2020-10-26'],
['2020-11-04', -6, '2020-10-27'],
['2020-11-04', -5, '2020-10-28'],
['2020-11-04', -4, '2020-10-29'],
['2020-11-04', -3, '2020-10-30'],
['2020-11-04', -2, '2020-11-02'],
['2020-11-04', -1, '2020-11-03'],
['2020-11-04', 0, '2020-11-04'],
['2020-11-04', 1, '2020-11-05'],
['2020-11-04', 2, '2020-11-06'],
['2020-11-04', 3, '2020-11-09'],
['2020-11-04', 4, '2020-11-10'],
['2020-11-04', 5, '2020-11-11'],
['2020-11-04', 6, '2020-11-12'],
['2020-11-04', 7, '2020-11-13'],
['2020-11-04', 8, '2020-11-16'],
['2020-11-04', 9, '2020-11-17'],
['2020-11-04', 10, '2020-11-18'],

['2020-11-05', -10, '2020-10-22'],
['2020-11-05', -9, '2020-10-23'],
['2020-11-05', -8, '2020-10-26'],
['2020-11-05', -7, '2020-10-27'],
['2020-11-05', -6, '2020-10-28'],
['2020-11-05', -5, '2020-10-29'],
['2020-11-05', -4, '2020-10-30'],
['2020-11-05', -3, '2020-11-02'],
['2020-11-05', -2, '2020-11-03'],
['2020-11-05', -1, '2020-11-04'],
['2020-11-05', 0, '2020-11-05'],
['2020-11-05', 1, '2020-11-06'],
['2020-11-05', 2, '2020-11-09'],
['2020-11-05', 3, '2020-11-10'],
['2020-11-05', 4, '2020-11-11'],
['2020-11-05', 5, '2020-11-12'],
['2020-11-05', 6, '2020-11-13'],
['2020-11-05', 7, '2020-11-16'],
['2020-11-05', 8, '2020-11-17'],
['2020-11-05', 9, '2020-11-18'],
['2020-11-05', 10, '2020-11-19'],

['2020-11-06', -10, '2020-10-23'],
['2020-11-06', -9, '2020-10-26'],
['2020-11-06', -8, '2020-10-27'],
['2020-11-06', -7, '2020-10-28'],
['2020-11-06', -6, '2020-10-29'],
['2020-11-06', -5, '2020-10-30'],
['2020-11-06', -4, '2020-11-02'],
['2020-11-06', -3, '2020-11-03'],
['2020-11-06', -2, '2020-11-04'],
['2020-11-06', -1, '2020-11-05'],
['2020-11-06', 0, '2020-11-06'],
['2020-11-06', 1, '2020-11-09'],
['2020-11-06', 2, '2020-11-10'],
['2020-11-06', 3, '2020-11-11'],
['2020-11-06', 4, '2020-11-12'],
['2020-11-06', 5, '2020-11-13'],
['2020-11-06', 6, '2020-11-16'],
['2020-11-06', 7, '2020-11-17'],
['2020-11-06', 8, '2020-11-18'],
['2020-11-06', 9, '2020-11-19'],
['2020-11-06', 10, '2020-11-20'],

['2020-11-07', -10, '2020-10-26'],
['2020-11-07', -9, '2020-10-27'],
['2020-11-07', -8, '2020-10-28'],
['2020-11-07', -7, '2020-10-29'],
['2020-11-07', -6, '2020-10-30'],
['2020-11-07', -5, '2020-11-02'],
['2020-11-07', -4, '2020-11-03'],
['2020-11-07', -3, '2020-11-04'],
['2020-11-07', -2, '2020-11-05'],
['2020-11-07', -1, '2020-11-06'],
['2020-11-07', 0, '2020-11-07'],
['2020-11-07', 1, '2020-11-09'],
['2020-11-07', 2, '2020-11-10'],
['2020-11-07', 3, '2020-11-11'],
['2020-11-07', 4, '2020-11-12'],
['2020-11-07', 5, '2020-11-13'],
['2020-11-07', 6, '2020-11-16'],
['2020-11-07', 7, '2020-11-17'],
['2020-11-07', 8, '2020-11-18'],
['2020-11-07', 9, '2020-11-19'],
['2020-11-07', 10, '2020-11-20'],

['2020-11-08', -10, '2020-10-26'],
['2020-11-08', -9, '2020-10-27'],
['2020-11-08', -8, '2020-10-28'],
['2020-11-08', -7, '2020-10-29'],
['2020-11-08', -6, '2020-10-30'],
['2020-11-08', -5, '2020-11-02'],
['2020-11-08', -4, '2020-11-03'],
['2020-11-08', -3, '2020-11-04'],
['2020-11-08', -2, '2020-11-05'],
['2020-11-08', -1, '2020-11-06'],
['2020-11-08', 0, '2020-11-08'],
['2020-11-08', 1, '2020-11-09'],
['2020-11-08', 2, '2020-11-10'],
['2020-11-08', 3, '2020-11-11'],
['2020-11-08', 4, '2020-11-12'],
['2020-11-08', 5, '2020-11-13'],
['2020-11-08', 6, '2020-11-16'],
['2020-11-08', 7, '2020-11-17'],
['2020-11-08', 8, '2020-11-18'],
['2020-11-08', 9, '2020-11-19'],
['2020-11-08', 10, '2020-11-20'],

['2019-01-29', 400, '2020-08-11'],
['2019-01-29', -400, '2017-07-18'],
];
}

/**
* @dataProvider providerMinusYears
*
Expand Down

0 comments on commit b4e45bf

Please sign in to comment.