Determining if a weekend is a long weekend

Long weekends, also known as a three-day weekend, is the perfect time to take a road trip or even take a short destination vacation. All without tapping into your accrued paid time off. Bonus points if the long weekend is four days!

Depending on your industry, it may be beneficial to know when these long holidays weekends occur. Staffing up (or down), setting proper support expectations, adjusting shipping estimates and even for forecasting sales.

Determining long weekends is pretty easy once you have a list of holidays. By determining which holidays fall on either a Friday or Monday, you then know which weekends are going to be long.

This guide requires an API key.   Get yours for free.

The first thing we need to do, is pull a list of holidays. Pulling this year's holidays can be sufficient in most scenarios. Remember though, New Year's Day can occur on the Monday of the next year, so you may want to check both this year and next year.

First we're going to pull this year's holidays using PHP and cURL (more languages coming soon!):

<?php
$key = '__YOUR_API_KEY__';

$parameters = http_build_query([
    'key' => $key,
    'country' => 'US',
    'year' => 2019,
]);

$curl = curl_init();

curl_setopt_array($curl, [
    CURLOPT_URL => 'https://holidayapi.com/v1/holidays?' . $parameters,
    CURLOPT_HEADER => false,
    CURLOPT_SSL_VERIFYPEER => true,
    CURLOPT_RETURNTRANSFER => true,
]);

$response = curl_exec($curl);

if ($error = curl_error($curl)) {
    throw new Exception($error);
}

curl_close($curl);

$response = json_decode($response, true);

if (!$response || !$response['holidays']) {
    throw new Exception('Malformed response');
}

Now that we have a list of holidays, we can loop through and determine which day of the week each holiday occurs on. Any time we encounter a holiday that lands or observes on a Friday or a Monday, we'll flag that weekend as being a long weekend.

First, let's loop through the holidays, and flag every date that's part of a long weekend. That includes the weekend days as well:

$day = 86400;
$long_weekend_dates = [];

foreach ($response['holidays'] as $holiday) {
    if ($holiday['observed'] !== $holiday['date']) {
        $date = $holiday['observed'];
    } else {
        $date = $holiday['date'];
    }

    $time = strtotime($date);
    $day_of_week = date('N', $time);

    // Lands or observes on Monday
    if ($day_of_week == 1) {
        // Flags Saturday through Monday
        $long_weekend_dates[date('Y-m-d', $time - ($day * 2))] = true;
        $long_weekend_dates[date('Y-m-d', $time - $day)] = true;
        $long_weekend_dates[$date] = true;
    }
    // Lands or observes on Friday
    elseif ($day_of_week == 5) {
        // Flags Friday through Sunday
        $long_weekend_dates[$date] = true;
        $long_weekend_dates[date('Y-m-d', $time + $day)] = true;
        $long_weekend_dates[date('Y-m-d', $time + ($day * 2))] = true;
    }
}

$long_weekend_dates = array_keys($long_weekend_dates);
sort($long_weekend_dates);

Now that we have an associative array of dates that are part of a long weekend, we could easily use the list to determine if a date is part of a long weekend or not.

To take things a step further, let's loop through again and create another array that groups the dates together that are part of the same weekend:

$long_weekends = [];
$long_weekend = [];

foreach ($long_weekend_dates as $index => $date) {
    $long_weekend[] = $date;
    $next_index = $index + 1;
    $end_of_dates = !isset($long_weekend_dates[$next_index]);
    $more_dates = false;

    if (!$end_of_dates) {
        $this_date = new DateTime($date);
        $next_date = new DateTime($long_weekend_dates[$next_index]);
        $interval = $this_date->diff($next_date);
        $more_dates = ($interval->format('%a') == 1);
    }

    if ($end_of_dates || !$more_dates) {
        $long_weekends[] = $long_weekend;
        $long_weekend = [];
    }
}

print_r($long_weekends);

That's all there is to it!