IsDateItemCoveredByHolidaysHandle

Determine if a date item is covered by a holidays handle's range

Overview

IsDateItemCoveredByHolidaysHandle is the exported, self-locking counterpart of the internal IsDateCoveredByHolidaysHandle(). It accepts either a DATE_LOG_HANDLE/DATE_RANGE_HANDLE (from which the associated holidays handle is extracted) or a HOLIDAYS_HANDLE directly, validates and locks whichever handles it needs, and returns whether hDateItem falls strictly within the holidays handle’s covered range and is not itself a holiday.

The covered range is documented as the half-open interval [first, last) of the holidays core: the first date of the core is covered, the last date of the core is not. Because the result is a BOOL, the function cannot tell you which of the failing conditions occurred.

Key Features

Function Signature


BOOL _Check_return_ IsDateItemCoveredByHolidaysHandle(
    _In_ DATE_ITEM_HANDLE       hDateItem,
    _In_ DATE_COLLECTION_HANDLE hDateLogHandle
);

_Check_return_ means the result must be inspected. DATE_COLLECTION_HANDLE is the generic collection handle type declared in datelog.h; it can hold any of DATE_LOG_HANDLE, DATE_RANGE_HANDLE or HOLIDAYS_HANDLE.

Parameters

hDateItem

[In] DATE_ITEM_HANDLE

The date item to test.

hDateLogHandle

[In] DATE_COLLECTION_HANDLE

A DATE_LOG_HANDLE, DATE_RANGE_HANDLE or HOLIDAYS_HANDLE.

  • Direction: input only.
  • Valid values: a handle from InitializeDateLogHandle or DuplicateDateLogHandle, or a holidays handle returned by GetDateLogHolidayHandle. For a log or range, the handle must have an associated holidays handle; for a holidays handle, its core must be populated.
  • NULL: invalid parameter; FALSE is returned.
  • Ownership / lifetime: remains owned by the caller and must be closed with CloseDateLogHandle. The function does not retain it after returning.

Return Values

ValueCondition
TRUEhDateItem is within [first, last) of the holidays core and is not a holiday itself.
FALSEThe item is not covered, is itself a holiday, a parameter is invalid, or a locking / handle-resolution failure occurred.

No HRESULT is returned. The library error codes that describe the same situations elsewhere are ERR_DATE_NO_COVERED (date not covered by the holidays collection), ERR_DATE_IS_HOLIDAY, ERR_INVALID_DATELOG_HANDLE and ERR_INVALID_HOLIDAY_HANDLE (see date_error.h); this function folds all of them into FALSE.

Remarks

Thread Safety

The function validates and locks the handles it needs for the duration of the check and unlocks them before returning. Concurrent callers on the same shared context are therefore serialized by the library. If locking fails, the function returns FALSE. Use DuplicateDateLogHandle to give each thread its own handle.

Handle Lifetime and Ownership

Ordering and Related Functions

Note: Because the covered interval is half-open, an item equal to the last date of the holidays core is not covered according to this function’s documented range.

See Also

Sample Code

The sample builds a holidays handle and a date log for 2025-01-02 through 2025-03-31, obtains the log’s own holidays handle, and tests four dates against both the log and the holidays handle. Every date item and all three handles are released on every path.


#include <Windows.h>
#include <stdio.h>
#include "datelog.h"

static BOOL MakeFileTime(WORD wYear, WORD wMonth, WORD wDay, PFILETIME pFt)
{
    SYSTEMTIME st = { 0 };

    st.wYear = wYear;
    st.wMonth = wMonth;
    st.wDay = wDay;
    return SystemTimeToFileTime(&st, pFt);
}

/* Creates a holidays handle and loads it with the range [first, last]. */
static HRESULT BuildHolidays(PFILETIME pFirst, PFILETIME pLast, HOLIDAYS_HANDLE *phHolidays)
{
    HRESULT hr = S_OK;
    HOLIDAYS_HANDLE hHolidays = NULL;
    DATE_ITEM_HANDLE hFirst = NULL;
    DATE_ITEM_HANDLE hLast = NULL;

    *phHolidays = NULL;

    hr = InitializeDateLogHandle(NULL, DATE_LOG_MAX, NULL, &hHolidays, HandleIsForHolidays);
    if (FAILED(hr)) goto cleanup;

    hr = InitializeDateItem(hHolidays, pFirst, NULL, &hFirst);
    if (FAILED(hr)) goto cleanup;

    hr = InitializeDateItem(hHolidays, pLast, NULL, &hLast);
    if (FAILED(hr)) goto cleanup;

    hr = LoadDateLogHandle(NULL, hFirst, hLast, hHolidays, NULL, 0);
    if (FAILED(hr)) goto cleanup;

    *phHolidays = hHolidays;
    hHolidays = NULL;

cleanup:
    FreeDateItem(hLast);
    FreeDateItem(hFirst);
    if (hHolidays != NULL) {
        (void)CloseDateLogHandle(hHolidays);
    }
    return hr;
}

