C++ timegm 将 DST 转换为未来某个给定时间的某个时区?

2024-04-09

我需要在我的班级中从 UTC 时间准确转换为给定时区的本地时间,无论 DST 是否有效。我的问题是,当我使用struct tm我必须提供 tm_isdst 成员,或者将其保留为 -1 以自动确定。

from mktime(3) - linux man page:
"The value specified in the tm_isdst field informs mktime() whether or not daylight saving time (DST) is in effect for the time supplied in the tm structure:
a positive value means DST is in effect;
zero means that DST is not in effect;
and a negative value means that mktime() should (use timezone information and system databases to) attempt to determine whether DST is in effect at the specified time.

现在这是我的问题。我正在与来自世界各地的交易所合作(来自芝加哥、纽约、圣保罗、墨尔本、布宜诺斯艾利斯、约翰内斯堡、上海、首尔......)。我有一个表,其中包含每个交易所的每个时区名称:例如非洲/约翰内斯堡、美国/芝加哥、美国/温尼伯。

我正在处理的数据是某些特定期货和期权金融工具的到期数据。我收到的数据始终采用 UTC 格式,我需要转换为交易所的本地时间。

长话短说,我当前的实现是为那些不应生效 DST 的资产的到期时间增加 1 小时(例如,在 12 月到期且当地时间为美国/芝加哥的工具,应添加 -360 分钟偏移量)和 DST 0,而另一个在同一时区的 6 月到期的应该有 -360 时区偏移 +60 DST 偏移,这将是 UTC 时间戳的 -300 偏移。我目前遇到的问题是,例如12 月,我得到的是上午 9:30,而不是上午 8:30,因为 UTC 时间戳已经包含 dst 偏移量。

这是我进行转换的函数,它显然已损坏:

#ifdef WIN32
#define timegm _mkgmtime
#endif

SimpleDateTime BusinessDateCalculator::UTC2TZ(const SimpleDateTime& utcDateTime, const int tz_utc_offset, const int tz_dst)
{
    struct tm stm;
    memset(&stm, 0, sizeof(stm));
    stm.tm_year = utcDateTime.getYear() - 1900;
    stm.tm_mon = utcDateTime.getMonth() - 1;
    stm.tm_mday = utcDateTime.getDay();
    stm.tm_hour = utcDateTime.getHour();
    stm.tm_min = utcDateTime.getMinute();
    stm.tm_sec = utcDateTime.getSecond();
    stm.tm_isdst = -1; //see note at the top of this file

    time_t tt = timegm( &stm );
    tt += (tz_utc_offset + tz_dst) * 60;

    struct tm ntm;
    memset(&ntm, 0, sizeof(ntm));
    gmtime_r( &tt, &ntm );
    return SimpleDateTime(ntm.tm_year + 1900, ntm.tm_mon + 1, ntm.tm_mday, ntm.tm_hour, ntm.tm_min, ntm.tm_sec, utcDateTime.getMillisecond());
}

其中 SimpleDateTime 是具有附加功能的日期时间类,例如从不同日期/时间格式(SQL、FIX、Timeonly、DateOnly)进行转换。

我随时都有某个交易所的时区信息。我的问题是我可以以某种方式提供时区名称,然后让timegm执行数据库搜索并确定美国/芝加哥时区的 DST 是否于 2014 年 12 月 19 日生效,因此不在 UTC 时间上添加额外的 60 分钟,并且在同一日期(例如在南部地区)半球时区 America/Sao_Paulo 的有效期至 2015 年 2 月 16 日,对于此时间戳,应添加 60 分钟以获得给定日期的正确当地时间。


当您通过 IANA 标识符引用时区时(例如"America/Chicago") - 已包含所有 DST 信息和时区的完整历史记录。至少,它在原始源数据中是这样的IANA 时区数据库 http://iana.org/time-zones.

你提到Boost http://www.boost.org/(在评论中)。虽然 Boost 确实支持这些类型的标识符,但它错误地认为它们是永久固定的。但事实并非如此,因为世界时区的偏移量和 DST 规则一直在变化。考虑到美国在 2007 年更改了 DST 规则,而俄罗斯则在今年晚些时候(2014 年 10 月)大幅更改了其时区。如果你看一下提升时区数据文件 https://github.com/boostorg/date_time/blob/master/data/date_time_zonespec.csv,您会看到它的格式剥离了所有历史记录,仅将每个标识符映射到一组规则。因此,我建议您这样做not使用 Boost 进行本地时区转换。

