3

I wrote small program to show local time relative to GMT (or UTC):

struct tm l;    
time_t stamp = 1534435540;

// No TZ set
printf("TZ=%s\n",getenv("TZ"));
gmtime_r(&stamp, &l);
printf("UTC: %0u:%0u:%0u - %0u.%0u.%0u\n",l.tm_hour,l.tm_min,l.tm_sec,l.tm_mday,l.tm_mon+1,l.tm_year+1900);
localtime_r(&stamp, &l);
printf("Local: %0u:%0u:%0u - %0u.%0u.%0u\n\n",l.tm_hour,l.tm_min,l.tm_sec,l.tm_mday,l.tm_mon+1,l.tm_year+1900);

// Positive TZ: east to Greenwich (e.g. China)
setenv("TZ", "UTC+6:00", 1);    
printf("TZ=%s\n",getenv("TZ"));     
tzset();    
gmtime_r(&stamp, &l);
printf("UTC: %0u:%0u:%0u - %0u.%0u.%0u\n",l.tm_hour,l.tm_min,l.tm_sec,l.tm_mday,l.tm_mon+1,l.tm_year+1900);
localtime_r(&stamp, &l);
printf("Local: %0u:%0u:%0u - %0u.%0u.%0u\n\n",l.tm_hour,l.tm_min,l.tm_sec,l.tm_mday,l.tm_mon+1,l.tm_year+1900);

// Negative TZ: west to Greenwich (e.g. US/Canada)
setenv("TZ", "UTC-6:00", 1);    
printf("TZ=%s\n",getenv("TZ"));
tzset();    
gmtime_r(&stamp, &l);
printf("UTC: %0u:%0u:%0u - %0u.%0u.%0u\n",l.tm_hour,l.tm_min,l.tm_sec,l.tm_mday,l.tm_mon+1,l.tm_year+1900);
localtime_r(&stamp, &l);
printf("Local: %0u:%0u:%0u - %0u.%0u.%0u\n\n",l.tm_hour,l.tm_min,l.tm_sec,l.tm_mday,l.tm_mon+1,l.tm_year+1900);

Output of this program is the following:

TZ=<null>
UTC: 16:5:40 - 16.8.2018
Local: 16:5:40 - 16.8.2018

TZ=UTC+6:00
UTC: 16:5:40 - 16.8.2018
Local: 10:5:40 - 16.8.2018

TZ=UTC-6:00
UTC: 16:5:40 - 16.8.2018
Local: 22:5:40 - 16.8.2018

It looks strange, isnt'it? According to Wiki:

For example, if the time being described is one hour ahead of UTC (such as the time in Berlin during the winter), the zone designator would be "+01:00", "+0100", or simply "+01"

So GMT+6 means that I add 6 hours to GMT to get local time.

But this article about TZ variable says the opposite:

This is positive if the local time zone is west of the Prime Meridian and negative if it is east.

Do I miss something or linux behaves opposite to standard?

x_arrange
  • 317
  • 2
  • 12
  • 5
    [Possible duplicate](https://unix.stackexchange.com/questions/104088/why-does-tz-utc-8-produce-dates-that-are-utc8) – n. m. could be an AI Aug 17 '18 at 10:36
  • 3
    Blame the Unix creators in America. They didn't like their timezone offsets being negative. – Ian Abbott Aug 17 '18 at 10:45
  • @IanAbbott Could also create the UNIX creators for using an international concept of time, like GMT, rather than setting systems time to local time like [DOS](https://www.cl.cam.ac.uk/~mgk25/mswish/ut-rtc.html). – chux - Reinstate Monica Aug 17 '18 at 13:38
  • @chux I suppose, but what sort of idiot would make system time subject to DST changes? Also, a UNIX system is multi-user, and the users could be in different time-zones. – Ian Abbott Aug 17 '18 at 17:15
  • 1
    It's even slightly more confusing these days, as some of the Olsen style timezone identifiers have numeric abbreviations, and the sign of the numeric abbreviation matches ISO 8601, not the sign of the POSIX TZ offsets. – Ian Abbott Aug 17 '18 at 17:51

1 Answers1

5

Unix creators used the opposite sign convention in the TZ environment variable compared to how time zones are described elsewhere, including in ISO 8601.

That Unix quirk was standardized in POSIX.1, and that's the standard Linux follows.

So yes, if you want to set timezone to UTC-04:00 (say, EDT, or Eastern Daylight Time for those somewhere in eastern Canada or US), you can set TZ to UTC+04:00.

Nominal Animal
  • 38,216
  • 5
  • 59
  • 86