- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我正在尝试使用 std::chrono::time_point<std::chrono::system_clock>
将当前年份存储在 1970 年之前的日期中,但是我遇到了一个关于从其内容读取到 std::tm
的问题结构。
我转换 time_point
到 time_t
首先,然后我读取它的值以获得 tm_year
值(value)。但是,当尝试这样做时,代码在使用 localtime_s
时失败了。 , 但是当我使用 gmtime_s
时它成功了.这仅适用于 1-1-1970 之前的日期,之后的日期可以很好地使用这两个函数。
下面的代码重现了错误。如果terstGmTimeVsLocalTime
用 utc=true
调用如果用 utc=false
调用它,它就可以工作它不会产生正确的输出。
#include <iomanip>
#include <time.h>
#include <iostream>
void testGmTimeVsLocaltime(const bool& utc) {
// Create time
std::tm timeInfoWrite = std::tm();
timeInfoWrite.tm_year = 1969 - 1900; // Year to parse, here it is 1969
timeInfoWrite.tm_mon = 0;
timeInfoWrite.tm_mday = 1;
timeInfoWrite.tm_hour = 1;
timeInfoWrite.tm_min = 0;
timeInfoWrite.tm_sec = 0;
timeInfoWrite.tm_isdst = -1;
std::chrono::time_point<std::chrono::system_clock> timePoint = std::chrono::system_clock::from_time_t(utc ? _mkgmtime(&timeInfoWrite) : std::mktime(&timeInfoWrite));
// Convert to time_t
std::time_t timeT = std::chrono::system_clock::to_time_t(timePoint);
// Read values
std::tm timeInfoRead;
if (utc) {
gmtime_s(&timeInfoRead, &timeT);
} else {
localtime_s(&timeInfoRead, &timeT);
}
// Output result
std::cout << (timeInfoRead.tm_year + 1900) << '\n';
// Wait for input
std::getchar();
}
int main() {
testGmTimeVsLocaltime(true); // Set to false to show bug
return 0;
}
utc=true
正如预期的那样,输出 1969。然而,utc=false
输出 1899(大概是因为发生错误并且 tm_year
被设置为 -1)。
有什么我想念的吗? The documentation没有具体说明 localtime_s
对于 1-1-1970 之前的日期应该会失败。
如果它有所作为,我正在使用 Windows 10 x64。
最佳答案
使用 Howard Hinnant's free, open-source date lib ,您可以完全避开笨拙、错误和容易出错的 C api,直接使用现代 <chrono>
基于系统:
#include "chrono_io.h"
#include "date.h"
#include <iostream>
void
testGmTimeVsLocaltime()
{
using namespace date;
// Create time
auto timeInfoWrite = 1969_y/jan/1;
sys_days timePoint = timeInfoWrite; // this is a chrono::time_point
std::cout << timePoint.time_since_epoch() << '\n'; // -365 days
// Convert to time_t
// no need
// Read values
year_month_day timeInfoRead = timePoint;
// Output result
std::cout << timeInfoRead.year() << '\n';
}
int
main()
{
testGmTimeVsLocaltime();
}
输出:
-365[86400]s
1969
有文字可以很容易地填写 year_month_day
struct 类似于 tm
的年月日部分.您可以轻松地将其转换为 std::chrono::time_point<system_clock, days>
(sys_days
)。这与 system_clock::time_point
相同, 但精度为天。它本身将隐式转换为秒精度 time_point
(类型定义为 sys_seconds
),或 system_clock::time_point
.
上面我只是输出了它的time_since_epoch()
这表明它比纪元早了 -365 天。
从来没有真正需要转换为 C API 数据结构,但如果您愿意,这很容易。例如,假设 time_t
自 1970-01-01 以来的秒数:
std::time_t timeT = sys_seconds{timePoint}.time_since_epoch().count();
std::cout << timeT << '\n';
哪些输出:
-31536000
反向转换(回到 year_month_day
)同样简单。如果要从 timeT
转换它只是稍微复杂一点:
year_month_day timeInfoRead = floor<days>(sys_seconds{seconds{timeT}});
这首先转换 time_t
至 chrono::seconds
, 然后到 seconds
-精度time_point
, 然后到 days
-精度time_point
, 最后到 year_month_day
字段类型( tm
-like)。
最后year_month_day
有一个 year()
可流式传输的 getter 成员函数。您可以显式转换 year
至 int
如果需要:
int{timeInfoRead.year()}
但我认为最好将年、月和日之类的东西保持为不同的类型,以便编译器可以帮助您在不小心混淆它们时发现它们。
最后,如果您真的想要计算机本地时区中的 1969-01-01 00:00:00,there's a library也这样做。并且它只是对上面简单程序的一个小修改。
#include "tz.h"
#include <iostream>
void
testGmTimeVsLocaltime()
{
using namespace date;
using namespace std::chrono;
// Create time
auto timeInfoWrite = 1969_y/jan/1;
auto timePoint = make_zoned(current_zone(), local_days{timeInfoWrite});
// Convert to time_t
std::time_t timeT = timePoint.get_sys_time().time_since_epoch().count();
std::cout << timeT << '\n';
// Read values
timePoint = sys_seconds{seconds{timeT}};
year_month_day timeInfoRead{floor<days>(timePoint.get_local_time())};
// Output result
std::cout << timeInfoRead.year() << '\n';
}
int
main()
{
testGmTimeVsLocaltime();
}
输出:
-31518000
1969
现在您创建一个 zoned_seconds
使用计算机的 current_zone()
时区,并转换您的 timeInfoWrite
至 local_days
而不是 sys_days
.
您可以从timePoint
中获取本地时间或系统时间.用于转换为 time_t
,系统时间最有意义:
std::time_t timeT = timePoint.get_sys_time().time_since_epoch().count();
现在(对我而言)输出是 5 小时后(18000 秒)。
-31518000
您可以使用 .get_local_time()
取回本地年份或系统 (UTC) 年份或 .get_sys_time()
.对我来说这没有区别( "America/New_York"
)。但如果你在 "Australia/Sydney"
,如果您请求 UTC 年份而不是 1969,您将得到 1968。这一切都非常容易通过简单地替换 "Australia/Sydney"
来模拟。或 "America/New_York"
对于 current_zone()
在上面的程序中。
是的,它适用于 Windows、VS-2013 及更高版本。时区库需要一些安装:https://howardhinnant.github.io/date/tz.html#Installation
关于c++ - localtime_s 失败,而 gmtime_s 在 1-1-1970 之前的日期成功,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42286616/
我正在尝试制作一个日历,所以我使用 time_t 和 localtime_s 来存储时间和日期信息,然后将其存储在 Calendar 类的各个成员中: void Callendar::Initiali
time_t t = time(0); struct tm *now = localtime(&t); 使用上面的代码,我可以像这样简单地获取日期: int yearNow = (now.tm_yea
以下 C++ 代码无法使用 VS2015 进行编译: #include #include void main() { const time_t t = std::time(nullptr)
好像localtime_s() (相当于标准 localtime_r )包含 MSVC 中的关键部分。 为了比较,这里有 2 个示例应用程序,一个是 localtime_s在一个循环中,另一个 gmt
time_t rawtime; struct tm * timeinfo; time ( &rawtime ); timeinfo = localtime ( &rawtime ); 这将返回:警告
我写了一个跨平台代码,给出了当前日期 (mm/dd/yy) 和时间 (hh/mm/ss) 和完整日期 (yyyymmdd),此代码适用于 windows(MSVS2015) 但不适用于Linux(GC
我正在使用 C++ 中的一个函数来帮助获取当月的整数。我进行了一些搜索并找到了一个使用本地时间的,但我不想将其设置为删除警告,因此我需要使用 localtime_s。但是当我使用它时,我的指针不再起作
我编写了以下接收时间点并返回带毫秒的 ISO 字符串的函数: std::string TimePointToISOString(const std::chrono::time_point& time)
我正在尝试使用 std::chrono::time_point 将当前年份存储在 1970 年之前的日期中,但是我遇到了一个关于从其内容读取到 std::tm 的问题结构。 我转换 time_poin
我是一名优秀的程序员,十分优秀!