Reputation: 61
I have a calculate shipping days method. I need to be able to add days onto a Carbon instance but i need to skip adding a day based on if its a specific day of the week, not necessarily Saturday/Sunday, it could be Monday or Tuesday as well. I cant seem to find anything in the Carbon Docs that specifies blacklisting certain days of the week when adding days.
Upvotes: 1
Views: 986
Reputation: 775
Yes you can use CarbonPeriod and method filter
$month = CarbonPeriod::between($start, Carbon::now()->endOfMonth())
->filter(fn ($date) => !$date->isMonday() || !$date->isSunday() )
->toArray();
This way you can skip days from your array of days
Upvotes: 0
Reputation: 5121
A library for Carbon helps to set open/closed days in a week and so you can:
https://github.com/kylekatarnls/business-time
And you could do:
BusinessTime::enable(Carbon::class, [
'monday'. => [],
'tuesday' => ['00:00-24:00'],
'wednesday' => ['00:00-24:00'],
'thursday' => ['00:00-24:00'],
'friday' => [],
'saturday' => ['00:00-24:00'],
'sunday' => ['00:00-24:00'],
]);
$date = Carbon::parse('2019-06-01');
echo $date->addOpenTime('4 days');
This add 4 days skipping Friday and Monday.
You could basically get the same result with a loop adding days one by one, but it will be as slow as the interval is big. To optimize the operation, you should first add complete weeks:
$daysToAdd = 36;
$skippedDays = ['Monday', 'Friday'];
$daysPerWeek = 7 - count($skippedDays);
$completeWeeks = floor($daysToAdd / $daysPerWeek);
function skip(CarbonInterface $date, array $skippedDays): CarbonInterface {
$date = $date->copy(); // if not using CarbonImmutable
while (in_array($date->format('l'), $skippedDays)) {
$date = $date->addDay();
}
return $date;
}
$start = Carbon::now(); // Or whatever date
$end = $start->copy()->addWeeks($completeWeeks); // ->copy() not needed if you use CarbonImmutable
$end = skip($end, $skippedDays);
// For each remaining days
for ($i = $daysToAdd % $daysPerWeek; $i--; $i > 0) {
$end = skip($end->addDay(), $skippedDays);
}
This is a vanilla version for your specific case, but if you think someday, you will have to deal with hour-intervals/hour-precision instead of days, or will have special days (like holidays exceptions), then you should definitely use cmixin/business-time
(link above).
Upvotes: 0