相反,请考虑使用ICU http://icu-project.org/。除此之外,它还包括时区转换功能,并使用 IANA 时区数据库的完整副本。你可以在这里阅读更多, http://userguide.icu-project.org/datetime/timezone并看到示例代码在这里。 http://userguide.icu-project.org/datetime/timezone/examples我对 C++ 不是特别熟练,但看来你可以使用 ICUCalendar类将 UTC 时间投影为特定时区的本地时间。

另一种选择是使用内置的时区函数GNU C 库 http://www.gnu.org/software/libc/documentation.html。它还使用完整时区数据库。有一个使用 IANA/Olson 标识符将 UTC 转换为本地时间的简单示例在这个网站上 http://rl.se/convert-utc-to-local-time,我也在下面发布了:

/*
    C source code example: Convert UTC to local time zone, considering daylight
    savings. Uses mktime(), gmtime() and localtime(). Works for dates between
    years 1902 and 2037. Should compile and run with any recent GNU C if your
    tzdata is healthy. Written by Robert Larsson  http://rl.se

    Code put in public domain; do what you want with it.
*/

#include    <stdio.h>
#include    <stdlib.h>
#include    <time.h>

#define     DESTZONE    "TZ=Europe/Stockholm"       // Our destination time zone

int main(void)
{
    struct tm   i;
    time_t      stamp;                              // Can be negative, so works before 1970

    putenv("TZ=UTC");                               // Begin work in Greenwich …

    i.tm_year = 2009-1900;                          // Populate struct members with
    i.tm_mon  = 8-1;                                // the UTC time details, we use
    i.tm_mday = 29;                                 // 29th August, 2009 12:34:56
    i.tm_hour = 12;                                 // in this example
    i.tm_min  = 34;
    i.tm_sec  = 56;

    stamp = mktime(&i);                             // Convert the struct to a Unix timestamp

    putenv(DESTZONE);                               // Switch to destination time zone

    printf("UTC  : %s", asctime(gmtime(&stamp)));
    printf("Local: %s", asctime(localtime(&stamp)));

    return 0;                                       // That’s it, folks.
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

C++ timegm 将 DST 转换为未来某个给定时间的某个时区? 的相关文章

随机推荐

  • 使用spring构建Web项目时如何修复MojoFailureException

    最近我使用spring STS和roo 1 2 0 M1来构建一个web项目 我设置了 jpa 并创建了一个具有某些字段的实体 并为该实体创建了一个存储库和一个服务层 然后当我执行测试时 它给出了以下错误 roo gt perform te
  • MongoDB 查询速度过慢,即使查询很简单并且与索引对齐

    我正在运行一个 MongoDB 服务器 这实际上就是它运行的全部内容 该服务器拥有 64GB RAM 和 16 个内核 以及 2TB 硬盘空间 文档结构 数据库有一个集合domains拥有大约 2000 万份文档 每个文档中都有相当多的数据
  • SQL JOIN 查询编写

    我正在尝试编写一个涉及两个表的简单查询 人 表有其独特之处person id and a name 朋友 表有一个person id and a friend id这是一个 FK 到person id在人员表中 person
  • StringBuilder 真的比连接十几个字符串慢吗?

    StringBuilder 真的比连接十几个字符串慢吗 编译器如何优化字符串连接 使得使用 连接十几个字符串会比StringBuilder更好 从一本 本 沃森写的 书中说 字符串连接 用于简单连接已知的 在编译时 time 字符串数量 只
  • 在AngularJS控制器中转换日期格式

    我编写以下代码来打印当前日期时间 scope date new Date 然后我使用 console log 打印相同的内容 console log scope date 它工作正常 2017 年 1 月 24 日星期二 16 36 06
  • 带点运算符的常数 (VBA)

    我想要一个常量材料的目录 这样我就可以使用如下所示的代码 Dim MyDensity MySymbol MyDensity ALUMINUM Density MySymbol ALUMINUM Symbol 显然 铝的密度和符号预计不会改变
  • WP - 检查 wp_insert_post 之前是否存在帖子

    如何检查 wp insert post 之前的帖子是否存在以避免重复 如果我删除 if 语句 post exists 并继续重新插入产生多个重复的帖子 下面的代码就可以工作 我用 post exists 编写了 if 语句 只是为了开始实现
  • 如何禁用 phpmailer 在浏览器上显示配置详细信息

    我不知道为什么电子邮件配置详细信息和状态在成功发送电子邮件后显示在我的页面上 如何禁用它 消息 服务器 gt 客户端 220 mx google com ESMTP ss3sm18138445pab 43 gsmtp客户端 gt 服务器 E
  • 如何识别用户空间和内核空间之间的特定套接字?

    我在用户空间中有一个库 可以拦截套接字层调用 例如socket connect accept 等等 我只处理 TCP 套接字 在内核空间中 我有一个网络内核模块 它处理所有 TCP 连接 我需要能够在驱动程序中识别哪些套接字被用户空间库拦截
  • VIM 高亮匹配开始/结束

    我正在尝试找到一个插件 它将突出显示与 Verilog 匹配的开始 结束语句 VIM 可以使用花括号 方括号 但不能使用它的开始 结束 我希望 VIM 突出显示正确的开始到正确的结束 在我看来 最好的选择是使用 matchit 该脚本是 v
  • 如何在 docker exec bash 命令中转义引号

    我正在尝试在 docker 中执行 bash 命令 但我无法弄清楚如何转义表名周围的单引号user mappings在我的指挥下 我尝试过反斜杠 双单引号和双引号单引号 我知道如果我不将命令包装起来我可以绕过它bash c 但我需要它 以便
  • 使用 CA 文件从 Azure Database for MySQL 进行 SSL 连接

    跟随新 MySQL 服务的 Azure 文档 https learn microsoft com en us azure mysql howto configure ssl 看来您可以使用他们的受信任的 CA 证书非常简单地设置 SSL 按
  • Pod 更新后出现许多构建错误

    我的项目中安装了很多 pod 自从我上次更新 Pod 以来 一切都运行良好 上次 pod 更新后 我遇到了 28 个以 无法构建模块 xxx 开头的构建错误 这是我的 Podfile target projectXXX do use fra
  • Node.js 监听 MongoDB 变化

    Node js 有没有办法监听 MongoDB 集合中特定数据的更改 并在发生更改时触发事件 嗯 这是一个老问题 但我也在为同样的事情而苦苦挣扎 我发现了一些花絮帮助我构建了一个解决方案 并且我已将其作为库发布 https github c
  • document.head v. document.getElementsByTagName("head")[0]

    使用有什么区别document head并使用document getElementsByTagName head 0 我运行的测试表明它们都需要大约一毫秒 我也见过 document head document getElementsBy
  • 如何在结构字段上创建可变迭代器

    所以我正在使用 Rust 开发一个小型 NES 模拟器 并且我正在尝试使用我的状态寄存器 寄存器是一个结构体 其中包含一些包含布尔值的字段 标志 寄存器本身是 CPU 结构体的一部分 现在 我想循环这些字段并根据我执行的某些指令设置布尔值
  • 为什么 -std=c++98 标志有时不起作用?

    情况如下 我想创建一个简单的 C 程序 但它必须使用onlyC 98 函数 我在用Ubuntu 20 04 4 LTS 我在用c 作为编译器我使用以下标志进行编译 Wall Werror Wextra std c 98 pedantic e
  • JTabbedPane 自定义选项卡外观

    我想自定义 JTabbedPane 中选项卡的外观 我想从最简单 最朴素的行为开始 无边框 纯色 问题是仍然存在不平整的情况 选项卡的边距略有重叠 您会看到 由于选择了第二个选项卡 因此它被 带到了前台 这是通过轻微的边距重叠来实现的 有没
  • staruml 抽象类?

    有谁知道如何使用 StarUML 创建抽象类 我在文档中找不到任何提及 是否有某种反映抽象类的更一般的概念 从工具箱中选择类并将其添加到画布中 然后转到属性选择 isAbstract 复选框 然后类名显示为斜体
  • C++ timegm 将 DST 转换为未来某个给定时间的某个时区?

    我需要在我的班级中从 UTC 时间准确转换为给定时区的本地时间 无论 DST 是否有效 我的问题是 当我使用struct tm我必须提供 tm isdst 成员 或者将其保留为 1 以自动确定 from mktime 3 linux man