Reputation: 13
I use the following codes to caculate timezone. When I set the timezone to Asia/Singapore, I think I should get 28800 which 28800/3600=8, it should be GMT +8, but it returns 27000/3600=7.5, Am I wrong?
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);
Upvotes: 1
Views: 426
Reputation: 753525
According to zdump -v Asia/Singapore
on a Mac, the time zone offset from UTC for Singapore between August 1965 and January 1982 was 7h 30m east of UTC:
$ 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
$
Consequently, the result you're getting is the correct offset from UTC in Singapore for 1970-01-01.
The current timezone of Singapore is GMT8. What I should do to fix this problem?
The current time zone offset of Singapore is UTC+8 (GMT+8), but historically (specifically, in 1970), that was not the case. You will have to devise a time nearer to the current time when the time zone offset in the database is correct. That seems to mean a time since 1982-01-01 00:30:00 +08:00. So, maybe you should use 2000-01-01 00:00:00? You'll need the number of seconds in the 30 years since 1970-01-01 00:00:00 to get the answer right, and you'll use that in place of the 0
in 0 - mktime(&tSysTime)
. I believe the relevant number is 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
That's a deep-seated mystery. No, it isn't. I have a pair of programs, strptime
and timestamp
that helped (plus a casual use of bc
).
I live in the 'US/Pacific' (officially, America/Los_Angeles, but I don't like that name much — I live a lot closer to San Francisco) time zone (UTC-08:00 in the winter; UTC-07:00 during the summer).
$ 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
$
If you spend the time working out how, you can probably do that with GNU date
.
Upvotes: 4