我使用以下代码来计算时区。当我将时区设置为亚洲/新加坡时,我认为我应该得到28800,其中28800/3600 = 8,它应该是GMT +8,但它返回27000/3600 = 7.5,我错了吗?
struct tm tSysTime;
long int secs;
memset(&tSysTime,0,sizeof(tSysTime));
tSysTime.tm_year = 70;
tSysTime.tm_mon = 0;
tSysTime.tm_mday = 1;
tSysTime.tm_hour = 0;
tSysTime.tm_min = 0;
tSysTime.tm_sec = 0;
secs = 0-mktime(&tSysTime);
printf("[main] time zone %ld\n",secs);
答案 0 :(得分:4)
根据Mac上的zdump -v Asia/Singapore
,从1965年8月到1982年1月,新加坡UTC的时区偏离UTC时间以东7小时30分:
$ zdump -v Asia/Singapore
Asia/Singapore Fri Dec 13 20:45:52 1901 UTC = Sat Dec 14 03:41:17 1901 SMT isdst=0
Asia/Singapore Sat Dec 14 20:45:52 1901 UTC = Sun Dec 15 03:41:17 1901 SMT isdst=0
Asia/Singapore Wed May 31 17:04:34 1905 UTC = Wed May 31 23:59:59 1905 SMT isdst=0
Asia/Singapore Wed May 31 17:04:35 1905 UTC = Thu Jun 1 00:04:35 1905 MALT isdst=0
Asia/Singapore Sat Dec 31 16:59:59 1932 UTC = Sat Dec 31 23:59:59 1932 MALT isdst=0
Asia/Singapore Sat Dec 31 17:00:00 1932 UTC = Sun Jan 1 00:20:00 1933 MALST isdst=1
Asia/Singapore Tue Dec 31 16:39:59 1935 UTC = Tue Dec 31 23:59:59 1935 MALST isdst=1
Asia/Singapore Tue Dec 31 16:40:00 1935 UTC = Wed Jan 1 00:00:00 1936 MALT isdst=0
Asia/Singapore Sun Aug 31 16:39:59 1941 UTC = Sun Aug 31 23:59:59 1941 MALT isdst=0
Asia/Singapore Sun Aug 31 16:40:00 1941 UTC = Mon Sep 1 00:10:00 1941 MALT isdst=0
Asia/Singapore Sun Feb 15 16:29:59 1942 UTC = Sun Feb 15 23:59:59 1942 MALT isdst=0
Asia/Singapore Sun Feb 15 16:30:00 1942 UTC = Mon Feb 16 01:30:00 1942 JST isdst=0
Asia/Singapore Tue Sep 11 14:59:59 1945 UTC = Tue Sep 11 23:59:59 1945 JST isdst=0
Asia/Singapore Tue Sep 11 15:00:00 1945 UTC = Tue Sep 11 22:30:00 1945 MALT isdst=0
Asia/Singapore Sun Aug 8 16:29:59 1965 UTC = Sun Aug 8 23:59:59 1965 MALT isdst=0
Asia/Singapore Sun Aug 8 16:30:00 1965 UTC = Mon Aug 9 00:00:00 1965 SGT isdst=0
Asia/Singapore Thu Dec 31 16:29:59 1981 UTC = Thu Dec 31 23:59:59 1981 SGT isdst=0
Asia/Singapore Thu Dec 31 16:30:00 1981 UTC = Fri Jan 1 00:30:00 1982 SGT isdst=0
Asia/Singapore Mon Jan 18 03:14:07 2038 UTC = Mon Jan 18 11:14:07 2038 SGT isdst=0
Asia/Singapore Tue Jan 19 03:14:07 2038 UTC = Tue Jan 19 11:14:07 2038 SGT isdst=0
$
因此,您获得的结果是1970-01-01新加坡UTC的正确偏移。
新加坡目前的时区是GMT8。我该怎么做才能解决这个问题?
新加坡目前的时区偏移是UTC + 8(GMT + 8),但历史上(特别是1970年),情况并非如此。当数据库中的时区偏移正确时,您将不得不设计一个更接近当前时间的时间。这似乎意味着自1982-01-01 00:30:00 +08:00以来的一段时间。那么,也许你应该使用2000-01-01 00:00:00?您需要自1970-01-01 00:00:00以来30年内的秒数才能得到正确的答案,并且您将使用它来代替0
中的0 - mktime(&tSysTime)
。我认为相关的数字是946684800
。
#include <stdio.h>
#include <string.h>
#include <time.h>
int main(void)
{
struct tm tSysTime;
long int secs;
memset(&tSysTime,0,sizeof(tSysTime));
tSysTime.tm_year = 100;
tSysTime.tm_mon = 0;
tSysTime.tm_mday = 1;
tSysTime.tm_hour = 0;
tSysTime.tm_min = 0;
tSysTime.tm_sec = 0;
secs = 946684800 - mktime(&tSysTime);
printf("[main] time zone %ld\n",secs);
return 0;
}
$ TZ=Asia/Singapore tzoff
[main] time zone 28800
$ TZ=US/Pacific tzoff
[main] time zone -28800
$ TZ=UTC0 tzoff
[main] time zone 0
$
946684800
这是一个根深蒂固的谜团。不,不是。我有一对帮助的strptime
和timestamp
程序(偶尔使用bc
)。
我住在'美国/太平洋'(官方,美国/洛杉矶,但我不喜欢这个名字 - 我住的地方离旧金山很近)时区(冬天的UTC-08:00;夏季的UTC-07:00。
$ strptime '2000-01-01 00:00:00'
946713600 = 2000-01-01 00:00:00
$ timestamp 946713600
946713600 = Sat Jan 01 00:00:00 2000
$ timestamp -Z 946713600
946713600 = Sat Jan 01 00:00:00 2000 -08:00
$ bc <<< '946713600 - 8 * 3600'
946684800
$ timestamp -Z 946684800
946684800 = Fri Dec 31 16:00:00 1999 -08:00
$ TZ=UTC0 timestamp -Z 946684800
946684800 = Sat Jan 01 00:00:00 2000 +00:00
$
如果你花时间研究方法,你可以用GNU date
做到这一点。