LoadDateLogHandle

Generate or extend a date collection for a date log, range, or holidays handle

Overview

LoadDateLogHandle is the primary entry point for populating a DATE_LOG_HANDLE, DATE_RANGE_HANDLE or HOLIDAYS_HANDLE with date items. It can do so in three ways:

The behavior depends on the type of the handle that is passed in. The handle type is determined when the handle is created with InitializeDateLogHandle (HandleIsForDatelog, HandleIsForRange or HandleIsForHolidays).

Key Features

Function Signature


HRESULT _Must_inspect_result_ _Success_(SUCCEEDED(return)) LoadDateLogHandle(
    _In_opt_  PFILE_INFO                pFileInfo,
    _In_opt_  DATE_ITEM_HANDLE          hStartDate,
    _In_opt_  DATE_ITEM_HANDLE          hEndDate,
    _In_      DATE_LOG_HANDLE           hDateLogHandle,
    _In_opt_  PDATE_COLLECTION_PROGRESS pProgData,
    _In_      DWORD                     dwFlags
);

The declaration follows datelog.h, where the first parameter is PFILE_INFO pFileInfo. The file type is declared in mdts_io_.h, which is not documented in this help set. The function takes exactly six arguments, in this order.

Calling Convention

Standard C calling convention with SAL annotations for parameter validation and return value inspection.

Parameters

pFileInfo

[In, Opt] PFILE_INFO

The existing date-log file to parse.

  • Direction: input; the structure describes the file and is not freed by this function.
  • NULL: allowed. If NULL, both hStartDate and hEndDate must be supplied so that a fresh range can be generated.
  • Ownership / lifetime: owned by the caller and must remain valid for the duration of the call. File size must be a valid multiple of the record length; otherwise ERR_FILE_IS_CORRUPTED is returned.
hStartDate

[In, Opt] DATE_ITEM_HANDLE

Start date (inclusive) when generating or extending a range without a file, or the merge-favor-source anchor.

  • NULL: allowed when a file is supplied; required (together with hEndDate) when no file is supplied.
  • Valid values: a date item from InitializeDateItem; it must be earlier than hEndDate, otherwise ERR_DATE_EARLIER_BASE is returned.
  • Ownership / lifetime: remains owned by the caller; free it with FreeDateItem after the call.
hEndDate

[In, Opt] DATE_ITEM_HANDLE

End date (inclusive).

  • NULL: allowed. If NULL and auto-update is requested, the most recent calendar market date is used.
  • Valid values: a date item that is covered by the target handle’s holidays handle; otherwise ERR_DATE_NO_COVERED is returned.
  • Ownership / lifetime: remains owned by the caller; free it with FreeDateItem after the call.
hDateLogHandle

[In] DATE_LOG_HANDLE

The target handle (date log, range or holidays) to populate.

  • NULL: not allowed.
  • Valid values: a handle from InitializeDateLogHandle or DuplicateDateLogHandle. Its type is resolved from the handle; an unknown type yields ERR_BAD_HANDLE_TYPE.
  • Holidays handles: a holidays handle whose core is already populated cannot be overwritten (HRESULT_FROM_WIN32(ERROR_INVALID_HANDLE_STATE)).
  • Ownership / lifetime: remains owned by the caller and is populated in place; the handle remains open after the call and must be closed with CloseDateLogHandle.
pProgData

[In, Opt] PDATE_COLLECTION_PROGRESS

Optional progress-reporting structure updated during multithreaded file parsing.

  • NULL: allowed and supported; pass NULL when you do not need progress. Progress is only meaningful when a file is parsed.
  • Ownership / lifetime: owned by the caller. No initialization or cleanup is required (see DATE_COLLECTION_PROGRESS); treat its fields as read-only.
dwFlags

[In] DWORD

Bit flags that control loading. Combine with bitwise OR; pass 0 for no options.

FlagValue and meaning
DATE_LOG_AUTO_UPDATE_FLAG0x200 — Automatically extend a date log handle to the most recent market date. Requires a valid file argument and a DATE_LOG_HANDLE (not a range or holidays handle).
DATE_RANGE_MERGE_FAVOR_SOURCE8 — When auto-extending, favors the generated range’s GUIDs over existing overlap.
DATE_RANGE_MERGE_RESTORE_ON_FAILURE16 — Preserves the prior core so it can be restored if the load/merge fails.
PARSE_VERIFY_ENABLE_FLAG0x80 — Enables additional validation during file parsing.

Return Values

ValueMeaning
S_OKDate collection successfully loaded, generated or extended.
ERR_FILE_IS_CORRUPTEDThe file size is not a valid multiple of DATE_RECORD_LENGTH.
ERR_DATE_NO_COVEREDhEndDate is not covered by the handle’s holidays handle.
ERR_DATE_EARLIER_BASEhStartDate is not earlier than hEndDate.
ERR_DATELOG_ZERO_GAP / ERR_MAX_DATELOG_REACHEDReturned from the internal gap calculation (GetMarketDaysGap) when the range is empty or invalid, or too large (more than DATE_LOG_MAX items).
ERR_BAD_HANDLE_TYPEThe handle’s magic number does not resolve to a known handle type.
HRESULT_FROM_WIN32(ERROR_INVALID_HANDLE_STATE)A holidays handle already has a populated core (it cannot be overwritten) when a holidays load is requested.
Other failure HRESULTPropagated from internal helpers (file parsing, merge, hashing).

