我需要在课堂上准确地将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。)AM,因为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美国/芝加哥时区生效,从而不将额外的60分钟添加到UTC时间,并在同一天,例如在南半球时区美洲/圣保罗,其有效期至2015年2月16日,对于这个时间戳,它应该增加60分钟,以获得给定日期的正确本地时间。
当您通过IANA标识符(例如“America/Chicago”
)引用时区时,它已经包含了所有DST信息和时区的完整历史记录。至少在IANA时区数据库的原始源数据中是这样的。
你(在评论中)提到了Boost。虽然Boost确实支持这些类型的标识符,但它错误地假设它们在时间上是永久固定的。这不是真的,因为世界上的时区一直在改变它们的偏移量和DST规则。考虑到美国在2007年改变了其DST规则,而俄罗斯在今年晚些时候(2014年10月)正在显着改变其时区。如果您查看Boost时区数据文件,您会发现它的格式删除了所有历史记录,只是将每个标识符映射到一组规则。出于这个原因,我建议您不要使用Boost进行本地时区转换。
相反,考虑使用ICU。其中包括时区转换功能,并使用IANA时区数据库的完整副本。您可以在这里阅读更多内容,并在这里查看示例代码。我对C语言不是特别熟练,但似乎可以使用ICU的日历
类将UTC时间投影到特定时区的本地时间。
另一种选择是使用GNU C库中内置的时区函数。它还使用完整的时区数据库。本网站上有一个使用IANA/Olson标识符转换UTC到当地时间的简单示例,我还发布了以下内容:
/*
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.
}
问题内容: 我有一个字符串类型就像一个计时:和是。 如何使用Java 8 datetime API将此时间信息转换为与UTC时间相对应的时间? 还需要考虑DST的东西。 问题答案: 您正在Java8 中寻找类-带有时区的完整日期时间和与UTC /格林威治标准时间的偏移量。就设计而言,此类应主要视为a 和a 的组合。的是一个至关重要的,但次要的,一条信息,用于确保所述类表示瞬间,特别是在夏令重叠。
问题内容: 我需要预测下一个至少2个时区转换何时将用于特定时区。 Java 8特别提供了新的API 。看起来确实正是我需要的东西,但是它没有列出“澳大利亚/悉尼” 2010年以后的任何东西。 确定下两个时区转换的日期/时间/偏移量的最可靠方法是什么? 问题答案: 该方法不会列出所有过渡,直到无限远(显然)为止。这将获得以下两个过渡: 输出: 下一次转换时间:2016-10-02T03:00 + 1
我将要求用户输入一个特定时间:上午10点、下午12点30分、下午2点47分、上午1点09分、下午5点等。我将使用获取用户的输入。 如何将该解析/转换为对象?Java中是否有任何内置函数允许我这样做?
我想将时间戳转换为。 这是我到目前为止已经实现的,但是它给了我错误的月份 任何帮助将不胜感激。
问题内容: 我想将此GMT时间戳转换为GMT + 13: 我已经尝试过约100种不同的DateFormat,TimeZone,Date,GregorianCalendar等组合,以尝试执行此非常基本的任务。 这段代码可以满足我在当前时间的需求: 但是我想要的是设置时间而不是使用当前时间。 我发现任何时候我都尝试这样设置时间: 使用本地计算机的TimeZone。这是为什么?我知道,当“ new Da