Discussion:
How to set timezone for localtime()
Giuseppe Modugno
2018-03-31 06:16:20 UTC
Permalink
I have the number of seconds since epoch 1970, in UTC. I'd like to convert
it into broken-down time (year, month, day, hours, ...). I live in Italy
and I need the broken-down in *local* time, so taking into account timezone
(+1 hour) *and* daylight savings.

My platform is a Cortex-M3 MCU from NXP. I'm using MCUXpresso IDE to build
my project and I'm using newlib-nano variant.

I looked at the code and it seems there is some instructions in localtime()
that take into account the timezone. However I don't know how to set
Italian timezone on my platform (somewhere I read I can set TZ environment
variable... but I don't have an environment at all).

Any help?
Brian Inglis
2018-03-31 06:45:46 UTC
Permalink
Post by Giuseppe Modugno
I have the number of seconds since epoch 1970, in UTC. I'd like to convert
it into broken-down time (year, month, day, hours, ...). I live in Italy
and I need the broken-down in *local* time, so taking into account timezone
(+1 hour) *and* daylight savings.
My platform is a Cortex-M3 MCU from NXP. I'm using MCUXpresso IDE to build
my project and I'm using newlib-nano variant.
I looked at the code and it seems there is some instructions in localtime()
that take into account the timezone. However I don't know how to set
Italian timezone on my platform (somewhere I read I can set TZ environment
variable... but I don't have an environment at all).
Any help?
Does your platform at least support putenv(3)?
If so, then on a hosted platform with the latest zoneinfo package, you can run:

$ tail -1 /usr/share/zoneinfo/Europe/Rome
CET-1CEST,M3.5.0,M10.5.0/3

which shows the encoded EU rules for that time zone: STD CET == UTC+1 with
opposite POSIX sign, DST CEST == UTC+2 from March last Sunday at 02.00, until
October last Sunday at 03.00.
In your program:

#include <stdlib.h>
putenv("TZ=CET-1CEST,M3.5.0,M10.5.0/3");
#include <time.h>
tzset();
time_t tt = time(&tt);
struct tm *stmp = localtime(&tt);

should give you the correct broken down time if tzset(3) and localtime(3)
support using TZ.
--
Take care. Thanks, Brian Inglis, Calgary, Alberta, Canada
Giuseppe Modugno
2018-04-05 10:44:06 UTC
Permalink
Post by Brian Inglis
Post by Giuseppe Modugno
I have the number of seconds since epoch 1970, in UTC. I'd like to convert
it into broken-down time (year, month, day, hours, ...). I live in Italy
and I need the broken-down in *local* time, so taking into account timezone
(+1 hour) *and* daylight savings.
My platform is a Cortex-M3 MCU from NXP. I'm using MCUXpresso IDE to build
my project and I'm using newlib-nano variant.
I looked at the code and it seems there is some instructions in localtime()
that take into account the timezone. However I don't know how to set
Italian timezone on my platform (somewhere I read I can set TZ environment
variable... but I don't have an environment at all).
Any help?
Does your platform at least support putenv(3)?
$ tail -1 /usr/share/zoneinfo/Europe/Rome
CET-1CEST,M3.5.0,M10.5.0/3
which shows the encoded EU rules for that time zone: STD CET == UTC+1 with
opposite POSIX sign, DST CEST == UTC+2 from March last Sunday at 02.00, until
October last Sunday at 03.00.
#include <stdlib.h>
putenv("TZ=CET-1CEST,M3.5.0,M10.5.0/3");
#include <time.h>
tzset();
time_t tt = time(&tt);
struct tm *stmp = localtime(&tt);
should give you the correct broken down time if tzset(3) and localtime(3)
support using TZ.
Good suggestione, it works well.

Now I have another similar question. I have to convert a struct tm in
UTC to time_t, but I set TZ to Italy timezone. Is there a function that
makes this convertion without checking current timezone configured in TZ?
Brian Inglis
2018-04-05 16:26:33 UTC
Permalink
Post by Brian Inglis
Post by Giuseppe Modugno
I have the number of seconds since epoch 1970, in UTC. I'd like to convert
it into broken-down time (year, month, day, hours, ...). I live in Italy
and I need the broken-down in *local* time, so taking into account timezone
(+1 hour) *and* daylight savings.
My platform is a Cortex-M3 MCU from NXP. I'm using MCUXpresso IDE to build
my project and I'm using newlib-nano variant.
I looked at the code and it seems there is some instructions in localtime()
that take into account the timezone. However I don't know how to set
Italian timezone on my platform (somewhere I read I can set TZ environment
variable... but I don't have an environment at all).
Does your platform at least support putenv(3)?
    $ tail -1 /usr/share/zoneinfo/Europe/Rome
    CET-1CEST,M3.5.0,M10.5.0/3
which shows the encoded EU rules for that time zone: STD CET == UTC+1 with
opposite POSIX sign, DST CEST == UTC+2 from March last Sunday at 02.00, until
October last Sunday at 03.00.
    #include <stdlib.h>
    putenv("TZ=CET-1CEST,M3.5.0,M10.5.0/3");
    #include <time.h>
    tzset();
    time_t tt = time(&tt);
    struct tm *stmp = localtime(&tt);
should give you the correct broken down time if tzset(3) and localtime(3)
support using TZ.
Now I have another similar question. I have to convert a struct tm in UTC to
time_t, but I set TZ to Italy timezone. Is there a function that makes this
convertion without checking current timezone configured in TZ?
As mktime(3) assumes local time, and there are no currently supported context or
locale variants (GNU timegm(3), BSD/tzcode mktime_z(3)), after the previous
code, you should use:

putenv("TZ=UTC0");
tzset();
struct tm stm_utc;
stm_utc.tm_year = year - 1900;
stm_utc.tm_month = month - 1;
stm_utc.tm_mday = day;
stm_utc.tm_hour = hour;
stm_utc.tm_min = min;
stm_utc.tm_sec = sec;
stm_utc.tm_isdst = 0;
time_t tt_utc = mktime(&stm_utc);
--
Take care. Thanks, Brian Inglis, Calgary, Alberta, Canada
Giuseppe Modugno
2018-04-06 07:48:37 UTC
Permalink
Post by Brian Inglis
Now I have another similar question. I have to convert a struct tm in UTC to
time_t, but I set TZ to Italy timezone. Is there a function that makes this
convertion without checking current timezone configured in TZ?
As mktime(3) assumes local time, and there are no currently supported context or
locale variants (GNU timegm(3), BSD/tzcode mktime_z(3)), after the previous
putenv("TZ=UTC0");
tzset();
struct tm stm_utc;
stm_utc.tm_year = year - 1900;
stm_utc.tm_month = month - 1;
stm_utc.tm_mday = day;
stm_utc.tm_hour = hour;
stm_utc.tm_min = min;
stm_utc.tm_sec = sec;
stm_utc.tm_isdst = 0;
time_t tt_utc = mktime(&stm_utc);
As you can read in my previous posts, putenv() calls setenv() that
allocates a new string every time (if the new value is longer than the
old value).
My application needs to call mktime() with "TZ=UTC0" and localtime()
with "TZ=CET..." regularly and I can't call continuously
setenv()/unsetenv(), because of a memory leak (unsetenv() doesn't call
free).

Another unpleasent thing happens with tzset() (that I *need* to call
every time I change "TZ" variable). tzset() allocates and save the
previous value of "TZ" variable. Every time it checks if the value is
different. If yes, it free() and malloc() the new value (and make all
the timezone calculations).
In this case there isn't any memory leak, however I'm indirectly and
continuously calling malloc()/free().

Loading...