4

I'm doing some code where I need to known which time zone is active in the system (I'm working on a Linux SO):

  • My first aproach was to check TZ enviroment var,it's empty unless I set it (for instance calling tzset)

  • After that I try extern long timezone (time.h) but this variable is always 0.

  • Finally I calculate the difference of my timezone and UTC+0 but I don't get my real timezone because I don't known if daylight saving apply

I'm pretty sure that there are a easy (and most consistent) way to achieve this. I'm looking for something like "Europe/Paris" or "UTC+2" or something like that

Any help will be appreciated!

unwind
  • 391,730
  • 64
  • 469
  • 606
Joan Esteban
  • 1,006
  • 12
  • 23

3 Answers3

3

As a starting point, I would suggest this:

#include <stdio.h>
#include <stdlib.h>
#include <time.h>

int main(void)
{
  char str[64];
  time_t timer;
  struct tm * ptm;
  timer = time(NULL);
  ptm = localtime(&timer); 
  strftime(str, sizeof(str), "%Z", ptm);
  printf("TZ: %s\n", str);
  return(0);
}
Djee
  • 429
  • 3
  • 9
  • 1
    I don't think `sizeof(str-1)` does what you think it does. – unwind Nov 10 '16 at 12:24
  • It's almost what I wanted!, I get 'CET' for Paris , EST for NY and CST for Costa Rica. – Joan Esteban Nov 10 '16 at 13:58
  • 1
    The minus 1 is not needed. `strftime(str, sizeof str , "%Z", ptm);` is OK. Better to check its return value. – chux - Reinstate Monica Nov 10 '16 at 15:50
  • @JoanEsteban How is this answer not what you wanted? If the result is `"CET"`, _that_ is the name of the time zone as code understands it. The name is _not_ `"Europe/Paris"`. On another system, code may return `"Europe/Paris"` as that is the name on that system. How did you set your system to "Paris"? Perhaps that is the short-coming? – chux - Reinstate Monica Nov 10 '16 at 15:52
  • 1
    @Joan. If you want to go further, you need to play with the so called Olson database (after Arthur David Olson), located in /usr/share/zoneinfo. Your /etc/localtime should be a symlink to the time zone in the form Asia/Tokyo for example in the Olson database. With a few system calls, you should trace this easily. This does not apply on limited embedded Linux systems, where TZ is still used in a condensed form, called POSIX TZ string (like EST5EDT,M03.2.0,M11.1.0) – Djee Nov 13 '16 at 21:41
1

Option 1)

timezone and tzname could be available after call tzset():

cout << "Before tzset: " << timezone << " " << tzname[0] << " " << tzname[1] << endl;
tzset();
cout << "After tzset: " << timezone << " " << tzname[0] << " " << tzname[1] << endl;

outputs (today, in Europe):

Before tzset: 0 GMT GMT
After tzset: -3600 CET CEST

Option 2) Some versions of "struct tm" (GNU, BSD, ...) contains fields "tm_zone" and "tm_isdst":

time_t timer;
struct tm *ptm;

timer = time(NULL);
ptm = localtime( &timer );
cout << ptm->tm_zone <<  " " << ptm->tm_isdst << endl;

timer -= 60*24*3600; // 60 days ago
ptm = localtime( &timer );
cout << ptm->tm_zone <<  " " << ptm->tm_isdst << endl;

outputs:

CET 0
CEST 1
pasaba por aqui
  • 3,446
  • 16
  • 40
0

The date +%Z command shows the current timezone, but what you actually want is to set it correctly. First remove the current timezone file:

# rm -f /etc/localtime

Then set the correct one for your timezone:

# ln -s /usr/share/zoneinfo/<your-time-zone-here> /etc/localtime

Do an ls /usr/share/zoneinfo/ to see the available timezones. For me it's /usr/share/zoneinfo/Europe/Amsterdam.

Then verify using the abovementioned date command.

sebvieira
  • 56
  • 6
  • That is not what I'm asking for, I already have done that to check my code with severals Timezones, but I want to get my timezone from C program (and, of course, I can't read /etc/localtime link because It's not always a link) – Joan Esteban Nov 10 '16 at 13:47