/* Creates a date log or range handle of the given type and generates [first, last] into it. */
static HRESULT BuildCollection(HOLIDAYS_HANDLE hHolidays, DateHandleType type,
                               PFILETIME pFirst, PFILETIME pLast, DATE_LOG_HANDLE *phCollection)
{
    HRESULT hr = S_OK;
    DATE_LOG_HANDLE hCollection = NULL;
    DATE_ITEM_HANDLE hFirst = NULL;
    DATE_ITEM_HANDLE hLast = NULL;

    *phCollection = NULL;

    hr = InitializeDateLogHandle(NULL, DATE_LOG_MAX, hHolidays, &hCollection, type);
    if (FAILED(hr)) goto cleanup;

    hr = InitializeDateItem(hHolidays, pFirst, NULL, &hFirst);
    if (FAILED(hr)) goto cleanup;

    hr = InitializeDateItem(hHolidays, pLast, NULL, &hLast);
    if (FAILED(hr)) goto cleanup;

    hr = LoadDateLogHandle(NULL, hFirst, hLast, hCollection, NULL, 0);
    if (FAILED(hr)) goto cleanup;

    *phCollection = hCollection;
    hCollection = NULL;

cleanup:
    FreeDateItem(hLast);
    FreeDateItem(hFirst);
    if (hCollection != NULL) {
        (void)CloseDateLogHandle(hCollection);
    }
    return hr;
}

typedef struct _SAMPLE_DATE {
    WORD wYear;
    WORD wMonth;
    WORD wDay;
} SAMPLE_DATE;

int main(void)
{
    static const SAMPLE_DATE candidates[] = {
        { 2025,  1,  2 },   /* first date of the holidays range */
        { 2025,  2, 18 },   /* inside the range                 */
        { 2025,  3, 31 },   /* last date of the range           */
        { 2025,  4,  1 }    /* beyond the range                 */
    };
    int exitCode = 1;
    HRESULT hr = S_OK;
    FILETIME ftFirst = { 0 };
    FILETIME ftLast = { 0 };
    HOLIDAYS_HANDLE hHolidaysSource = NULL;
    DATE_LOG_HANDLE hDateLog = NULL;
    HOLIDAYS_HANDLE hHolidays = NULL;
    size_t i = 0;

    if (!MakeFileTime(2025, 1, 2, &ftFirst) || !MakeFileTime(2025, 3, 31, &ftLast)) {
        printf("Invalid calendar date.\n");
        return 1;
    }

    hr = BuildHolidays(&ftFirst, &ftLast, &hHolidaysSource);
    if (FAILED(hr)) {
        printf("BuildHolidays failed: 0x%08lX\n", (unsigned long)hr);
        goto cleanup;
    }

    hr = BuildCollection(hHolidaysSource, HandleIsForDatelog, &ftFirst, &ftLast, &hDateLog);
    if (FAILED(hr)) {
        printf("BuildCollection failed: 0x%08lX\n", (unsigned long)hr);
        goto cleanup;
    }

    /* The caller owns the returned holidays handle and must close it. */
    hHolidays = GetDateLogHolidayHandle(hDateLog);
    if (hHolidays == NULL) {
        printf("The date log has no usable holidays handle.\n");
        goto cleanup;
    }

    for (i = 0; i < sizeof(candidates) / sizeof(candidates[0]); i++) {
        FILETIME ft = { 0 };
        DATE_ITEM_HANDLE hItem = NULL;

        if (!MakeFileTime(candidates[i].wYear, candidates[i].wMonth, candidates[i].wDay, &ft)) {
            continue;
        }

        hr = InitializeDateItem(hDateLog, &ft, NULL, &hItem);
        if (FAILED(hr)) {
            printf("%04u-%02u-%02u: no date item (0x%08lX)%s\n",
                   candidates[i].wYear, candidates[i].wMonth, candidates[i].wDay,
                   (unsigned long)hr, hr == ERR_DATE_IS_HOLIDAY ? " - holiday or weekend" : "");
            continue;
        }

        /* The collection argument may be a date log or a holidays handle. */
        printf("%04u-%02u-%02u: via date log = %s, via holidays handle = %s\n",
               candidates[i].wYear, candidates[i].wMonth, candidates[i].wDay,
               IsDateItemCoveredByHolidaysHandle(hItem, hDateLog) ? "covered" : "not covered",
               IsDateItemCoveredByHolidaysHandle(hItem, hHolidays) ? "covered" : "not covered");

        FreeDateItem(hItem);
    }

    exitCode = 0;

cleanup:
    if (hHolidays != NULL) {
        (void)CloseDateLogHandle(hHolidays);
    }
    if (hDateLog != NULL) {
        (void)CloseDateLogHandle(hDateLog);
    }
    if (hHolidaysSource != NULL) {
        (void)CloseDateLogHandle(hHolidaysSource);
    }
    return exitCode;
}