我需要在我的班级中从 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 分钟以获得给定日期的正确当地时间。