HiveBrain v1.2.0
Get Started
← Back to all entries
patternphpMinor

Get Next Working Date, skip weekends and holidays

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
workingskipnextdategetandholidaysweekends

Problem

The object is to be able to pass some dates (start date, holiday) and the number of days you want to skip. We only want to skip working days, not weekends and holidays.

Just let me know what you'd do different than what I have. The code works, but I was told there are issues with it, but not told what issues they are.

function getWDays($startDate,$holiday,$wDays){

$d = new DateTime( $startDate );
$t = $d->getTimestamp();
$h = strtotime($holiday);

// loop for $wDays days
for($i=0; $isetTimestamp($t);

return $d->format( 'Y-m-d' );

}

echo getWDays("2013-08-29","2013-09-02", 3)

Solution


  • Use full words to express your function's ability so that your code is intuitive to other developers.



  • Organize the incoming parameters so that optional values are listed last. Assign a default value to optional parameters so that they can be omitted from function calls.



  • It is too limiting to make the "holiday" parameter a string type variable. Because it is possible that multiple holidays might be encountered while incrementing the date, make the parameter an array. Because it is possible that there are no holidays, design your function to work even if the array is empty.



  • Use type hinting on your function parameter to make your code clear and easy to maintain.



  • I'll demonstrate using a Datetime object as the hero of the process, but strtotime() will work too.



  • Use a classic for() loop to increment the counter variable.



  • Use modify() to advance the date to the next available weekday.



  • Temporarily store the modified date as Y-m-d so that it can be compared in the next step and eventually returned.



  • Use a post-loop check to potentially advance the date past a forbidden date (holiday).



  • To safeguard the function from breakage when an integer less than 1 is passed as the second parameter, I am using the null coalescing operator to fallback to the starting date. Other developers may instead prefer to throw an exception -- I would support that technique as well.



Code: (Demo)

function getFutureWeekday(
    string $startDate,
    int $numberOfDays,
    array $holidays = []
): string
{
    $dt = new DateTime($startDate);
    for ($i = 0; $i modify('+1 weekday')->format('Y-m-d');
        } while (in_array($date, $holidays));
    }
    return $date ?? $startDate;
}

echo getFutureWeekday('2022-03-30', 4, ['2022-04-05']);

Code Snippets

function getFutureWeekday(
    string $startDate,
    int $numberOfDays,
    array $holidays = []
): string
{
    $dt = new DateTime($startDate);
    for ($i = 0; $i < $numberOfDays; ++$i) {
        do {
            $date = $dt->modify('+1 weekday')->format('Y-m-d');
        } while (in_array($date, $holidays));
    }
    return $date ?? $startDate;
}

echo getFutureWeekday('2022-03-30', 4, ['2022-04-05']);

Context

StackExchange Code Review Q#30791, answer score: 5

Revisions (0)

No revisions yet.