-3

I'm trying to print in the console the current time in my local timezone (-0600), then printing the time at the +0100 timezone. Currently I'm using gmtime, and adding 1 to the tm_hour section.

However when using strftime, it still prints the: "... +0000".

How can I print it properly? How can I change my effective time zone, for instance?

Yu Hao
  • 119,891
  • 44
  • 235
  • 294
Memo
  • 1
  • 2

1 Answers1

1

On macOS Sierra 10.12.2 with GCC 6.3.0, the following code works:

#include "posixver.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <unistd.h>

#ifndef lint

extern const char jlss_id_settz_c[];
const char jlss_id_settz_c[] = "@(#)$Id: settz.c,v 1.2 2017/01/23 07:06:21 jleffler Exp $";
#endif

static void time_convert(time_t t0, char const *tz_value)
{
    char old_tz[64] = "-none-";
    char *tz = getenv("TZ");
    if (tz != 0)
        strcpy(old_tz, tz);
    setenv("TZ", tz_value, 1);
    tzset();
    char new_tz[64];
    strcpy(new_tz, getenv("TZ"));
    char buffer[64];
    struct tm *lt = localtime(&t0);
    strftime(buffer, sizeof(buffer), "%Y-%m-%d %H:%M:%S", lt);
    if (strcmp(old_tz, "-none-") == 0)
        unsetenv("TZ");
    else
        setenv("TZ", old_tz, 1);
    tzset();
    printf("%ld = %s (TZ=%s)\n", (long)t0, buffer, new_tz);
}

int main(void)
{
    time_t t0 = time(0);
    char *tz = getenv("TZ");
    if (tz != 0)
        time_convert(t0, tz);
    time_convert(t0, "UTC0");
    time_convert(t0, "IST-5:30");
    time_convert(t0, "EST5");
    time_convert(t0, "EST5EDT");
    time_convert(t0, "PST8");
    time_convert(t0, "PST8PDT");
}

By default, TZ is not set in the environment — those ungainly tests for getenv("TZ") returning NULL are necessary to handle that. When run, the output is:

$ ./settz
1485155290 = 2017-01-23 07:08:10 (TZ=UTC0)
1485155290 = 2017-01-23 12:38:10 (TZ=IST-5:30)
1485155290 = 2017-01-23 02:08:10 (TZ=EST5)
1485155290 = 2017-01-23 02:08:10 (TZ=EST5EDT)
1485155290 = 2017-01-22 23:08:10 (TZ=PST8)
1485155290 = 2017-01-22 23:08:10 (TZ=PST8PDT)
$

With the environment set so TZ=US/Alaska, the output is:

$ TZ=US/Alaska ./settz
1485155395 = 2017-01-22 22:09:55 (TZ=US/Alaska)
1485155395 = 2017-01-23 07:09:55 (TZ=UTC0)
1485155395 = 2017-01-23 12:39:55 (TZ=IST-5:30)
1485155395 = 2017-01-23 02:09:55 (TZ=EST5)
1485155395 = 2017-01-23 02:09:55 (TZ=EST5EDT)
1485155395 = 2017-01-22 23:09:55 (TZ=PST8)
1485155395 = 2017-01-22 23:09:55 (TZ=PST8PDT)
$

This is ugly as a technique; it is also not fast. However, on some platforms, it does in fact work.

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
  • Concerning `char new_tz[64];`, I'd expect this code to use `char new_tz[42+1];` [Respected reference](http://stackoverflow.com/questions/3477347/php-tz-setting-length#comment3629648_3477491), but [don't panic](https://en.wikipedia.org/wiki/Phrases_from_The_Hitchhiker's_Guide_to_the_Galaxy). ;-) – chux - Reinstate Monica Jan 23 '17 at 16:51
  • @chux: Oh, him? Yeah, he sometimes knows of what he speaks. That question was about minimum length, and 42 was advocating (tongue in cheek) for 'more than 30'. And, of course, 42 is the answer to question of life, the universe, and everything. Using 64 gives more leeway — I'd rather be safe than sorry, except that the code should ensure that the string being copied isn't too long — but doesn't. OTOH, it was only demo code I created back in 2012 (and that code crashed when I checked it, because of no TZ environment variable — hence the update yesterday). – Jonathan Leffler Jan 23 '17 at 17:03
  • This isn't safe to do in the case of multiple threads, because `setenv` isn't safe to use if there are multiple threads, especially if another thread might read the environment. – Thayne Nov 03 '21 at 06:53