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

auroralabs's avatar

Helper function to exclude Weekends

Hi,

I have a helper that is supposed to exclude weekends from a cauculation. The created_at date for example is

2024-08-20 22:54:27 and today is 2024-08-26 9:54:27 = 5 Days 9 Hours When I run this script is returns 4 Days 9 Hours

Can someone shed any light into why it is omitting 1 day in the calculation??

0 likes
2 replies
LaryAI's avatar
Level 58

To address the issue of excluding weekends from the calculation, we need to ensure that the logic correctly handles the difference in days and hours while excluding weekends. The provided code has a good start, but there are a few improvements and corrections we can make to ensure it works as expected.

Here's a revised version of the helper function:

Explanation:

  1. Fetching Activities: The function fetches the latest activity and the next activity to determine the time range.
  2. End Time Calculation: If there is no next activity, the end time is set to the current time.
  3. Duration Calculation:
    • diffInDaysFiltered is used to calculate the total number of days excluding weekends.
    • diffFiltered with CarbonInterval::hour() is used to calculate the total number of hours excluding weekends.
  4. Remaining Hours: The remaining hours after full days are calculated using the modulus operator.
  5. Human-Readable Format: The duration is formatted into a human-readable string showing days and hours.

This should correctly calculate the duration excluding weekends and return the result in a human-readable format.

s4muel's avatar

first to make it clear, the correct diff should be 3 days and 11 hours, right? because it is 5 days 11 hours minus two weekend days.

its a bit tricky, the diffInDays() carbon method returns a float and the diffInDaysFiltered() returns an integer. it simply iterates over the days "kind of" ignoring the hours (not really, but rounding them up so to speak) and excludes two days, when it matches the condition. imagine returning true for the condition, you get 6 days, instead of 5 (5 whole days + 11 hours). so it is 6 minus 2 = 4 if two weekend days are excluded).

$startTime = Carbon::make('2024-08-20 22:54:27');
$endTime = Carbon::make('2024-08-26 9:54:27');

dump($startTime->diffInDays());
//5.5705280264352

dump($startTime->diffInDaysFiltered(function (Carbon $date) {
    return true;
}, $endTime));
//6 (same same but different)

i would calculate (and filter) just the hours and then convert it to carbon interval

$totalHours = $startTime->diffFiltered(CarbonInterval::hour(), function (Carbon $date) {
    return !$date->isWeekend();
}, $endTime);

$duration = CarbonInterval::hours($totalHours)->cascade();

dump($duration->forHumans(['parts' => 2]));
//3 days 11 hours

Please or to participate in this conversation.