[This is a generic, C-heavy answer, not necessarily specific to a particular platform, let alone Arduino.]
I guess there are two questions here: how can you set the timezone, and how can you confirm what it's set to?
It's true that setting the time zone — like, sadly, many aspects of date and time handling in C — is pretty rinky-dink. The recommended way is indeed to set the TZ
environment variable, either before your program starts, or from within it by calling setenv
or putenv
, followed by tzset
.
As a comment pointed out, setting the environment like that is questionable on a bare-metal platform like Arduino.
Other than setting the TZ
variable, your only other option for choosing the time zone to use involves the "BSD-inspired" tzalloc
and localtime_rz
functions, as described in this answer. But those functions are, also sadly, not at all widely available.
And then, once you've set the time zone (if you set it), how do you find out what it is?
You found some text documenting some global variables timezone
, daylight
, and tzname
, but those are very, very old, and (IMO) totally obsolete. (But I might be wrong.) In a comment I suggested that "they may still exist in some traditional Unix environments" but that "I'd be surprised if they exist anywhere else". Well, I'm surprised: they exist right here on my Mac! And on Linux, too. But I'm not surprised if they don't exist on Arduino.
If you're not having any luck accessing a global variable named timezone
, it would be worth trying _timezone
and __timezone
; there's a (slight) chance one of those might work.
But the much better way of discovering UTC offsets, which I recommend, is to use the semistandard tm_gmtoff
field in struct tm
. That is, after calling
struct tm *tmp = localtime(&t);
see if you can access tmp->tm_gmtoff
along with tmp->tm_hour
and tmp->tm_min
and the rest. The tm_gmtoff
field isn't standard, unfortunately, but in my experience most systems support it. If tm_gmtoff
doesn't work, try _tm_gmtoff
and __tm_gmtoff
.
And, finally, if neither timezone
nor tm_gmtoff
are available to you, there's one last trick — try this squirrelly-looking code:
struct tm *tm2 = gmtime(&t);
tm2->tm_isdst = -1;
time_t t2 = mktime(tm2);
printf("UTC offset: %ld\n", t - t2);
This takes a time_t
timestamp (that is, seconds since 1970), converts it to broken-down struct tm
values without applying the local time zone offset, then converts it from struct tm
right back to time_t
while applying the local time zone, meaning that the two time_t
values should differ by precisely the local time zone offset. Try that, it almost always works. (Even though it is, as I said, squirrelly, and not strictly portable.)
The remaining issue here is what we even mean by "the current time zone". Both tm_gmtoff
and the gmtime
/mktime
trick I just showed will give you the UTC offset as of the time value you're converting, which means you'll get an offset including Daylight Saving Time adjustments. For example, when I run the code just now, those two methods give me an offset of 14400, or 4 hours, because I'm in the U.S. Eastern time zone, and DST just kicked in here last weekend. The timezone
variable, on the other hand, contains 18000, or 5 hours, because Eastern time is nominally UTC-5 (except it's 5 hours behind UTC for much less than half the year, due to DST political follies).
Also, the timezone
variable (at least on this system) seems to use the opposite sign convention.