如何比较两个tm(来自ctime)变量

问题描述 投票:1回答:1

我刚刚开始学习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。我认为它必须不同于零。

我是在做错什么还是结果是正确的?

c++ date calendar date-arithmetic gregorian-calendar
1个回答
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 1492time_t类型。问题在于,暂时没有可用的函数可以与日历进行相互转换:这些仅与C ++ 20一起提供。

但是如果您只想比较两个旧日期,假设没有日历不一致,则可以只比较年份,如果相等,则比较月份和日期。我知道这听起来很荒谬,但是无论您的C ++版本和实现是什么,它都可以正常工作。

© www.soinside.com 2019 - 2024. All rights reserved.