Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

PeteBatin's avatar

PHP Carbon diffInWeekdays alternative to return float instead of int

I'm working on a leave/holiday management system.

As well as booking full days leave/holiday they can book half days (morning or afternoon off).

I need to calculate the total amount of days during a requested period. 3 and a half days would be presented as 3.5

To make calculations easier for half days, the maths is based on a day starting at 00:00 and ending at 23:59:59.999999

I can do this with the following but it doesn't exclude weekends which are counted as part of a users leave quota.

if($validated['leave_start_day_part'] == 'AM'){
    //Leave starts at the beginning of the day 
    $startDate = Carbon::createFromDate($validated['leave_start_date'])->startOfDay();
}else{
    //Leave starts midday (half day)
    $startDate = Carbon::createFromDate($validated['leave_start_date'])->midDay();
}

if($validated['leave_end_day_part'] == 'AM'){
    //Leave ends at midday (half day)
    $endDate = Carbon::createFromDate($validated['leave_end_date'])->midDay();
}else{
    //Leave ends at the end of the day
    $endDate = Carbon::createFromDate($validated['leave_end_date'])->endOfDay();
}

$dayCount = $startDate->copy()->diffInDays($endDate);

diffInDays returns a float which is perfect but also includes weekend days.

However if I switch that to the following it returns a whole integer (3.5 is returned as 3)

$dayCount = $startDate->copy()->diffInWeekdays($endDate);

I've considered using diffInDaysFiltered but that also only returns an integer. The decimal is crucial to calculate the total used leave. Is there another method of Carbon that can achieve this and output float or is it time to consider another route?

0 likes
3 replies
jaseofspades88's avatar

If you want to instantly round down all decimals, you could go for...

$dayCount = (int) floor($startDate->copy()->diffInWeekdays($endDate));

This will floor the result of the difference in weekdays to a whole decimal and then you can cast it to an integer as I have done above. If you wish to round up, simply substitute the floor() method with round().

PeteBatin's avatar

@jaseofspades88 Thanks Jase, sorry but decimals are crucial. .5 represents a half day.

diffInWeekdays already returns an integer

PeteBatin's avatar
PeteBatin
OP
Best Answer
Level 10

For anyone who may stumble across my ramblings in the future I achieved it with the following.

if($validated['leave_start_day_part'] == 'AM'){
    $startDate = Carbon::createFromDate($validated['leave_start_date'])->startOfDay();
}else{
    $startDate = Carbon::createFromDate($validated['leave_start_date'])->midDay();
}

if($validated['leave_end_day_part'] == 'AM'){
    $endDate = Carbon::createFromDate($validated['leave_end_date'])->midDay();
}else{
    $endDate = Carbon::createFromDate($validated['leave_end_date'])->endOfDay();
}

$dayCount = $startDate->copy()->diffInDays($endDate); // Returns the amount of days with decimal but also includes weekend days.
$weekendDayCount = $startDate->copy()->diffInWeekenddays($endDate); //Count the amount of weekend days (returns int)
$totalDayCount = $dayCount-$weekendDayCount; //Subtract the weekend day count (int) from all days count, leaving the float in place.

Please or to participate in this conversation.