IsDateCoveredByDateLog

Determine whether a date item is within range and covered by a date log's holidays

Overview

IsDateCoveredByDateLog determines whether a date item is both later than the first date of a date log and covered by the holidays handle associated with that log (that is, it lies within the range of dates the holidays handle knows about).

The function is a simple predicate: it returns TRUE or FALSE and never reports why a date is not covered. Because it returns only BOOL, invalid parameters are indistinguishable from a date that is simply not covered. Use it as a quick gate before relying on a date item with a particular date log; use InitializeDateItem or the other query functions when you need an HRESULT that explains the failure.

Key Points

Function Signature


BOOL IsDateCoveredByDateLog(
    _In_ DATE_ITEM_HANDLE hDateItem,
    _In_ DATE_LOG_HANDLE  hDateLog
);

The function takes exactly two arguments, in this order: the date item first, the date log second. The declaration is reproduced from this function’s documentation; datelog.h lists IsDateCoveredByDateLog among its analysis functions but does not reproduce its prototype.

Parameters

hDateItem

[In] DATE_ITEM_HANDLE

The date item to test.

  • Direction: input only; the item is not modified.
  • Valid values: a date item handle obtained from InitializeDateItem, GetDateItemCopy or a lookup function such as FindDateItemHandle.
  • NULL: not valid; FALSE is returned.
  • Ownership / lifetime: remains owned by the caller. Standalone items must still be released with FreeDateItem after the call.
hDateLog

[In] DATE_LOG_HANDLE

The date log whose first date and associated holidays handle define the valid coverage range.

Return Values

ValueCondition
TRUEThe date item is later than the log’s first date and is covered by the log’s holidays handle.
FALSEReturned on invalid parameters, when the date is not later than the log’s first date, or when the date is not covered by the holidays handle.

The function does not return HRESULT values. For the library error codes that describe the same conditions elsewhere, see ERR_DATE_EARLIER_BASE (date earlier than the start date) and ERR_DATE_NO_COVERED (date not covered by the holidays collection) in date_error.h; those codes are returned by other functions, not by this one.

Remarks

Thread Safety

This page does not document a locking guarantee for IsDateCoveredByDateLog itself. The library as a whole uses mutex-based synchronization on shared handle contexts (see datelog.h); to avoid contending on a single handle from several threads, give each thread its own handle via DuplicateDateLogHandle.

Handle Lifetime and Ownership

Ordering and Relationship to Sibling Functions

See Also

Sample Code

The sample builds a holidays handle and a date log for 2025-01-02 through 2025-03-31, then tests several candidate dates. The helper functions use only documented mdts_date calls; the holidays handle is shared with the log (the log duplicates it internally) and is closed separately. Every date item is freed and both handles are closed 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[] = {
        { 2024, 12, 31 },   /* before the first loaded date */
        { 2025,  1,  2 },   /* the first loaded date itself */
        { 2025,  2, 18 },   /* inside the loaded range      */
        { 2025,  3, 31 }    /* the last loaded date         */
    };
    int exitCode = 1;
    HRESULT hr = S_OK;
    FILETIME ftFirst = { 0 };
    FILETIME ftLast = { 0 };
    HOLIDAYS_HANDLE hHolidays = NULL;
    DATE_LOG_HANDLE hDateLog = NULL;
    size_t i = 0;

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

    /* The log needs a populated holidays handle; the log keeps its own reference. */
    hr = BuildHolidays(&ftFirst, &ftLast, &hHolidays);
    if (FAILED(hr)) {
        printf("BuildHolidays failed: 0x%08lX\n", (unsigned long)hr);
        goto cleanup;
    }

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

    if (!IsValidDateLogHandle(hDateLog)) {
        printf("The date log handle is not valid.\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;
        }

        /* Creating the item also rejects holidays and weekends. */
        hr = InitializeDateItem(hDateLog, &ft, NULL, &hItem);
        if (FAILED(hr)) {
            if (hr == ERR_DATE_IS_HOLIDAY) {
                printf("%04u-%02u-%02u: holiday or weekend, no date item created\n",
                       candidates[i].wYear, candidates[i].wMonth, candidates[i].wDay);
            } else {
                printf("%04u-%02u-%02u: InitializeDateItem failed: 0x%08lX\n",
                       candidates[i].wYear, candidates[i].wMonth, candidates[i].wDay, (unsigned long)hr);
            }
            continue;
        }

        if (IsDateCoveredByDateLog(hItem, hDateLog)) {
            printf("%04u-%02u-%02u: covered by the date log\n",
                   candidates[i].wYear, candidates[i].wMonth, candidates[i].wDay);
        } else {
            printf("%04u-%02u-%02u: NOT covered (not later than the first date, outside the holidays range, or invalid arguments)\n",
                   candidates[i].wYear, candidates[i].wMonth, candidates[i].wDay);
        }

        FreeDateItem(hItem);
    }

    exitCode = 0;

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