mktime(3)would honor the time offset indicated by tm_gmtoff when converting to a time_t representation.
mktime(3)always assumes the "current timezone" defined by the executing environment. Since ISO C and POSIX define the semantics for
mktime(3)but neither defines a tm_gmtoff member for the tm structure, not surprisingly
mktime(3)does not honor it.
So, lets say you have a struct tm, complete with correctly-populated tm_gmtoff field: how do you convert it to a time_t representation?
Many modern C libraries (including glibc and FreeBSD's libc) include a
timegm(3)function. No, this function doesn't honor tm_gmtoff either. Instead,
gmtime(3)converts the struct tm to a time_t just like
mktime(3), but ignores the timezone of the executing environment and always assumes GMT as the timezone.
However, if your libc implements both tm_gmtoff and
timegm(3)you are in luck. You just need to use
timegm(3)to get the time_t representing the time in GMT and then subtract the offset stored in tm_gmtoff. The tricky part is that calling
timegm(3)will modify the struct tm, clearing the tm_gmtoff field to zero (at least it does on the FreeBSD 4.10 machine I'm testing with). Combined with C's lack of guaranteed left-to-right evaluation, you need to save the tm_gmtoff so it doesn't get clobbered before you can use it. Something like:
tm2time(const struct tm *src)
struct tm tmp;
tmp = *src;
return timegm(&tmp) - src->tm_gmtoff;
Note that I copy the entire struct tm into a temporary variable. This prevents
timegm(3)from clobbering the tm_gmtoff so that we can use it to accurately compute the seconds since the epoch. The copy in
tmpgets clobbered, but the copy in
srcis left intact. Also, by copying the
srcstruct tm into a temporary, we never modify the argument passed in -- which is just a generally friendly thing to do.
All that said, the truly pedantic will point out that neither ISO C nor POSIX specs dictate that time_t must represents seconds. However, since we are already depending on two non-standard extensions, it seems reasonable to also depend on the fact that systems implementing
timegm(3)and the tm_gmtoff field all implement time_t values in seconds.