std::tm到std::time_t的转换会为1970年之前的特定日期(c++)提供错误



我目前正在尝试通过time_t存储出生日期。为此,我还使用了std::mktimestd::tm。但是,当我尝试将特定日期从std::tm转换为std::time_t时,它会返回-1,这表明转换不成功。我知道Unix时间戳应该存储从1970年1月1日UTC开始的秒数,但我找不到任何表明不允许使用负时间戳的参考。为什么会发生这种情况?我应该使用另一种替代方法来存储出生日期吗?

#include <ctime>
#include <iostream>
int main(int argc, char const *argv[])
{
int year = 1914;
int month = 1;
int day = 1;
std::tm tm{};
std::time_t timestamp;
tm.tm_year = year - 1900;
tm.tm_mon = month - 1;
tm.tm_mday = day;
timestamp = std::mktime(&tm);
std::cout << timestamp << std::endl;
return 0;
}

如果您有兴趣使用date1库将日期存储为天数,下面是它的样子:

#include "date/date.h"
#include <cassert>
#include <chrono>
#include <iostream>
int
main()
{
namespace chr = date;
//  namespace chr = std::chrono;
int year = 1914;
int month = 1;
int day = 1;
chr::sys_days timestamp = chr::year{year}/month/day;
int intstamp = timestamp.time_since_epoch()/chr::days{1};
std::cout << intstamp << 'n';
chr::year_month_day recover_birthday = chr::sys_days{chr::days{intstamp}};
assert(year  ==      int{recover_birthday.year()});
assert(month == unsigned{recover_birthday.month()});
assert(day   == unsigned{recover_birthday.day()});
std::cout << "min date = "  << chr::year::min()/01/01 << 'n';
std::cout << "max date =  " << chr::year::max()/12/31 << 'n';
}

输出:

-20454
min date = -32767-01-01
max date =  32767-12-31

上面我展示了转换的两种方式:

  1. {year, month, day}int
  2. int{year, month, day}

我还添加了{year, month, day}数据结构的自记录有效性范围。

这将适用于C++11/14/17。date1是一个开源的,免费的,只有头的库,不需要安装。只有#include "date/date.h"。如果您需要时区支持(本例不需要(,那么在同一链接上还有一个额外的、仅限标头的库。

如果您不想使用date1,这里记录了它为进行此计算而包装的算法。

date1库也是C++20<chrono>的预览。要将上述程序移植到C++20,请删除#include "date/date.h"并将namespace chr = date;更改为namespace chr = std::chrono;


1完全披露:我是这个图书馆的主要作者。我不想从这一努力中获得任何经济利益。但如果我不完全披露这些信息,有时人们会变得脾气暴躁。

最新更新