我刚刚开始学习C ++。
我正在使用Windows 7 Ultimate x64和Visual Studio版本:
Microsoft Visual Studio Enterprise 2017
Version 15.9.12
VisualStudio.15.Release/15.9.12+28307.665
Installed Version: Enterprise
Visual C++ 2017 00369-90013-89248-AA631
Microsoft Visual C++ 2017
Visual Studio Tools for CMake 1.0
Visual Studio Tools for CMake
我正在尝试比较这两个日期:
1582 10月15日2009年6月19日18:00
因为我想知道日期是否晚于1582年10月15日。
为此,我有这段代码:
#include <ctime>
tm date = { 0, 0, 18, 19, 5, 109, 0, 0, 0 };
tm gregorian = { 0, 0, 0, 15, 9, (1582 - 1900), 0, 0, 0};
double aux = std::difftime(std::mktime(&date), std::mktime(&gregorian));
但是aux
等于0.0
。我认为它必须不同于零。
我是在做错什么还是结果是正确的?
一旦使用较旧日期,应谨慎使用所使用的日期和时间函数。 较旧可能已经在1970-01-01的前一天开始。如果您回到1582-10-15,即Gregorian calendar的生效日期,则需要额外的护理。
在您的代码中,mktime()
将日期转换为time_t
,然后您可以使用该日期来区分两个日期。根据C标准:
clock_t
中可以表示的时间范围和精度time_t
是实现定义的。
通常,time_t表示为自1970-01-01起经过的秒数。这需要知道(或假设)日期和时间的时区(默认为0:00:00),并且不仅要对the年而且对leap seconds也要有一个全面的了解。
如果日期无效或无法在实现支持的time_t范围内转换,则mktime()
返回错误代码-1。因此,代码的安全版本将检查潜在的错误:
mktime()
std::time_t th = std::mktime(&date);
std::time_t tl = std::mktime(&gregorian);
if (th==-1 || tl==-1) {
std::cout<<"At least one of the date couldn't be converted"<<std::endl;
}
else {
double aux = std::difftime(th, tl);
std::cout << aux<< " "<< aux/3600.0/24.0/365.25 <<std::endl;
}
并在其上可以很好地实现。对于MSVC,转换在1970-01-01之前的任何日期都会失败。记录在案Online demo。
现在,如果您使时间回到1582-10-15,那么将其转换为用于比较两个旧日期的精确秒数并没有太大意义。因此,您可能需要考虑here。该库可以处理从1400年1月1日到9999年12月31日的日期。而不是转换为秒,而是将日期转换为天数。
然后您可以通过比较天数来可靠地比较日期1582-10-15和1582-10-14:
boost::gregorian::date
有趣的是,在上面的示例中,您将看到BOOST将进行理论计算。它将发现1582-10-14和1582-10-15(boost::gregorian::date
)之间存在一天的差异。
当然,我们都知道这很荒谬,因为using namespace boost::gregorian;
date d0(1582, 10, 15);
date d1(1582, 10, 25);
date d2(1582, 10, 14);
std::cout << d1-d0 << std::endl;
std::cout << d2-d0 << std::endl;
导致1582年10月4日紧随其后,直到1582年10月15日。
还请注意,根据国家/地区的不同,在其他日期也存在这种日历不一致的情况。以英国为例,根据维基百科的说法,1752年9月2日,星期三,然后是1752年9月14日,星期四。
最后,如果您比较公历之前的日期,则需要接受歧义。以1492年10月12日为例,哥伦布踏进美国的那一天。实际上,这是儒略历中表示的日期。在公历demo中。
现在,introduction of the Gregorian calendar有点陈旧。标准的C ++指的是C标准,以定义相关功能。
现代C ++提供it would in reality be 21 October 1492和time_t
类型。问题在于,暂时没有可用的函数可以与日历进行相互转换:这些仅与C ++ 20一起提供。
但是如果您只想比较两个旧日期,假设没有日历不一致,则可以只比较年份,如果相等,则比较月份和日期。我知道这听起来很荒谬,但是无论您的C ++版本和实现是什么,它都可以正常工作。