GetDateItemHandleGap

Calculate the number of market days between two date items

Overview

GetDateItemHandleGap is the public wrapper around the internal GetMarketDaysGap(), resolving the holidays handle from a DATE_LOG_HANDLE's context automatically and returning the number of market days between two date items.

Purpose

Allows callers who only have a date log/range handle (not a raw holidays handle) to compute market-day gaps without manually extracting the holidays handle. Market days exclude weekends and the holidays defined by the associated holidays collection.

Key Features

Function Signature


LONG _Check_return_ _On_failure_(return > DATE_LOG_MAX) GetDateItemHandleGap(
    _In_    DATE_LOG_HANDLE hDateLogHandle,
    _In_    DATE_ITEM_HANDLE  hStartDate,
    _In_    DATE_ITEM_HANDLE  hEndDate,
    _In_    DateGapSpec DateGapType
);

Parameters

hDateLogHandle

[In] DATE_LOG_HANDLE

Handle whose associated holidays handle supplies the market calendar.

  • NULL: not allowed; the function fails with DATE_LOG_SENTINEL.
  • Valid values: a date log (or range) handle created with a holidays handle (InitializeDateLogHandle() requires one for date log and range handles).
  • Ownership/lifetime: the caller retains ownership; the handle is locked for the duration of the call.
hStartDate

[In] DATE_ITEM_HANDLE

The starting date item.

  • NULL: not allowed (invalid parameter, returns DATE_LOG_SENTINEL).
  • Valid values: a standalone item from InitializeDateItem() or an item from the collection (FindDateItemHandle()).
  • Ownership: read only; not retained or freed.
hEndDate

[In] DATE_ITEM_HANDLE

The ending date item.

  • NULL: not allowed (invalid parameter, returns DATE_LOG_SENTINEL).
  • Valid values / ownership: same as hStartDate. A start date later than the end date yields a negative result.
DateGapType

[In] DateGapSpec

Controls how the boundaries are counted.

  • InclusiveDateGap: both start and end dates are included in the gap.
  • ExclusiveDateGap: only dates between the start and the end are included.
  • Invalid values: any other value fails with DATE_LOG_SENTINEL.

Return Values

The function returns a LONG, not an HRESULT. Gaps may legitimately be negative, so detect failure with the _On_failure_ contract (result > DATE_LOG_MAX), not with FAILED/SUCCEEDED.

Return valueMeaning
0 .. DATE_LOG_MAX (or negative)Number of market days between the two dates; negative if hStartDate is after hEndDate.
DATE_LOG_SENTINELReturned on invalid parameters, invalid DateGapType, lock failure, or if the computed gap would exceed DATE_LOG_MAX.

Behavior and Operations

Validate & Lock Handle
→
Delegate to GetMarketDaysGap
→
Unlock & Return

Internally the function delegates entirely to the internal GetMarketDaysGap(), using pDateLog->pContext->hHolidays as the holidays handle. The date log handle is locked while the gap is computed and unlocked before return.

Remarks

Header note: datelog.h declares this functionality as signed int GetDateItemGap(hDateLogHandle, hStartDate, hEndDate, DateGapType) (same four parameters, different name and no _On_failure_ annotation) and describes InclusiveDateGap as "both start and end dates included" and ExclusiveDateGap as "only dates between start and end included". The parameter descriptions above follow that enumeration reference. Also note that because the result is a signed LONG, the failure test > DATE_LOG_MAX only works if DATE_LOG_SENTINEL is a positive value above DATE_LOG_MAX.

See Also

Sample Code


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

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

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

