Generate or extend a date collection for a date log, range, or holidays handle
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:
hStartDate and hEndDate when no file is supplied;DATE_LOG_AUTO_UPDATE_FLAG).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).
DATE_COLLECTION_PROGRESS structure.DATE_LOG_AUTO_UPDATE_FLAG.DATE_RANGE_MERGE_RESTORE_ON_FAILURE.
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.
Standard C calling convention with SAL annotations for parameter validation and return value inspection.
[In, Opt] PFILE_INFO
The existing date-log file to parse.
NULL, both hStartDate and hEndDate must be supplied so that a fresh range can be generated.ERR_FILE_IS_CORRUPTED is returned.[In, Opt] DATE_ITEM_HANDLE
Start date (inclusive) when generating or extending a range without a file, or the merge-favor-source anchor.
hEndDate) when no file is supplied.InitializeDateItem; it must be earlier than hEndDate, otherwise ERR_DATE_EARLIER_BASE is returned.FreeDateItem after the call.[In, Opt] DATE_ITEM_HANDLE
End date (inclusive).
NULL and auto-update is requested, the most recent calendar market date is used.ERR_DATE_NO_COVERED is returned.FreeDateItem after the call.[In] DATE_LOG_HANDLE
The target handle (date log, range or holidays) to populate.
InitializeDateLogHandle or DuplicateDateLogHandle. Its type is resolved from the handle; an unknown type yields ERR_BAD_HANDLE_TYPE.HRESULT_FROM_WIN32(ERROR_INVALID_HANDLE_STATE)).CloseDateLogHandle.[In, Opt] PDATE_COLLECTION_PROGRESS
Optional progress-reporting structure updated during multithreaded file parsing.
NULL when you do not need progress. Progress is only meaningful when a file is parsed.[In] DWORD
Bit flags that control loading. Combine with bitwise OR; pass 0 for no options.
| Flag | Value and meaning |
|---|---|
DATE_LOG_AUTO_UPDATE_FLAG | 0x200 — 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_SOURCE | 8 — When auto-extending, favors the generated range’s GUIDs over existing overlap. |
DATE_RANGE_MERGE_RESTORE_ON_FAILURE | 16 — Preserves the prior core so it can be restored if the load/merge fails. |
PARSE_VERIFY_ENABLE_FLAG | 0x80 — Enables additional validation during file parsing. |
| Value | Meaning |
|---|---|
S_OK | Date collection successfully loaded, generated or extended. |
ERR_FILE_IS_CORRUPTED | The file size is not a valid multiple of DATE_RECORD_LENGTH. |
ERR_DATE_NO_COVERED | hEndDate is not covered by the handle’s holidays handle. |
ERR_DATE_EARLIER_BASE | hStartDate is not earlier than hEndDate. |
ERR_DATELOG_ZERO_GAP / ERR_MAX_DATELOG_REACHED | Returned 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_TYPE | The 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 HRESULT | Propagated 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().
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().
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.
CloseDateLogHandle.FreeDateItem after the call, on success and on failure.InitializeDateLogHandle first. A date log or range needs a populated holidays handle, so load the holidays handle (HandleIsForHolidays) before loading a log that depends on it.InitializeDateItem, which rejects holiday dates with ERR_DATE_IS_HOLIDAY.GetDateCollectionLength reports the number of items, and IsDateLogHandleUpToDate tells whether the log reaches the most recent market date.MergeDateLogHandle; to promote a merged range to a date log, see ConvertDateLogHandle.DATE_LOG_MAX (0x591C8 = 370,120) items (datelog.h).datelog.h requires <Windows.h> to be included first and Windows 10 or later.InitializeDateLogHandleInitializeDateItemMergeDateLogHandleConvertDateLogHandleIsDateLogHandleUpToDateGetDateCollectionLengthDuplicateDateLogHandleFreeDateItemCloseDateLogHandleThe 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;
}