在 UTC 的 windows 上将 tm 转换为 time_t - _mkgmtime 返回 -1
Converting tm to time_t on windows in UTC - _mkgmtime returning -1
我正在尝试将 UTC ECMA date format strings 解析为 Windows 上的 std::chrono::system_clock::time_point
。
我的计划:
- 使用
scanf
将字符串加载到struct tm
- 使用
_mkgmtime
将其转换为 time_t
(我为此使用 _mkgmtime,因为它使用 UTC 时间,不像 mktime
,它使用当地时间)。
- 使用
std::chrono::system_clock::from_time_t
转换为time_point
但是,第 2 步总是为我返回 -1,给我第 3 步的虚假值。
tm
结构似乎有效,所以我不确定我做错了什么。
#include <chrono>
#include <iostream>
using namespace std;
int main() {
string timeStr = "2020-12-01T06:06:48Z";
struct tm tm = {0};
float s;
if (sscanf_s(timeStr.c_str(), "%d-%d-%dT%d:%d:%fZ", &tm.tm_year, &tm.tm_mon,
&tm.tm_mday, &tm.tm_hour, &tm.tm_min, &s) == 6) {
tm.tm_sec = static_cast<int>(s);
time_t t = _mkgmtime(&tm);
cout << "YEAR: " << tm.tm_year << endl; // 2020
cout << "MON: " << tm.tm_mon << endl; // 12
cout << "MDAY: " << tm.tm_mday << endl; // 1
cout << "HOUR: " << tm.tm_hour << endl; // 6
cout << "MIN: " << tm.tm_min << endl; // 6
cout << "SEC: " << tm.tm_sec << endl; // 48
cout << "TIME: " << t << endl; // -1
// TODO once this is solved:
auto tp = chrono::system_clock::from_time_t(t);
}
}
编译器是 MSVC 2019、C++17、x64。我无法升级到 C++20,否则我会为此使用新的计时工具。
在 tm
结构中,成员 tm_year
is the number of years since 1900。在 2020 年喂食意味着您实际提供的是 3920 年。
看来_mkgmtime
讨厌那一年。在我的系统上 _mkgmtime64
似乎也不起作用。它应该适合 64 位 time_t
,但绝对超出 32 位版本的范围。我找不到明确的、记录在案的 3920 被拒绝的原因或功能放弃的分界点。确保你有 64 位 time_t
.
但是在这种情况下 none 很重要,因为我们想要 2020 年。添加
tm.tm_year -= 1900;
tm.tm_mon -= 1; // valid range 0 to 11, not 1 to 12
转换前会解决问题。
这是它在 C++20 中的样子:
#include <chrono>
#include <iostream>
#include <sstream>
int
main()
{
using namespace std;
using namespace std::chrono;
string timeStr = "2020-12-01T06:06:48Z";
istringstream in{timeStr};
system_clock::time_point tp;
in >> parse("%FT%TZ", tp);
cout << tp << '\n'; // 2020-12-01 06:06:48.000000
}
使用 C++20 <chrono>
preview library,只需添加 #include "date/date.h"
和 using namespace date;
,它现在适用于 C++11/14/17。
我正在尝试将 UTC ECMA date format strings 解析为 Windows 上的 std::chrono::system_clock::time_point
。
我的计划:
- 使用
scanf
将字符串加载到struct tm
- 使用
_mkgmtime
将其转换为time_t
(我为此使用 _mkgmtime,因为它使用 UTC 时间,不像mktime
,它使用当地时间)。 - 使用
std::chrono::system_clock::from_time_t
转换为time_point
但是,第 2 步总是为我返回 -1,给我第 3 步的虚假值。
tm
结构似乎有效,所以我不确定我做错了什么。
#include <chrono>
#include <iostream>
using namespace std;
int main() {
string timeStr = "2020-12-01T06:06:48Z";
struct tm tm = {0};
float s;
if (sscanf_s(timeStr.c_str(), "%d-%d-%dT%d:%d:%fZ", &tm.tm_year, &tm.tm_mon,
&tm.tm_mday, &tm.tm_hour, &tm.tm_min, &s) == 6) {
tm.tm_sec = static_cast<int>(s);
time_t t = _mkgmtime(&tm);
cout << "YEAR: " << tm.tm_year << endl; // 2020
cout << "MON: " << tm.tm_mon << endl; // 12
cout << "MDAY: " << tm.tm_mday << endl; // 1
cout << "HOUR: " << tm.tm_hour << endl; // 6
cout << "MIN: " << tm.tm_min << endl; // 6
cout << "SEC: " << tm.tm_sec << endl; // 48
cout << "TIME: " << t << endl; // -1
// TODO once this is solved:
auto tp = chrono::system_clock::from_time_t(t);
}
}
编译器是 MSVC 2019、C++17、x64。我无法升级到 C++20,否则我会为此使用新的计时工具。
在 tm
结构中,成员 tm_year
is the number of years since 1900。在 2020 年喂食意味着您实际提供的是 3920 年。
看来_mkgmtime
讨厌那一年。在我的系统上 _mkgmtime64
似乎也不起作用。它应该适合 64 位 time_t
,但绝对超出 32 位版本的范围。我找不到明确的、记录在案的 3920 被拒绝的原因或功能放弃的分界点。确保你有 64 位 time_t
.
但是在这种情况下 none 很重要,因为我们想要 2020 年。添加
tm.tm_year -= 1900;
tm.tm_mon -= 1; // valid range 0 to 11, not 1 to 12
转换前会解决问题。
这是它在 C++20 中的样子:
#include <chrono>
#include <iostream>
#include <sstream>
int
main()
{
using namespace std;
using namespace std::chrono;
string timeStr = "2020-12-01T06:06:48Z";
istringstream in{timeStr};
system_clock::time_point tp;
in >> parse("%FT%TZ", tp);
cout << tp << '\n'; // 2020-12-01 06:06:48.000000
}
使用 C++20 <chrono>
preview library,只需添加 #include "date/date.h"
和 using namespace date;
,它现在适用于 C++11/14/17。