【发布时间】:2011-11-08 14:24:20
【问题描述】:
我是 C++ 新手,所以我想知道是否有一些库可以帮助更流畅地处理日期。
我有一个相当简单的任务。我有一个不同值的开始日期,当我将日期增加随机天数时,我必须得到它的日期。
我认为mktime 和time_t 对象接缝有助于我尝试做的事情。如果他们是答案,有人可以给我一个好的指南的链接吗?
【问题讨论】:
我是 C++ 新手,所以我想知道是否有一些库可以帮助更流畅地处理日期。
我有一个相当简单的任务。我有一个不同值的开始日期,当我将日期增加随机天数时,我必须得到它的日期。
我认为mktime 和time_t 对象接缝有助于我尝试做的事情。如果他们是答案,有人可以给我一个好的指南的链接吗?
【问题讨论】:
提升:Boost.Date
Qt 框架:QDateTime
托管代码项目:CTime
如果您想基本上自己处理日期和时间:C/C++ standard library
【讨论】:
一天通常是 86400 秒(leap seconds 除外)。您可以将其添加到time_t 并获得一个新的time_t 等。然后您可以使用mktime 和localtime 将其转换为struct tm,它可以用strftime 显示,也可以用@987654329 解析@
【讨论】:
time_t 不是一个可移植的解决方案,因为不同的库/平台可能对time_t 使用不同的表示(参见cplusplus.com/reference/ctime/time_t)。
嗯,有Boost Date and time module。如果您的编译器足够新,则可以使用 C++11 chrono 命名空间。
【讨论】:
我刚刚编写了自己的函数来将 Days、Months 和 Years 添加到现有的 DATE 类中。我还不能测试它,但也许它有帮助:
bool DATE::add(int Day, int Month, int Year){
int DaysPerMonth[13] = { 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
this -> Day += Day;
while(this -> Day > DaysPerMonth[ this-> Month ]){
if((this -> Year % 4 == 0 && this -> Year % 100 != 0) || this -> Year % 400 == 0){
DaysPerMonth[2] = 29;
}
this -> Day -= DaysPerMonth[ this-> Month ];
this -> Month++;
if(this -> Month > 12){
this -> Month = 1;
this -> Year++;
}
}
this -> Month = ( this -> Month + (Month % 12));
this -> Year = ( this -> Year + Year + (Month/12));
if((this -> Year % 4 == 0 && this -> Year % 100 != 0) || this -> Year % 400 == 0){
DaysPerMonth[2] = 29;
// check pathologic case wether date is 1 of March and added Year targets switchyear
if( this -> Day == 1 && this -> Month == 3){
this -> Day = 29;
this -> Month = 2;
}
}
if(this -> Month < 1 || this -> Month > 12 || this -> Day < 1 || this -> Day > DaysPerMonth[this->Month]){
valid = false;
cerr << "something went wrong, calculated Date is: " << this -> Day << "."<< this -> Month << "." << this -> Year << endl << flush;
return false;
}else{
return true;
}
}
【讨论】:
一个十年前的问题的新答案,因为时代变了,工具也变得更好了。
在 C++20 中,日期可以用几种不同的简洁有用的方式表示。
std::chrono::sys_daysstd::chrono::year_month_daystd::chrono::year_month_weekday(这不是一个详尽的列表)
上面的每个数据结构都代表一个日期,但各有优缺点,就像我们有几种容器类型表示一系列值(vector、list、deque 等)各有优缺点.
要为日期添加天数,sys_days 显然是日期表示的最佳选择。 sys_days 只不过是自 1970-01-01 以来(或之前)的天数。它是一个类型别名:
time_point<system_clock, days>
其中days 是std::chrono::duration:
duration<至少 25 位的有符号整数类型, ratio_multiply<ratio<24>, hours::period>>
因此,将days 添加到sys_days 只是底层的积分运算。
C++20 允许在{year, month, day} 概念和sys_days 之间进行无缝转换。所以这看起来像:
sys_days tp = sys_days{January/30/2022} + days{400}; // tp = 2023-03-06
积分可以用作上述公式的输入。但是,在使用 <chrono> 时,最好尝试保持在 <chrono> 的强类型系统中。:
int y = 2022;
int m = 1;
int d = 30;
int num_days = 400;
sys_days tp = sys_days{month(m)/d/y} + days{num_days}; // tp = 2023-03-06
无论如何,只需将tp 打印出来即可轻松观察到:
cout << tp << '\n';
输出:
2023-03-06
还提供其他格式选项,并且还可以通过编程方式访问年、月和日的值。最好将这些值保留在 chrono 强类型 year、month 和 day 中,但也可以转换为整数类型。
【讨论】:
使用标准ctime 标头的可移植方法是使用localtime()(或gmtime() 使用UTC 时间)构造一个mt 结构。然后,将天数添加到 tm_day 成员并使用 mktime() 将结构转换回时间。
tm_day 成员代表一个月中的某天,但mktime 允许它超过一个月的天数,甚至允许它为负值,以防需要减法 em> 从日期算起的天数,因此您不必担心换行。
一个例子:
#include <ctime>
time_t add_days(const time_t& time_value, int days) {
tm tm_value = *localtime(&time_value);
tm_value.tm_mday += days;
return mktime(&tm_value);
}
此方法的缺点可能是标准库可能无法以线程安全的方式实现localtime()。这可以通过使用 localtime_r() 来解决,但移植性较差。
【讨论】: