考虑到闰年,向 COledateTime 添加一年的正确方法是什么?
What is the right way to add a year to COledateTime taking into account leap years?
我有这个代码:
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++ 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 Programs19\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 Programs19\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 Programs19\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
is a wrapper around the (hideously surprising) DATE
类型。它在内部存储一个 64 位浮点值,其中整数表示自 1899 年 12 月 30 日(午夜)以来的天数。小数部分表示一天中的时间(例如 0.25
表示 6 A.M.,而 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
天,这将是 return 2021 年 3 月 1 日)。
尝试通过对各个日期组件进行算术来构造 COleDateTime
的初始解决方案在构造过程中失败了。构造函数验证其输入。当传递 (2021, 2, 29, 0, 0, 0)
时,它确定无效日期,并将 m_status
设置为 invalid
。
1 这并不完全正确。 (-1 .. 0]
范围内的值映射到与其绝对值相同的时间点。请注意,例如COleDateTime{-0.25} == COleDateTime{0.25}
的计算结果为 false
,即使它们表示相同的时间点。
我有这个代码:
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++ 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 Programs19\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 Programs19\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 Programs19\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
is a wrapper around the (hideously surprising) DATE
类型。它在内部存储一个 64 位浮点值,其中整数表示自 1899 年 12 月 30 日(午夜)以来的天数。小数部分表示一天中的时间(例如 0.25
表示 6 A.M.,而 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
天,这将是 return 2021 年 3 月 1 日)。
尝试通过对各个日期组件进行算术来构造 COleDateTime
的初始解决方案在构造过程中失败了。构造函数验证其输入。当传递 (2021, 2, 29, 0, 0, 0)
时,它确定无效日期,并将 m_status
设置为 invalid
。
1 这并不完全正确。 (-1 .. 0]
范围内的值映射到与其绝对值相同的时间点。请注意,例如COleDateTime{-0.25} == COleDateTime{0.25}
的计算结果为 false
,即使它们表示相同的时间点。