I must be missing something I'm attempting to get the timezone global variable value which is supposed to be set after TZset is called.
void setTimezone(String timezonestr){
Serial.printf(" Setting Timezone to %s\n",timezonestr.c_str());
setenv("TZ",timezonestr.c_str(),1);
tzset();
Serial.print(timezone);
}
The error that I'm receiving is that
sketch.ino: In function 'void setup()': sketch.ino:75:24: error: expected primary-expression before ')' token
Serial.print(timezone);
Reading the docs I thought this was a global variable that should be set after tzset is called.
Feel free to take a look at the Messy trial and error code...
https://wokwi.com/projects/359035878235429889
After some searching I was able to find:
After calling the tzset() function in a C program, the timezone information is stored in a number of global variables that can be accessed by your program. These global variables are:
extern long timezone: This variable stores the difference in seconds between Coordinated Universal Time (UTC) and the local standard time. extern int daylight: This variable is non-zero if the local timezone is currently in daylight saving time, and zero otherwise. extern char *tzname[]: This is an array of two character strings that store the names of the local standard time and daylight saving time, respectively. To access these global variables in your program, you can simply refer to them by name, just like any other global variable. For example:
Thanks
^
[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
TZenvironment variable, either before your program starts, or from within it by callingsetenvorputenv, followed bytzset.As a comment pointed out, setting the environment like that is questionable on a bare-metal platform like Arduino.
Other than setting the
TZvariable, your only other option for choosing the time zone to use involves the "BSD-inspired"tzallocandlocaltime_rzfunctions, 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, andtzname, 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_timezoneand__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_gmtofffield instruct tm. That is, after callingsee if you can access
tmp->tm_gmtoffalong withtmp->tm_hourandtmp->tm_minand the rest. Thetm_gmtofffield isn't standard, unfortunately, but in my experience most systems support it. Iftm_gmtoffdoesn't work, try_tm_gmtoffand__tm_gmtoff.And, finally, if neither
timezonenortm_gmtoffare available to you, there's one last trick — try this squirrelly-looking code:This takes a
time_ttimestamp (that is, seconds since 1970), converts it to broken-downstruct tmvalues without applying the local time zone offset, then converts it fromstruct tmright back totime_twhile applying the local time zone, meaning that the twotime_tvalues 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_gmtoffand thegmtime/mktimetrick 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. Thetimezonevariable, 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
timezonevariable (at least on this system) seems to use the opposite sign convention.