如何比较两个tm(来自ctime)变量
How to compare two tm (from ctime) variables
我刚刚开始学习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 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年,也就是公历的生效日期,那么就需要格外小心。
怎么了
在代码中,mktime()
将一个日期转换为time_t
,然后用它来区分两个日期。根据C标准:
clock_t
和CCD_ 6是实现定义的。
通常,time_t以自1970-01-01以来经过的秒数表示。这需要知道(或假设(日期和时间的时区(默认为0:00:00(,并且不仅要对闰年,还要对闰秒有一个完美的了解。
如果日期无效或无法在实现支持的time_t范围内转换,mktime()
将返回错误代码-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;
}
在线演示,并提供了一个运行良好的实现。对于MSVC,转换在1970-01-01之前的任何日期都失败。这里有记录。
有更好的解决方案吗
现在,如果你回到1582-10-15年,那么将其转换为比较两个旧日期的精确秒数就没有那么大意义了
因此,您可能需要考虑boost::gregorian::date
。这个库可以处理从1400-01年1月到9999-31年12月的日期。它不是转换为秒,而是将日期转换为天数。
然后,您可以通过获得天数差异来可靠地比较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之间找到一天的差异(演示(。
当然,我们都知道这是荒谬的,因为格里高利历的引入导致1582年10月4日紧接着是1582年的10月15日。
另请注意,根据国家的不同,其他日期也存在这种日历不一致的情况。例如,根据维基百科的数据,1752年9月2日星期三是1752年九月14日星期四。
最后,如果你比较公历之前的日期,你需要接受歧义。以1492年10月12日为例,哥伦布在美洲踏上了一只脚。事实上,这是儒略历中的一个日期。在公历中,它实际上是1492年10月21日。
有更简单的选择吗
现在,time_t
有点过时了。C++标准是指定义相关函数的C标准。
现代C++提供了std::chrono
和std::chrono::time_point
类型。问题是,目前还没有可用的函数可以转换到日历和从日历转换:这些函数只能与C++20一起提供。
但是,如果你只想比较两个旧日期,假设没有日历不一致,你可以只比较年份,如果相等,则比较月份,如果相等则比较日期。我知道这听起来很荒谬,但无论你的C++版本和实现是什么,这都会毫无问题地工作
- 来自 std::list 的迭代器 .end() 按预期返回"0xcdcdcdcdcdcdcdcd"但 .begin()
- 2D数组来自文本输入,中间有空格
- 通过继承类使用来自不同命名空间的运算符
- Cuda C++:设备上的Malloc类,并用来自主机的数据填充它
- C++:来自外部文件的Trivia
- 如何处理来自核心指南检查器的关于gsl::at的静态分析警告
- 针对遗留库的链接:来自预制makefile的-lgfortranbegin
- 如何在C++中正确引用来自不同类的类的对象?
- Qt中来自不同功能的按钮引用
- C++包含来自 #include "DevEngine/Core.h" 的错误
- Eigen c++ 三角形来自
- 来自 DLL 的函数调用 [表观调用的括号前面的表达式必须具有(指向-)函数类型]
- C++:如何将 unix 时间的字符串转换为 *tm?(使用时间错误:"cannot convert 'String' to 'tm*' ")
- 来自 Android 应用程序内部的 boost 类型的 boost::wrapexcept<boost::system::system_error> 的未捕获异常
- 中止信号来自 C++ 中的中止(3) (SIGABRT)
- 如何多次询问来自QML对话框的输入?
- 如何强制 Thrift 仅接受来自本地主机的连接
- 使 ld 忽略来自 /etc/ld.so.conf 的目录
- 来自逆 vp 矩阵和相机位置的光线方向不正确
- 如何比较两个tm(来自ctime)变量