Carbon DateTime extension to calculate the "next business day"

1.1.0 2014-09-07 18:21 UTC


Build Status

Have some business logic that requires a somewhat complicated calculation for deadlines or effective dates that need to be modified based on holidays, weekends or special dates? This wrapper for the PHP Carbon project (a DateTime extension itself) is for you!


The basic principal for this utility is to perform date based logic to determine the "next business day" for a provided date. There are various ways to layer in complexity to supplement holidays and deadlines.

The meat and potatoes functionality is provided by the nbd(Carbon $c) method. The method will perform it's checking routine by checking the various criteria and incrementing the day by one in a loop. The nbd() method will return an updated Carbon:: object with the date set to the appropriate business day.

Please note: This is for date logic only.

Basic usage

use CarbonExt\NBD\Calculator;
use CarbonExt\NBD\CoreCallbacks C;
use Carbon\Carbon;

$nbd = new Calculator();

/* Date to find the next business day for */
$dt = new Carbon('2014-01-01');

/* Cherry pick special dates */
$nbd->addExclusion(new Carbon('2014-01-02'));
var_dump($nbd->nbd($dt)); /* Carbon obj: 2014-01-03 */

Callback support

/* Custom exclusion callbacks for layering in complexity */
$nbd->addCallback(C::ignoreDaysOfWeek(array(4))); /* No Fridays, uses Carbon's 0-based offsets */

/* All callback functions must accept a Carbon object and return a bool value */
$cfn = function(Carbon $dt) {
    return ($dt->day % 2 == 0);

$nbd->addCallback($cfn); /* Only on even days of the month */

Deadline support

Say you want to allow payments made today, before 3:00pm effective today. If the payment was submitted after 3:00pm, it is not effective until the next business day...

NOTE: Deadlines are ONLY effective based on hour logic; the date passed into setDeadline() is unregarded!

$nbd->setDeadline(new Carbon('3:00pm'));

$nbd->nbd(new Carbon('2014-01-01 2:59:59pm')); /* Carbon obj: 2014-01-01 00:00:00 */
$nbd->nbd(new Carbon('2014-01-01 3:00:01pm')); /* Carbon obj: 2014-01-02 00:00:00 */

A more complete use case via extension...

use CarbonExt\NBD\Calculator;
use CarbonExt\NBD\CoreCallbacks as C;
use Carbon\Carbon;

class BusinessDayCalc extends Calculator {

    protected $observedHolidays = array(
        'January 1st', /* New years */
        'July 4th', /* Independence Day */
        'November 28th', /* Thanksgiving */
        'December 25th', /* Christmas */

    public function __construct() {


        $observed = array();

        /* Use ignoreRecurring strategy to ignore recurring month-day combos */
        foreach ($this->observedHolidays as $dt) {
            $observed[] = new Carbon($dt);


        /* Use ignoreNDOW strategy to ignore complex, verbal-oriented exceptions */
        /* Ignore Memorial Day: Last Monday of May */
        $this->addCallback(C::ignoreNDOW(5, -1, 1));

        /* Ignore Labor Day: First Monday of September */
        $this->addCallback(C::ignoreNDOW(9, 1, 1));

$nbd = new BusinessDayCalc();
/* Now all your business use-case rules are automatically built in */


Please follow the Git Flow conventions. Proposals should be performed against develop or a feature/bugfix/support branch to be merged in by the maintainer.

Releases/versioning semantics follow the Semantic Versioning 2.0.x guidelines. Minute adjustments (e.g.: changes to this may or may not result in a new version tag, depending on the nature of the change.