我正在寻找一些我认为非常简单的东西 – 给定特定时区的本地Unix时间(指定为string,例如“America / New_York” – 注意这不是我的本地时间),获取相应的时间值在GMT。 也就是说
time_t get_gmt_time(time_t local_time,const char* time_zone);
就像听起来那么简单,我能find的最接近的是来自timegm手册页的以下代码片段:
#include <time.h> #include <stdlib.h> time_t my_timegm(struct tm *tm) { time_t ret; char *tz; tz = getenv("TZ"); setenv("TZ","",1); tzset(); ret = mktime(tm); if (tz) setenv("TZ",tz,1); else unsetenv("TZ"); tzset(); return ret; }
如何在Windows上优雅地打印Perl中的%z(timezone)格式?
Windows中的历史夏令时
使用C#在远程计算机上设置date,时间和时区
如何在Windows(非Java)应用程序中使用Java时区ID?
在MSYS中更改时区
更改tomcat的时区
在服务器上设置哪个时区:Etc / UTC或者Etc / Universal?
任何人都知道翻译时区描述的来源?
Java时区已经搞乱了
守护进程中的DST更改处理(* NIX)
如果您尝试以下操作:
#include <stdio.h> #include <time.h> /* defines 'extern long timezone' */ int main(int argc,char **argv) { time_t t,lt,gt; struct tm tm; t = time(NULL); lt = mktime(localtime(&t)); gt = mktime(gmtime(&t)); printf( "(t = time(NULL)) == %x,n" "mktime(localtime(&t)) == %x,n" "mktime(gmtime(&t)) == %xn" "difftime(...) == %fn" "timezone == %dn",t,gt,difftime(gt,lt),timezone); return 0; }
你会注意到时区转换确保:
mktime(localtime(t)) == t和
mktime(gmtime(t)) == t + timezone ,
因此:
difftime(mktime(gmtime(t)),mktime(localtime(t))) == timezone
(后者是由tzset()或任何时区转换函数的调用初始化的全局变量)。
以上示例输出:
$ TZ = GMT ./xx
(t = time(NULL))== 4dd13bac,
mktime(localtime(&t))== 4dd13bac,
mktime(gmtime(&t))== 4dd13bac
difftime(...)== 0.000000
时区== 0
$ TZ = EST ./xx
(t = time(NULL))== 4dd13baf,
mktime(localtime(&t))== 4dd13baf,
mktime(gmtime(&t))== 4dd181ff
difftime(...)== 18000.000000
时区== 18000
$ TZ = CET ./xx
(t = time(NULL))== 4dd13bb2,
mktime(localtime(&t))== 4dd13bb2,
mktime(gmtime(&t))== 4dd12da2
difftime(...)== -3600.000000
时区== -3600
从这个意义上说,你试图“向后做” – time_t在UN * X中被视为绝对的 ,即总是相对于“EPOCH”(1970年1月1日0:00 UTC)。
UTC和当前时区(最后一个tzset()调用)之间的区别总是在external long timezone全局中。
这并没有摆脱环境操纵的丑陋,但你可以节省自己通过mktime()的努力。
从tzfile(5),它将/ usr / share / zoneinfo(在我的系统上)中的文件记录在可怕的细节中:
看来,时区在内部使用tzfile,但glibc拒绝暴露给用户空间。 这很可能是因为标准化的功能更加有用和便携,而且实际上由glibc记录。
再一次,这可能不是你正在寻找的(即一个API),但信息是在那里,你可以解析它,而不是太痛苦。
我真的认为有些事情是滑稽的,但似乎被误解了。 我知道你可能正在寻找直接的C代码,但这里是我得到的最好的:
我知道Python通过tzinfo类有一些时区的概念 – 你可以在日期时间文档中阅读它。 你可以看一下模块的源代码(在压缩包里 ,它在modulees / datetime.c中) – 它看起来有一些文档,所以也许你可以从中得到一些东西。
与Python的答案类似,我可以告诉你R做了什么:
R> Now <- Sys.time() # get current time R> format(Now) # format under local TZ [1] "2009-08-03 18:55:57" R> format(Now,tz="Europe/London") # format under explicit TZ [1] "2009-08-04 00:55:57" R> format(Now,tz="America/Chicago") # format under explicit TZ [1] "2009-08-03 18:55:57" R>
但R使用扩展通常struct tm的内部表示法—请参阅R-2.9.1 / src / main / datetime.c。
不过,这是一个多毛的话题,如果它是标准库,那将会很好。 因为这不是最好的选择是使用Boost Date_Time(例子)
gmtime,localtime及其变体的问题是对TZ环境变量的依赖。 时间函数首先调用tzset(void),它读取TZ以确定偏移DST等。如果在用户环境中未设置TZ,(g)libc使用系统时区。 所以如果你在欧洲/巴黎有一个本地struct tm,并且你的机器或者环境被设置为'America / Denver',那么当你转换成GMT时将会应用错误的偏移量。 所有的时间函数调用tzset(void)读取TZ来设置char * tzname [2],long timezone(以GMT为单位的秒数)和int daylight(DST的布尔值)。 直接设置这些不会有什么影响,因为tzset()会在下一次调用localtime时覆盖它们。
在原来的问题中,我面临着与'igor'相同的问题,而setenv的工作似乎是有问题的(re-entran?)。 我决定进一步查看是否可以将tzset(void)修改为tzset(char *)来显式设置上述变量。 那当然,这只是一个坏主意……但是在探究glibc的来源和IANA TZ数据库来源时,我得出的结论是setenv方法并不是那么糟糕。
首先,setenv只修改进程全局'char ** environ'(而不是调用shell,所以'真实'TZ不受影响)。 其次,glibc实际上对setenv进行了锁定。 缺点是setenv / tzset调用不是原子的,所以在原始线程调用tzset之前,另一个线程可能会写入TZ。 但是一个使用线程的良好实现的应用程序应该注意这一点。
如果POSIX定义了tzset在广泛的IANA TZ数据库中查找字符*(并用NULL来表示'使用用户或系统TZ /'),那么这将是很酷的,但是如果失败了,setenv似乎是可以的。
为什么不能使用gmtime_r() ? 以下工作对我来说很好:
int main() { time_t t_gmt,t_local=time(NULL); struct tm tm_gmt; gmtime_r(&t_local,&tm_gmt); t_gmt = mktime(&tm_gmt); printf("Time Now is: %s",ctime(&t_local)); printf("Time in GMT is: %s",ctime(&t_gmt)); return 0; }
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 [email protected] 举报,一经查实,本站将立刻删除。