I am writing a C application that analyzes data files written by an external program (which I do not control). It stores binary data, one field of which is time in the standard UNIX "era" format (seconds since January 1, 1970, UTC).
Another field is the time zone saved as the offset in seconds from UTC.
Cool, I have everything I need for the date / time string to represent this information in the time zone in which it was written, right? Well ... that doesn't seem to be, and / or I'm not sure how to do it.
I threw things back to a fairly simple test:
#include <stdio.h> #include <time.h> int main(void) { time_t t; struct tm *tm; char buf[BUFSIZ]; int offset = 4980; /* slightly bizarre, just to test this - an hour * and 23 minutes ahead of UTC */ t = time(NULL); tm = localtime(&t); strftime(buf, BUFSIZ, "%FT%T%z", tm); printf("before: %s\n", buf); /* since we're not telling localtime anything different, * compensate here (by subtracting applied offset, and adding * desired one): */ t += offset - tm->tm_gmtoff; tm = localtime(&t); tm->tm_zone = "XYZ"; // not used -- but it was in an earlier version tm->tm_gmtoff = offset; // on macos, I used to also have %+, which referenced tm_zone strftime(buf, BUFSIZ, "%FT%T%z", tm); printf("after: %s\n", buf); return 0; }
When I run this on MacOS X 10.6, I get:
before: 2011-02-23T00:53:04-0800 after: 2011-02-23T10:16:04-0800
What would I expect (and actually get in a Linux box):
before: 2011-02-23T00:53:04-0800 after: 2011-02-23T10:16:04+0123
Do I need to change the TZ environment variable (and maybe call tzset )? There seems to be a way to manipulate data structures and get the right things, but of course this does not work (on MacOS X 10.6, anyway, works fine on Linux).
As a workaround, I suppose I can remove% z from my format string and create this part myself.
Ideally, however, I would like to have either a modification of my struct tm , or some other function call that I can use (e.g. strftime, but with an extra parameter or something else, or maybe an alternative form of localtime, instead ), which would make things different.
Since Linux seems to behave (although even there, the above solution is not entirely ideal, because I'm fudging my time_t value, I'd rather have a parameter that changes how struct tm calculated), this is something that I should to report as an error against macOS?
Alternatively, is there any other set of library procedures that I could name, even if it ultimately requires a third-party (something from the GNU library, I present)? I would rather keep C, although I would consider ObjC or C ++ options.