Use FAILED/SUCCEEDED to test the result; the value must be inspected (_Must_inspect_result_). The codes ERR_* are defined in date_error.h. On failure, the error date item (if any) is captured for later retrieval through GetDateLogHandleErrorInfo().

Behavior and Operations

Lock Handle→Dispatch by Handle Type→Parse / Generate→Hash + Merge (if needed)→Unlock

On failure, the old core is restored (if DATE_RANGE_MERGE_RESTORE_ON_FAILURE was set and a prior core existed) and the error date item (if any) is captured via GetDateLogCoreErrorItemInfo() for later retrieval through GetDateLogHandleErrorInfo().

Remarks

Thread Safety

The handle is locked for the duration of the load and unlocked before returning, so concurrent operations on the same shared context are serialized. Do not call other functions on the same handle from another thread and expect them to run in parallel with a load; use DuplicateDateLogHandle to give each thread its own handle onto the shared context.

Handle Lifetime and Ownership

Ordering and Related Functions

Note: datelog.h requires <Windows.h> to be included first and Windows 10 or later.

See Also

Sample Code

The sample generates a range without a file: it loads a holidays handle for 2025-01-02 through 2025-03-31, creates a date log that uses it, loads the same range into the log, and prints the number of items. It then shows a documented failure by trying to load an inverted range into a date range handle (ERR_DATE_EARLIER_BASE). To parse an existing file instead, pass a PFILE_INFO as the first argument (created by the mdts_io_.h file library, which is not covered here); add DATE_LOG_AUTO_UPDATE_FLAG to extend a file-backed log to the most recent market date. All date items and 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);
}

int main(void)
{
    int exitCode = 1;
    HRESULT hr = S_OK;
    FILETIME ftFirst = { 0 };
    FILETIME ftLast = { 0 };
    HOLIDAYS_HANDLE hHolidays = NULL;
    DATE_LOG_HANDLE hDateLog = NULL;
    DATE_LOG_HANDLE hRange = NULL;
    DATE_ITEM_HANDLE hFirst = NULL;
    DATE_ITEM_HANDLE hLast = NULL;
    DWORD dwLength = 0;

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

    /* 1. A holidays handle is generated first; the log and range reference it. */
    hr = InitializeDateLogHandle(NULL, DATE_LOG_MAX, NULL, &hHolidays, HandleIsForHolidays);
    if (FAILED(hr)) {
        printf("Creating the holidays handle failed: 0x%08lX\n", (unsigned long)hr);
        goto cleanup;
    }

    hr = InitializeDateItem(hHolidays, &ftFirst, NULL, &hFirst);
    if (FAILED(hr)) {
        printf("Creating the first date item failed: 0x%08lX\n", (unsigned long)hr);
        goto cleanup;
    }
    hr = InitializeDateItem(hHolidays, &ftLast, NULL, &hLast);
    if (FAILED(hr)) {
        printf("Creating the last date item failed: 0x%08lX\n", (unsigned long)hr);
        goto cleanup;
    }

    /* No file: generate the range [first, last]. Progress reporting applies to file parsing only. */
    hr = LoadDateLogHandle(NULL, hFirst, hLast, hHolidays, NULL, 0);
    if (FAILED(hr)) {
        printf("Loading the holidays handle failed: 0x%08lX\n", (unsigned long)hr);
        goto cleanup;
    }

    /* 2. Create the date log that uses the holidays handle and generate its dates. */
    hr = InitializeDateLogHandle(NULL, DATE_LOG_MAX, hHolidays, &hDateLog, HandleIsForDatelog);
    if (FAILED(hr)) {
        printf("Creating the date log failed: 0x%08lX\n", (unsigned long)hr);
        goto cleanup;
    }

    hr = LoadDateLogHandle(NULL, hFirst, hLast, hDateLog, NULL, 0);
    if (FAILED(hr)) {
        printf("Loading the date log failed: 0x%08lX\n", (unsigned long)hr);
        goto cleanup;
    }

    dwLength = GetDateCollectionLength(hDateLog);
    if (dwLength > DATE_LOG_MAX) {
        printf("GetDateCollectionLength reported a failure.\n");
        goto cleanup;
    }
    printf("The date log now holds %lu date items.\n", (unsigned long)dwLength);

    /* 3. Demonstrate a documented failure: the start date must be earlier than the end date. */
    hr = InitializeDateLogHandle(NULL, DATE_LOG_MAX, hHolidays, &hRange, HandleIsForRange);
    if (FAILED(hr)) {
        printf("Creating the range failed: 0x%08lX\n", (unsigned long)hr);
        goto cleanup;
    }

    hr = LoadDateLogHandle(NULL, hLast, hFirst, hRange, NULL, 0);
    if (hr == ERR_DATE_EARLIER_BASE) {
        printf("Rejected as expected: the start date is not earlier than the end date.\n");
    } else if (FAILED(hr)) {
        printf("Loading the range failed: 0x%08lX\n", (unsigned long)hr);
    } else {
        printf("Unexpected success loading the inverted range.\n");
    }

    exitCode = 0;

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