我有以下代码:

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日无效。

考虑leap年,向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天的leap年,它仍然存在潜在的缺陷。那么正确的方法是什么?

我看到这个类似的问题:

C++ add 1 year to date

这意味着使用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

最佳答案

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

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 };

此操作始终定义明确,无论produce年如何,都会产生一个有效的时间点。在幕后,它只是添加了浮点值,这些值没有日历属性的概念。以下代码

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

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

尝试通过对各个日期成分进行算术来构造COleDateTime的初始解决方案在构造期间失败。构造函数验证其输入。传递(2021, 2, 29, 0, 0, 0)时,它确定无效的日期,并将 m_status 设置为invalid

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

关于c++ - 考虑leap年,向COledateTime添加年份的正确方法是什么?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/60473361/

10-11 18:40