让 mktime() 在 C++ 中忽略 DST 和本地时区

Posted

技术标签:

【中文标题】让 mktime() 在 C++ 中忽略 DST 和本地时区【英文标题】:Have mktime() ignore DST and local time zone in C++ 【发布时间】:2021-09-29 05:49:18 【问题描述】:

我们的系统从供应商处接收 ASCII 格式“20210715083015”的数据。这个时间是美国东部时间,并且已经针对夏令时进行了调整。

自 Epoch 以来,我们的后端需要以纳秒为单位的时间。我正在尝试使用 mktime() 进行转换,但 mktime() 坚持要为 DST 添加一个小时,即使我强制 tm_isdst 为 0。

这里是sn-p的代码:

std::tm tmstr;
<breakdown ASCII time into tm structure>

tmstr.tm_isdst = 0;
cout << "isdst before: " tmstr.tm_isdst;
time_t seconds = std::mktime(&tmstr);
cout << ", isdst after: " tmstr.tm_isdst << endl;

这是输出:

isdst before: 0, isdst after: 1

它忽略了0的设定值,并应用自己的转换。

如何使用 mktime() 或类似的东西,而不尝试将时间调整到我的时区?我宁愿不必在内部设置时区,我只想让它从 tm 结构直接转换为秒。

这是 g++ 版本 7.3.1,在 Redhat 版本 6.10 下。

【问题讨论】:

你能用gmtime吗?当然,您必须将字符串调整为 UTC。 如果您查看 mktime 的手册页,您会看到 is_dst 在调用后更新,无论您将其设置为什么,以提供 /indication/ 是否 dst 将在在上述时间运行。 @bib 不幸的是,我看到的 mktime() 文档说它尊重 is_dst 的设置,但显然这是不正确的。 @PaulSanders 这需要检查我们是否会越过日期边界,而且我还必须知道 DST 当前是否生效。 【参考方案1】:

在这里发帖更容易...

从 mktime 手册页中,您没有阅读所写的内容...

mktime() 函数将分解的时间结构(表示为本地时间)转换为日历时间表示。该函数忽略调用者在 tm_wday 和 tm_yday 字段中提供的值。 tm_isdst 字段中指定的值通知 mktime() 对于 tm 结构中提供的时间,夏令时 (DST) 是否有效:正值表示 DST 有效;零表示 DST 无效;负值意味着 mktime() 应该(使用时区信息和系统数据库)尝试确定 DST 在指定时间是否有效。

mktime() 函数对 tm 结构的字段进行如下修改: tm_wday 和 tm_yday 设置为根据其他字段的内容确定的值;如果结构成员超出其有效区间,它们将被标准化(例如,10 月 40 日更改为 11 月 9 日); tm_isdst 分别设置(不管其初始值)为正值或 0,以指示 DST 在指定时间是否有效。调用 mktime() 还会使用有关当前时区的信息设置外部变量 tzname。

【讨论】:

我确实读过它,我只是误解了它会调整它是否我想要它,即使我为其他字段提供了有效值。【参考方案2】:

忽略0的设定值

不,它没有忽略该成员。

mktime().tm_isdst 考虑在内,然后将所有struct tm 成员调整为该日期的通常值,从而更改为.tm_isdst .tm_hour 预计在 OP 的情况下,因为 tmstr 是在 7 月 15 日的“20210715”白天。


我如何使用mktime() 或类似的东西,而不会尝试将时间调整到我的时区?

mktime() 是本地时间转换。通常的做法是让mktime()推导出日光标志。

tmstr.tm_isdst = -1;

这个时间是美国东部时间,并且已经针对夏令时进行了调整。

不,您声称它是美国标准东部时间 (EST)。美国东部时间 (ET) 有日光调整。

将您的时区从包含白天和标准时段的时区更改为仅包含标准时段的时区。研究setenv()。也许很简单:

// Implementation dependent code.
setenv("TZ", "EST5", 1);
tzset();
time_t seconds = mktime(&tmstr);

缺少关键问题:time_t 结果是否正确?

暂时忽略tmstr。报告了什么time_t 值? time_t 的预期值是多少?

我怀疑 OP 确实得到了正确的 time_t 值,只是不是 struct tm 中的预期结果。

【讨论】:

转换后的tm结构我懒得看。它返回了提前一小时设定的 time_t。 @FlyboyWilson 请在gmtime() 函数之前发布tmstr 的所有成员的所有值以及函数的返回数字结果。什么是环境变量TZ? “20210715083015”没有显示tmstr 的设置方式。可能它做得对,但也许不是? @FlyboyWilson “我懒得看转换后的 tm 结构。”鉴于mktime() 之后的问题cout &lt;&lt; ", isdst after: " tmstr.tm_isdst &lt;&lt; endl;,尚不清楚。

以上是关于让 mktime() 在 C++ 中忽略 DST 和本地时区的主要内容,如果未能解决你的问题,请参考以下文章

PHP mktime函数获取今天的开始和结束时间戳

在 Pandas 中,将 tz_localize 用于忽略 DST 的时间序列的最佳方法是啥?

转换不存在的 struct tm 时的 mktime 问题(因为日光变化时间)

c++ mktime和时间秒数的理解

php获取当前时间和转换格式

检测 C++ 中的 DST 更改