Reputation: 1785
I'm trying to get difference between two dates in human format but only with working days. Here is my actual code:
$start = '2018-09-13 09:30:00';
$end = '2018-10-16 16:30:00';
$from = Carbon::parse($start);
$to = Carbon::parse($end);
$weekDay = $from->diffInWeekdays($to);
$human = $to->diffForHumans($from, true, false, 6);
var_dump($weekDay); //24
var_dump($human); // 1 month 3 days 7 hours
diffForHumans
is perfect for my needs but I can't find any way of filtering like diffInDaysFiltered
What I would like to achieve is to get this result: 24 days 7 hours
because we only have 24
working days
I tried a preg_replace
first to replace 3 days by $weekDay
result but if we have a month before it's incorrect and I have: 1 month 24 days 7 hours
Is there any solution for my problem ?
Upvotes: 8
Views: 8991
Reputation: 1
Ok, The solution works, but i had some problem with more complex time calculation, so i figured out another solution with while cycle
Carbon::macro('isHoliday', function ($self = null) {
// compatibility chunk
if (!isset($self) && isset($this)) {
$self = $this;
}
// Put your array of holidays here
return in_array($self->format('d/m'), [
'23/12',
'24/12',
'25/12',
'26/12',
'27/12',
'28/12',
'29/12',
'30/12',
'31/12',
'01/01',
'02/01',
'03/01',
'04/01',
'05/01',
'06/01',
'07/01',
]);
});
$end = Carbon::now();
$hours = 160;
while($hours > 0) {
if ($end->hour < 9 || $end->hour >= 18 || $end->hour == 13 || $end->isWeekend() || $end->isHoliday()) {
$end->addHour();
} else {
$end->addHour();
$hours--;
}
}
Debugbar::addMessage($end);
Upvotes: 0
Reputation: 408
The above-mentioned answers are good correct. But there are some other ways also with carbon.
$startDate = Carbon::create(2017, 4, 4);
$endDate = Carbon::create(2017, 4, 18);
$no_of_days = $startDate->diffInDaysFiltered(function(Carbon $date) {
return !$date->isSunday();
}, $endDate);
Some useful functions of Carbon
$dt->isMonday();
$dt->isTuesday();
$dt->isWednesday();
$dt->isThursday();
$dt->isFriday();
$dt->isSaturday();
$dt->isSunday();
$dt->isDayOfWeek(Carbon::SATURDAY); // is a saturday
For more information go to https://carbon.nesbot.com/docs/
Upvotes: 3
Reputation: 1785
Here is the answer thanks to imbrish
I need to use the cascade factor to define:
Then with the diffFiltered
I can only select weekday and working hours. You can also add a filter on public holiday thanks to macro
CarbonInterval::setCascadeFactors(array(
'days' => array(10, 'hours'),
'weeks' => array(5, 'days'),
'months' => array(20, 'days'),
));
$resolution = CarbonInterval::hour();
$start = Carbon::parse('2017-07-13 11:00');
$end = Carbon::parse('2017-07-17 18:00');
$hours = $start->diffFiltered($resolution, function ($date) {
return $date->isWeekday() && $date->hour >= 8 && $date->hour < 18;
}, $end);
$interval = CarbonInterval::hours($hours)->cascade();
echo $interval->forHumans(); // 2 days 7 hours
Here is the macro part:
Carbon::macro('isHoliday', function ($self = null) {
// compatibility chunk
if (!isset($self) && isset($this)) {
$self = $this;
}
// Put your array of holidays here
return in_array($self->format('d/m'), [
'25/12', // Christmas
'01/01', // New Year
]);
});
Then simply add && !$date->isHoliday()
inside the diffFiltered
Upvotes: 12