1

我有这个代码:

COleDateTime datStart = COleDateTime::GetCurrentTime(), datEnd;

// Update end date (one year later)
datEnd.SetDateTime(datStart.GetYear() + 1,
    datStart.GetMonth(),
    datStart.GetDay(),
    datStart.GetHour(),
    datStart.GetMinute(),
    datStart.GetSecond());

上述代码昨天(2020 年 2 月 29 日)失败,因为datEnd导致2021 年 2 月 29 日无效。

datStart在考虑闰年的情况下安全地增加一年的正确方法是什么?

C# 有:

DateTime theDate = DateTime.Now;
DateTime yearInTheFuture = theDate.AddYears(1);

MFC/C++ 的等价物是什么?

一种可能性是:

COleDateTimeSpan spnYear;
spnYear.SetDateTimeSpan(365, 0, 0, 0);

datEnd = datStart + spnYear;

但由于闰年有 366 天,它仍然存在潜在缺陷。那么正确的方法是什么?

我看到这个类似的问题:

C++ 添加 1 年至今

这意味着使用boost. 尽管从未将其用于日期操作,但我的项目确实有所提升。想知道这是否可以与COleDateTime对象一起使用?

使用boost

boost::gregorian::date dStart{ datStart.GetYear(), datStart.GetMonth(), datStart.GetDay() };
boost::gregorian::date dEnd = dStart + boost::gregorian::years(1);

datEnd.SetDateTime(
    dEnd.year(),
    dEnd.month(),
    dEnd.day(),
    datStart.GetMonth(),
    datStart.GetMinute(),
    datStart.GetSecond());

不编译。

4>D:\My Programs\2019\MeetSchedAssist\Meeting Schedule Assistant\PublishersDatabaseDlg.cpp(354,49): error C2398: Element '1': conversion from 'int' to 'boost::gregorian::date::year_type' requires a narrowing conversion
4>D:\My Programs\2019\MeetSchedAssist\Meeting Schedule Assistant\PublishersDatabaseDlg.cpp(354,70): error C2398: Element '2': conversion from 'int' to 'boost::gregorian::date::month_type' requires a narrowing conversion
4>D:\My Programs\2019\MeetSchedAssist\Meeting Schedule Assistant\PublishersDatabaseDlg.cpp(354,89): error C2398: Element '3': conversion from 'int' to 'boost::gregorian::date::day_type' requires a narrowing conversion
4

1 回答 1

3

COleDateTime是(非常令人惊讶的)DATE类型的包装器。它在内部存储一个 64 位浮点值,其中整数表示自 1899 年 12 月 30 日(午夜)以来的天数。小数部分表示一天中的时间(例如0.25,表示早上 6 点,0.5是中午)。每个浮点值都是合法值,代表一个唯一的1时间点。

COleDateTime向一个值添加一年等于将该值365.0(或任何适合您需要的值)添加到其内部表示中。这可以通过m_dt直接访问成员来完成

COleDateTime datEnd{ datStart.m_dt + 365.0 };

或通过使用COleDateTimeSpan

datEnd = datStart + COleDateTimeSpan{ 365.0 };
// or
datEnd = datStart + COleDateTimeSpan{ 365, 0, 0, 0 };

此操作始终是明确定义的,并且无论闰年如何都会产生一个有效的时间点。在引擎盖下,它只是添加浮点值,没有日历属性的概念。以下代码

COleDateTime datStart{ 2020, 2, 29, 0, 0, 0 };
COleDateTime datEnd{ datStart + COleDateTimeSpan{ 365.0 } };

将生成一个表示 2021 年 2 月 28 日的时间点(请注意,如果您添加366.0天数,这将返回 2021 年 3 月 1 日)。


COleDateTime尝试通过对各个日期组件进行算术来构造 a 的初始解决方案在构造过程中失败。构造函数验证其输入。当通过(2021, 2, 29, 0, 0, 0)时,它确定一个无效的日期,并设置m_statusinvalid.


1 这并不完全正确。范围内的值(-1 .. 0]映射到与其绝对值相同的时间点。请注意,即使它们代表相同的时间点,例如也会COleDateTime{-0.25} == COleDateTime{0.25}计算为。false

于 2020-03-02T07:35:50.287 回答