int main(void)
{
    HOLIDAYS_HANDLE  hHolidays = NULL;
    DATE_LOG_HANDLE  hDateLog = NULL;
    DATE_ITEM_HANDLE hStart = NULL;
    DATE_ITEM_HANDLE hEnd = NULL;
    FILETIME         ftStart = { 0 };
    FILETIME         ftEnd = { 0 };
    HRESULT          hr = E_FAIL;
    int              exitCode = 1;
    LONG             lInclusive = 0;
    LONG             lExclusive = 0;
    LONG             lReverse = 0;

    hr = InitializeDateLogHandle(NULL, DATE_LOG_MAX, NULL, &hHolidays, HandleIsForHolidays);
    if (FAILED(hr)) {
        printf("InitializeDateLogHandle [holidays] failed: 0x%08lX\n", (unsigned long)hr);
        goto cleanup;
    }

    hr = InitializeDateLogHandle(NULL, DATE_LOG_MAX, hHolidays, &hDateLog, HandleIsForDatelog);
    if (FAILED(hr)) {
        printf("InitializeDateLogHandle [date log] failed: 0x%08lX\n", (unsigned long)hr);
        goto cleanup;
    }

    if (!MakeFiletime(2026, 1, 5, &ftStart) || !MakeFiletime(2026, 3, 31, &ftEnd)) {
        printf("SystemTimeToFileTime failed: %lu\n", GetLastError());
        goto cleanup;
    }

    /* Standalone date items; the caller owns them and frees them with FreeDateItem. */
    hr = InitializeDateItem(hHolidays, &ftStart, NULL, &hStart);
    if (FAILED(hr)) {
        printf("InitializeDateItem [start] failed: 0x%08lX\n", (unsigned long)hr);
        goto cleanup;
    }

    hr = InitializeDateItem(hHolidays, &ftEnd, NULL, &hEnd);
    if (FAILED(hr)) {
        printf("InitializeDateItem [end] failed: 0x%08lX\n", (unsigned long)hr);
        goto cleanup;
    }

    /* The holidays collection is populated first, then the date log over the same range. */
    hr = LoadDateLogHandle(NULL, hStart, hEnd, hHolidays, NULL, 0);
    if (FAILED(hr)) {
        printf("LoadDateLogHandle [holidays] failed: 0x%08lX\n", (unsigned long)hr);
        goto cleanup;
    }

    hr = LoadDateLogHandle(NULL, hStart, hEnd, hDateLog, NULL, 0);
    if (FAILED(hr)) {
        printf("LoadDateLogHandle [date log] failed: 0x%08lX\n", (unsigned long)hr);
        goto cleanup;
    }

    /* Failure is reported in-band with DATE_LOG_SENTINEL, which is greater than DATE_LOG_MAX. */
    lInclusive = GetDateItemHandleGap(hDateLog, hStart, hEnd, InclusiveDateGap);
    if (lInclusive > DATE_LOG_MAX) {
        printf("GetDateItemHandleGap [inclusive] failed.\n");
        goto cleanup;
    }

    lExclusive = GetDateItemHandleGap(hDateLog, hStart, hEnd, ExclusiveDateGap);
    if (lExclusive > DATE_LOG_MAX) {
        printf("GetDateItemHandleGap [exclusive] failed.\n");
        goto cleanup;
    }

    /* Swapping start and end yields a negative gap. */
    lReverse = GetDateItemHandleGap(hDateLog, hEnd, hStart, InclusiveDateGap);
    if (lReverse > DATE_LOG_MAX) {
        printf("GetDateItemHandleGap [reversed] failed.\n");
        goto cleanup;
    }

    printf("Market days 2026-01-05 .. 2026-03-31\n");
    printf("  inclusive: %ld\n  exclusive: %ld\n  reversed : %ld\n", lInclusive, lExclusive, lReverse);
    exitCode = 0;

cleanup:
    FreeDateItem(hEnd);
    FreeDateItem(hStart);
    if (hDateLog != NULL) {
        hr = CloseDateLogHandle(hDateLog);
        if (FAILED(hr)) {
            printf("CloseDateLogHandle [date log] failed: 0x%08lX\n", (unsigned long)hr);
        }
    }
    if (hHolidays != NULL) {
        hr = CloseDateLogHandle(hHolidays);
        if (FAILED(hr)) {
            printf("CloseDateLogHandle [holidays] failed: 0x%08lX\n", (unsigned long)hr);
        }
    }
    return exitCode;
}