Determine if a date item is a market holiday
IsDateItemHoliday is the exported, self-locking counterpart of the internal IsMarketHoliday(). It accepts a DATE_LOG_HANDLE, DATE_RANGE_HANDLE or HOLIDAYS_HANDLE, resolves and locks the associated holidays handle as needed, and delegates the actual holiday check.
Unlike the BOOL predicates in this family, the result is a signed int with three outcomes: 1 (holiday), 0 (not a holiday) and -1 (error). Always test for a negative result before treating the value as a boolean, because -1 is non-zero and would be misread as “is a holiday” in an if test.
-1) apart from a definite negative answer (0).
signed int _Check_return_ _On_failure_(return < 0) IsDateItemHoliday(
_In_ DATE_ITEM_HANDLE hDateItem,
_In_ DATE_COLLECTION_HANDLE hDateLogHandle
);
_On_failure_(return < 0) documents that a negative return value signals failure. datelog.h declares the related IsDateItemMarketHoliday(hDateItem, hHolidays), which takes a HOLIDAYS_HANDLE and is documented there as returning 1 for a weekend or holiday, 0 for a valid market day and -1 on error; this page documents the date-collection-handle form IsDateItemHoliday and its holiday-only wording.
[In] DATE_ITEM_HANDLE
The date item to check.
InitializeDateItem, GetDateItemCopy or FindDateItemHandle.-1 is returned.FreeDateItem.[In] DATE_COLLECTION_HANDLE
A DATE_LOG_HANDLE, DATE_RANGE_HANDLE or HOLIDAYS_HANDLE that supplies (or is) the holidays handle used for the check.
InitializeDateLogHandle or DuplicateDateLogHandle, or a holidays handle from GetDateLogHolidayHandle. A log or range must have an associated holidays handle.-1 is returned.CloseDateLogHandle.| Value | Meaning |
|---|---|
1 | The date is a market holiday. |
0 | The date is not a market holiday. |
-1 | Invalid parameters, a locking failure, or an internal error occurred. |
The function returns plain integers, not HRESULTs; do not use SUCCEEDED/FAILED on the result. The related error codes ERR_DATE_IS_HOLIDAY, ERR_INVALID_DATELOG_HANDLE and ERR_INVALID_HOLIDAY_HANDLE in date_error.h are returned by other functions and are all folded into -1 or 1 here as described above.
The function resolves and locks the holidays handle it needs for the duration of the check and unlocks it afterwards, so calls from different threads against the same shared context are serialized by the library. A locking failure is reported as -1. Duplicate the handle with DuplicateDateLogHandle to give each thread its own handle.
GetDateLogHolidayHandle, you own that independently reference-counted handle and must close it.InitializeDateItem are already screened: a holiday date yields ERR_DATE_IS_HOLIDAY instead of an item. IsDateItemHoliday is therefore most useful for items obtained from other sources, such as FindDateItemHandle or GetDateItemCopy.IsDateItemCoveredByHolidaysHandle tests range coverage and treats a holiday as not covered.IsDateCoveredByDateLog combines a first-date check with holidays coverage.-1 is non-zero. Writing if (IsDateItemHoliday(...)) treats errors as holidays. Compare against 1, 0 and < 0 explicitly.IsDateItemCoveredByHolidaysHandleIsDateCoveredByDateLogIsValidDateLogHandleGetDateLogHolidayHandleInitializeDateItemFindDateItemHandleGetDateItemCopyFreeDateItemCloseDateLogHandleThe sample builds a holidays handle and a date log for 2025-01-02 through 2025-03-31, creates a date item for each candidate date, and classifies it with IsDateItemHoliday using explicit handling of the three possible results. Holiday dates that the library refuses to turn into items are reported separately. All 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);
}
/* 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, 20 }, /* a Monday; may be a holiday depending on the holidays data */
{ 2025, 2, 18 }, /* an ordinary trading day */
{ 2025, 3, 31 }
};
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;
}
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;
}
for (i = 0; i < sizeof(candidates) / sizeof(candidates[0]); i++) {
FILETIME ft = { 0 };
DATE_ITEM_HANDLE hItem = NULL;
int holiday = 0;
if (!MakeFileTime(candidates[i].wYear, candidates[i].wMonth, candidates[i].wDay, &ft)) {
continue;
}
hr = InitializeDateItem(hDateLog, &ft, NULL, &hItem);
if (hr == ERR_DATE_IS_HOLIDAY) {
/* The library refuses to create an item for a holiday or weekend. */
printf("%04u-%02u-%02u: InitializeDateItem reports a holiday or weekend\n",
candidates[i].wYear, candidates[i].wMonth, candidates[i].wDay);
continue;
}
if (FAILED(hr)) {
printf("%04u-%02u-%02u: InitializeDateItem failed: 0x%08lX\n",
candidates[i].wYear, candidates[i].wMonth, candidates[i].wDay, (unsigned long)hr);
continue;
}
holiday = IsDateItemHoliday(hItem, hDateLog);
if (holiday < 0) {
printf("%04u-%02u-%02u: the holiday check failed\n",
candidates[i].wYear, candidates[i].wMonth, candidates[i].wDay);
} else if (holiday == 1) {
printf("%04u-%02u-%02u: market holiday\n",
candidates[i].wYear, candidates[i].wMonth, candidates[i].wDay);
} else {
printf("%04u-%02u-%02u: not a market holiday\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;
}