gpt4 book ai didi

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

转载 作者:太空宇宙 更新时间:2023-11-04 12:30:52 25 4
gpt4 key购买 nike

我刚开始学习 C++。

我使用的是带有 Visual Studio 版本的 Windows 7 Ultimate x64:

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 October 15
2009 June 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 标准:

The range and precision of times representable in clock_t and time_t are implementation-defined.

通常,time_t以自 1970-01-01 以来经过的秒数表示。这需要知道(或假设)日期和时间的时区(默认为 0:00:00),并且不仅要完美理解闰年,还要完美理解 leap seconds。 .

mktime()如果日期无效或无法在实现支持的 time_t 范围内转换,则返回错误代码 -1。因此,您的代码的更安全版本将检查潜在错误:

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

Online demo有一个运行良好的实现。对于 MSVC,转换对于 1970-01-01 之前的任何日期都会失败。已记录 here .

有更好的解决方案吗?

现在,如果您回到 1582-10-15,将其转换为用于比较两个旧日期的精确秒数没有多大意义。
因此,您可能需要考虑 boost::gregorian::date .该库能够处理从 1400-Jan-01 到 9999-Dec-31 的日期。它将日期转换为天数,而不是转换为秒数。

然后您可以通过获取天数差异来可靠地比较日期,例如 1582-10-15 和 1582-10-14:

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;

为什么旧日期如此复杂?

有趣的是,在上面的示例中,您会看到 BOOST 会进行理论计算。它将发现 1582-10-14 和 1582-10-15 ( demo ) 之间存在一天的差异。

当然,我们都知道这是荒谬的,因为introduction of the Gregorian calendar导致 1582 年 10 月 4 日紧随其后的是第二天的 1582 年 10 月 15 日。

另请注意,其他日期也存在此类日历不一致的情况,具体取决于国家/地区。以英国为例,根据维基百科,1752 年 9 月 2 日星期三之后是 1752 年 9 月 14 日星期四。

最后,如果您比较公历之前的日期,您需要接受歧义。以 1492 年 10 月 12 日为例,即哥伦布踏足美洲的那一天。它实际上是儒略历中的一个日期。在公历it would in reality be 21 October 1492 .

还有更简单的选择吗?

现在,time_t 有点遗留了。 C++标准指的是相关函数定义的C标准。

现代 C++ 提供 std::chronostd::chrono::time_point 类型。问题是目前没有可用的函数来转换日历和从日历转换:这些只会随 C++20 一起提供。

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

关于c++ - 如何比较两个 tm(来自 ctime)变量,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58683730/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com