Calculate the number of market days between two date items in a date log
GetDateItemHandleGap calculates the number of market days between two date items within a validated date log handle context. This function is the public-facing wrapper around the core GetMarketDaysGap() implementation, providing thread-safe mutex protection and handle validation.
This function enables applications to determine the count of business/market days between two dates, excluding weekends and holidays as defined by the date log's associated holidays collection. The result can be:
GetMarketDaysGap() for holiday checking
LONG _Check_return_ _Success_(return != DATE_LOG_SENTINEL) GetDateItemHandleGap(
_In_ DATE_LOG_HANDLE hDateLogHandle,
_In_ DATE_ITEM_HANDLE hStartDate,
_In_ DATE_ITEM_HANDLE hEndDate,
_In_ DateGapSpec DateGapType
);
Standard C calling convention with SAL annotations for parameter validation and return value inspection.
_Check_return_: Compiler warning if caller ignores return value_Success_(return != DATE_LOG_SENTINEL): Success condition: return value not equal to sentinel_In_: Input parameter (non-NULL, unchanged)[In] DATE_LOG_HANDLE
Handle to the date log that owns the date items and provides access to the holidays collection.
InitializeDateLogHandle() or LoadDateLogHandle()IsValidDateLogHandle() before calling this function[In] DATE_ITEM_HANDLE
Handle to the starting date item for gap calculation.
[In] DATE_ITEM_HANDLE
Handle to the ending date item for gap calculation.
[In] DateGapSpec
Specifies whether the gap includes or excludes the boundary dates.
| Enumeration Value | Numeric | Description |
|---|---|---|
| ExclusiveDateGap | 0 | Excludes both boundary dates from the count. Counts only dates strictly between start and end. Adjacent dates yield gap of -1. |
| InclusiveDateGap | 1 | Includes both boundary dates in the count. For identical dates, returns 0. For adjacent dates, returns 1. Recommended for most use cases. |
Gap calculation succeeded. Positive value indicates end date is chronologically after start date. Magnitude represents count of market days.
Both dates are identical (with inclusive gap specification).
End date is chronologically before start date. Magnitude represents absolute count of market days between dates.
Gap calculation failed. Returned in these scenarios:
| Return Value | Meaning | Action |
|---|---|---|
| > 0 | End date is after start date; magnitude is day count | Use value for gap calculation |
| == 0 | Dates are identical | Use value; no gap exists |
| < 0 | End date is before start date; negate for absolute count | Use abs(value) or negate based on logic |
| DATE_LOG_SENTINEL | Error occurred; computation not performed | Check handle validity and date values; retry if appropriate |
Calls IsValidDateLogHandle(hDateLogHandle). If false, returns DATE_LOG_SENTINEL immediately.
Checks:
If any check fails, returns DATE_LOG_SENTINEL.
Acquires ((PDATE_LOG)hDateLogHandle)->pContext->hMutex with INFINITE timeout.
MergeDateLogHandle() or other operations.
Within the __try block, calls GetMarketDaysGap() with:
In the __finally block, always releases the mutex to ensure cleanup even on exception.
The function delegates to GetMarketDaysGap(), which:
The underlying GetMarketDaysGap() handles date order internally:
// Assuming hDateLog is valid and contains dates from 2025-01-01 onwards
// Weekends and holidays are properly configured
DATE_ITEM_HANDLE hDate1 = NULL;
DATE_ITEM_HANDLE hDate2 = NULL;
// Create date items for 2025-01-06 (Monday) and 2025-01-10 (Friday)
FILETIME ft1 = { /* 2025-01-06 */ };
FILETIME ft2 = { /* 2025-01-10 */ };
InitializeDateItem(hDateLog, &ft1, NULL, &hDate1);
InitializeDateItem(hDateLog, &ft2, NULL, &hDate2);
// Calculate market days between the dates (inclusive)
LONG lGap = GetDateItemHandleGap(
hDateLog,
hDate1,
hDate2,
InclusiveDateGap // Include both boundary dates
);
if (lGap != DATE_LOG_SENTINEL) {
printf("Market days from Jan 6 to Jan 10: %ld\n", lGap);
// Output: 5 (Mon, Tue, Wed, Thu, Fri)
} else {
printf("Error calculating gap\n");
}
FreeDateItem(hDate1);
FreeDateItem(hDate2);
// Dates provided in reverse chronological order
DATE_ITEM_HANDLE hLater = NULL; // 2025-01-10
DATE_ITEM_HANDLE hEarlier = NULL; // 2025-01-06
// ... initialize hLater and hEarlier ...
LONG lGap = GetDateItemHandleGap(
hDateLog,
hLater, // Passed as "start" (chronologically later)
hEarlier, // Passed as "end" (chronologically earlier)
InclusiveDateGap
);
if (lGap != DATE_LOG_SENTINEL) {
printf("Gap: %ld\n", lGap);
// Output: -5 (negative because end is before start)
printf("Absolute gap: %ld\n", labs(lGap));
// Output: 5
} else {
printf("Error calculating gap\n");
}
DATE_LOG_HANDLE hDateLog = NULL;
DATE_ITEM_HANDLE hDate1 = NULL;
DATE_ITEM_HANDLE hDate2 = NULL;
// ... initialize handles ...
// Case 1: Invalid date log handle
LONG lGap = GetDateItemHandleGap(NULL, hDate1, hDate2, InclusiveDateGap);
if (lGap == DATE_LOG_SENTINEL) {
printf("Error: Invalid date log handle\n"); // Expected
}
// Case 2: NULL date items
lGap = GetDateItemHandleGap(hDateLog, NULL, hDate2, InclusiveDateGap);
if (lGap == DATE_LOG_SENTINEL) {
printf("Error: NULL start date\n"); // Expected
}
// Case 3: Invalid gap type (> 1)
lGap = GetDateItemHandleGap(hDateLog, hDate1, hDate2, 99);
if (lGap == DATE_LOG_SENTINEL) {
printf("Error: Invalid gap type\n"); // Expected
}
// Same two dates, different gap specifications
DATE_ITEM_HANDLE hDate1 = /* Monday */;
DATE_ITEM_HANDLE hDate2 = /* Tuesday */;
// Inclusive: counts both Mon and Tue
LONG lInclusiveGap = GetDateItemHandleGap(
hDateLog,
hDate1,
hDate2,
InclusiveDateGap
);
printf("Inclusive gap: %ld\n", lInclusiveGap); // Output: 1 (Mon and Tue counted)
// Exclusive: counts no dates between Mon and Tue (adjacent dates)
LONG lExclusiveGap = GetDateItemHandleGap(
hDateLog,
hDate1,
hDate2,
ExclusiveDateGap
);
printf("Exclusive gap: %ld\n", lExclusiveGap); // Output: -1 (no dates between)
Fully thread-safe. The function acquires the date log context mutex before accessing the holidays handle or performing gap calculation.
((PDATE_LOG)hDateLogHandle)->pContext->hMutexGetMarketDaysGap() computation
// Thread 1
LONG gap1 = GetDateItemHandleGap(hDateLog, hDate1, hDate2, InclusiveDateGap);
// Thread 2 (may block if Thread 1 is still computing)
LONG gap2 = GetDateItemHandleGap(hDateLog, hDate3, hDate4, InclusiveDateGap);
// Thread 3 (may also block)
LONG gap3 = GetDateItemHandleGap(hDateLog, hDate5, hDate6, InclusiveDateGap);
// Threads execute sequentially with mutex serialization
INFINITE timeout for mutex acquisition,
calling threads will block indefinitely if:
If this function returns DATE_LOG_SENTINEL:
IsValidDateLogHandle()GetMarketDaysGap(): Core implementation called by this wrapperInitializeDateItem(): Create date items for gap calculationIsMarketHoliday(): Check if a single date is a holidayIsValidDateLogHandle(): Validate date log handlesNewDateItem(): Allocate standalone date items