COleDateTime and comparing just date part

129 views Asked by At

I have two COleDateTime variables mapped to two controls on a dialog. The controls are set as short date. But, the dates selected by the user still include timestamps internally by MFC. So, when I test the variables for equality they fail.

Given 2 COleDateTime objects, how can we do comparison and ignore the time component? For example, I want to do this test:

(datMeeting >= m_sSetup.datStart && datWeek <= m_sSetup.datEnd)

But the Start / End (mapped to dialog) have time components even though I don't need them. I just want to compare dates.


At the moment I am doing it this way:

(datMeeting.GetDay() >= m_sSetup.datStart.GetDay() &&
datMeeting.GetMonth() >= m_sSetup.datStart.GetMonth() &&
datMeeting.GetYear() >= m_sSetup.datStart.GetYear())
&&
(datMeeting.GetDay() <= m_sSetup.datEnd.GetDay() &&
    datMeeting.GetMonth() <= m_sSetup.datEnd.GetMonth() &&
    datMeeting.GetYear() <= m_sSetup.datEnd.GetYear())
1

There are 1 answers

5
IInspectable On BEST ANSWER

COleDateTime internally stores a DATE value, accessible through its m_dt public member.

A DATE data type is a double-precision floating point value, where the whole numbers represent the date and the fractional part the time of day. Stripping the fractional part thus leaves a value representing the date only. Casting a floating point value to an integer value does exactly that:

auto const meeting_date = static_cast<int>(datMeeting.m_dt);
auto const start_date = static_cast<int>(m_sSetup.datStart.m_dt);
auto const end_date = static_cast<int>(m_sSetup.datEnd.m_dt);

if (meeting_date >= start_date && meeting_date <= end_date) {
    // ...
}

Of course there's nothing wrong writing a free function, e.g.,

[[nodiscard]]
bool is_date_in_range(COleDateTime date,
                      COleDateTime start,
                      COleDateTime end) noexcept
{
    auto const d = static_cast<int>(date.m_dt);
    auto const s = static_cast<int>(start.m_dt);
    auto const e = static_cast<int>(end.m_dt);

    return d >= s && d <= e;
}

that hides the intricacies and conveys a clear message about intent.


Note that the comparison expression as you have it now has a latent bug. It will start manifesting early next year. If datMeeting's year is strictly greater than datStart's year, its month and day must not be used in the comparison. If they are, some dates are wrongfully rejected.

The proposed solution above is immune to this defect as it operates on integer values which have a strict total ordering.