2

I am working on an Linux based router. I am working on a C application. I want to get current time in my application continuously.

The problem is, it gives me time according to the application launch timezone although I have changed timezone after the application started. The timezone of the system has been changed. The date command on Linux terminal shows different timezone and date/time.

time_t currTm;
struct tm *loctime;
char udrTime[50];
while (1)
{
    currTm = time(NULL);
    loctime = localtime(&currTm);
    strftime(udrTime, sizeof(udrTime), "%Y-%m-%d %H:%M:%S", loctime);
    printf("udr_time = %s\n", udrTime);
    usleep(10000);
}  

I expect output according to timezone changes.

jww
  • 97,681
  • 90
  • 411
  • 885
Nayan
  • 151
  • 9
  • 1
    Is the `TZ` environment variable set on your system? If yes, try unsetting it before launching your C application. – nwellnhof Jun 21 '19 at 13:19
  • 1
    I don't believe this is possible in standard C. You might have to rely on OS specific API. – Irelia Jun 21 '19 at 13:21
  • Maybe [`tzset(3)`](https://linux.die.net/man/3/tzset) in Linux? [`tzset`](https://pubs.opengroup.org/onlinepubs/9699919799/) is a standard Posix function. Also see questions like [How to get the current time zone?](https://stackoverflow.com/q/2136970/608639) and [What are the disadvantages to using ctime's tzset?](https://stackoverflow.com/q/8900844/608639) – jww Jun 21 '19 at 14:33
  • @jww No need to call `tzset`: _This function is automatically called by the other time conversion functions that depend on the timezone._ – Maxim Egorushkin Jun 21 '19 at 14:51
  • _I want to get current time in my application continuously._ - what is the intended use of the time? Do you print it or embed the string somewhere or just measure time intervals? – Maxim Egorushkin Jun 21 '19 at 15:24
  • @Maxim - Is it called once, or is it called each time a timezone is needed? It seems there's some stale data somewhere. It also seems like one should not need to change the environment to make things work as expected in a C program. – jww Jun 21 '19 at 16:58
  • @jww You may like to come up with a use case when that call is needed. I would look it up in glibc sources. Your recommendation should have a basis. – Maxim Egorushkin Jun 21 '19 at 17:01
  • @Maxim - I believe recommendation does have a basis. According to the [The Open Group Base Specifications](https://pubs.opengroup.org/onlinepubs/9699919799/functions/tzset.html), the purpose of `tzset` is to *"set timezone conversion information"*. Perhaps I am missing something? – jww Jun 21 '19 at 17:05
  • 1
    @jww You missed _This function is automatically called by the other time conversion functions that depend on the timezone._ `tzset` updates `tzname`, `timezone` and `daylight` global variables, which aren't normally used directly. The condition when it is called is `tzname != getenv("TZ")`. – Maxim Egorushkin Jun 21 '19 at 17:09
  • 1
    Thanks @Maxim. I can't find that text in in the Posix specification. I do see it appears `tzset` is not thread safe, which looks a little unusual to me. – jww Jun 21 '19 at 17:54
  • @jww For Linux you may like to consult Linux documentation: http://man7.org/linux/man-pages/man3/tzset.3.html – Maxim Egorushkin Jun 24 '19 at 09:37
  • Thanks @Maxim. Does that apply to other runtimes as well, like Musl? Or is it just a glibc thing? – jww Jun 24 '19 at 20:48

1 Answers1

3

To change the timezone from within the application just set TZ environment variable, nothing else is necessary:

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

void print_time(time_t t) {
    char buf[256];
    strftime(buf, sizeof buf, "%H:%M:%S", localtime(&t));
    printf("%s %s\n", getenv("TZ"), buf);
}

int main() {
    time_t t = time(NULL);

    setenv("TZ", "Europe/London", 1);
    print_time(t);

    setenv("TZ", "America/New_York", 1);
    print_time(t);

    return 0;
}

Outputs:

Europe/London 15:48:58
America/New_York 10:48:58
Maxim Egorushkin
  • 131,725
  • 17
  • 180
  • 271