Last active
March 10, 2022 09:26
-
-
Save mRoca/249d8374ee4e6fdfac502c100841b266 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
/** | |
* Returns all days between two dates matching a wanted position in a week, in a month. | |
* | |
* For instance, in order to get all dates matching the request: | |
* "First and third monday and friday of each month between 2022-01-08 and 2022-06-15" : | |
* | |
* $days = getDatesInRangeByDaysInMonth(new DateTimeImmutable('2022-01-08'), new DateTimeImmutable('2022-06-15'), [1, 5], [1, 3]); | |
* | |
* @param DateTimeInterface $startDate | |
* @param DateTimeInterface $endDate | |
* @param int[] $daysOfWeek | |
* @param int[] $daysOfWeekInMonth | |
* @return DateTimeImmutable[] | |
*/ | |
function getDatesInRangeByDaysInMonth(DateTimeInterface $startDate, DateTimeInterface $endDate, array $daysOfWeek, array $daysOfWeekInMonth): array | |
{ | |
$days = [1 => 'Monday', 2 => 'Tuesday', 3 => 'Wednesday', 4 => 'Thursday', 5 => 'Friday', 6 => 'Saturday', 7 => 'Sunday']; | |
$ordinals = [1 => 'first', 2 => 'second', 3 => 'third', 4 => 'fourth', 5 => 'fifth']; | |
// Clean passed variables | |
$startDate = $startDate instanceof DateTime ? DateTimeImmutable::createFromMutable($startDate) : $startDate; | |
$endDate = $endDate instanceof DateTime ? DateTimeImmutable::createFromMutable($endDate) : $endDate; | |
$daysOfWeek = array_unique(array_filter($daysOfWeek, static fn($d) => array_key_exists((int)$d, $days))); | |
$daysOfWeekInMonth = array_unique(array_filter($daysOfWeekInMonth, static fn($d) => array_key_exists((int)$d, $ordinals))); | |
/** @var DateTimeImmutable[] $result */ | |
$result = []; | |
// Iterator | |
$period = new DatePeriod($startDate->modify('first day of this month'), new DateInterval('P1M'), $endDate); | |
foreach ($period as $firstDayOfMonth) { | |
/** @var DateTimeImmutable $firstDayOfMonth */ | |
foreach ($daysOfWeekInMonth as $dayOfWeekInMonth) { | |
foreach ($daysOfWeek as $dayOfWeek) { | |
$newDate = $firstDayOfMonth->modify(sprintf('%s %s of this month', $ordinals[$dayOfWeekInMonth], $days[$dayOfWeek])); | |
if ($newDate < $startDate || $newDate > $endDate) { | |
continue; | |
} | |
$result[] = $newDate; | |
} | |
} | |
} | |
return $result; | |
} | |
$startDate = new DateTimeImmutable('2022-01-08'); | |
$endDate = new DateTimeImmutable('2022-06-15'); | |
$daysOfWeek = [1, 5]; // 1 = monday, 5 = friday | |
$daysOfWeekInMonth = [1, 3]; // First and third monday and friday of each month | |
$days = getDatesInRangeByDaysInMonth($startDate, $endDate, $daysOfWeek, $daysOfWeekInMonth); | |
print_r($days); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment