std::tm 到 std::time_t 转换给出 1970 年之前特定日期的错误 (c++)
std::tm to std::time_t conversion gives error for a specific date before 1970 (c++)
我目前正在尝试通过 time_t
存储出生日期。为此,我还使用了 std::mktime
和 std::tm
。但是,当我尝试将特定日期从 std::tm
转换为 std::time_t
时,它 returns -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
上面我展示了两种方式的转换:
- 从
{year, month, day}
到 int
- 从
int
到 {year, month, day}
我还为 {year, month, day}
数据结构添加了 self-documenting 有效范围。
这将适用于 C++11/14/17。 date1 是一个 open-source 免费的 header-only 库,无需安装。就 #include "date/date.h"
。如果您需要时区支持(本例不需要),那么在 link.
上还有一个非 header-only 库
如果您不想使用 date1,它包装的用于执行此计算的算法记录在 此处。
date1 库也是 C++20 <chrono>
的预览版。要将上述程序移植到 C++20,请删除 #include "date/date.h"
并将 namespace chr = date;
更改为 namespace chr = std::chrono;
.
1 完全披露:我是这个库的主要作者。我不会从这项工作中寻求任何经济利益。但有时如果我不完全公开这些信息,人们会变得脾气暴躁。
我目前正在尝试通过 time_t
存储出生日期。为此,我还使用了 std::mktime
和 std::tm
。但是,当我尝试将特定日期从 std::tm
转换为 std::time_t
时,它 returns -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
上面我展示了两种方式的转换:
- 从
{year, month, day}
到int
- 从
int
到{year, month, day}
我还为 {year, month, day}
数据结构添加了 self-documenting 有效范围。
这将适用于 C++11/14/17。 date1 是一个 open-source 免费的 header-only 库,无需安装。就 #include "date/date.h"
。如果您需要时区支持(本例不需要),那么在 link.
如果您不想使用 date1,它包装的用于执行此计算的算法记录在 此处。
date1 库也是 C++20 <chrono>
的预览版。要将上述程序移植到 C++20,请删除 #include "date/date.h"
并将 namespace chr = date;
更改为 namespace chr = std::chrono;
.
1 完全披露:我是这个库的主要作者。我不会从这项工作中寻求任何经济利益。但有时如果我不完全公开这些信息,人们会变得脾气暴躁。