diff options
author | Kaz Kylheku <kaz@kylheku.com> | 2023-02-13 17:58:50 -0800 |
---|---|---|
committer | Kaz Kylheku <kaz@kylheku.com> | 2023-02-13 17:58:50 -0800 |
commit | 8d54fdb9967429c46c8dc84d1c07d994b5c79856 (patch) | |
tree | b92bcf6d096e089ed9f20b46d31c5b9ee2a3c1b9 /time.c | |
parent | 53586222a4184fcbb72c993efeab8fd7ae74bbee (diff) | |
download | txr-8d54fdb9967429c46c8dc84d1c07d994b5c79856.tar.gz txr-8d54fdb9967429c46c8dc84d1c07d994b5c79856.tar.bz2 txr-8d54fdb9967429c46c8dc84d1c07d994b5c79856.zip |
time: respect gmtoff in calculating numeric time.
We have the following problem. On some platforms, the broken-down
C time structure "struct tm" has a GMT offset field which
gives the time zone of the specified time. In the Lisp
structure, we call the corresponding slot gmtoff.
This value should be taken into account when converting
the broken-down time to a numeric time value.
The underlying platform functions like mktime don't do this;
they not only ignore the gmtoff, but in some cases clobber
the field.
The GNU C library version of the POSIX strptime function
supports "%z" and "%Z" specifiers which populate the GMT
offset. But then it gets wrongly ignored.
Old/wrong behavior:
1> (time-parse-utc "%H:%M:%z" "00:00:+0900")
0
New behavior (on platforms with the GMT offset):
1> (time-parse-utc "%H:%M:%z" "00:00:+0900")
32400
* time.c (time_meth): If the Lisp time structure we are given
specifies a non-nil gmtoff, then add its value
to the returned result.
(time_parse_local, time_parse_utc): If struct tm has a
GMT offset, then we add its value to the time_t returned
by mktime, timegm or timegm_hack.
* txr.1: Updated.
Diffstat (limited to 'time.c')
-rw-r--r-- | time.c | 30 |
1 files changed, 27 insertions, 3 deletions
@@ -408,9 +408,15 @@ static val time_meth(val utc_p, val time_struct) val min = slot(time_struct, min_s); val sec = slot(time_struct, sec_s); val dst = slot(time_struct, dst_s); + val gmtoff = slot(time_struct, gmtoff_s); - return (utc_p ? make_time_utc : make_time)(year, month, day, - hour, min, sec, dst); + val out = (utc_p ? make_time_utc : make_time)(year, month, day, + hour, min, sec, dst); + + if (gmtoff) + out = plus(out, gmtoff); + + return out; } static val time_string_meth(val time_struct, val format) @@ -462,9 +468,17 @@ static val time_parse_meth(val time_struct, val format, val string) val time_parse_local(val format, val string) { struct tm tms = epoch_tm(); + if (!strptime_wrap(string, format, &tms)) return nil; +#if HAVE_TM_GMTOFF + { + long gmtoff = tms.TM_GMTOFF; + return num(mktime(&tms) + gmtoff); + } +#else return num(mktime(&tms)); +#endif } val time_parse_utc(val format, val string) @@ -472,7 +486,17 @@ val time_parse_utc(val format, val string) struct tm tms = epoch_tm(); if (!strptime_wrap(string, format, &tms)) return nil; -#if HAVE_TIMEGM +#if HAVE_TIMEGM && HAVE_TM_GMTOFF + { + long gmtoff = tms.TM_GMTOFF; + return num_time(timegm(&tms) + gmtoff); + } +#elif HAVE_TM_GMTOFF + { + long gmtoff = tms.TM_GMTOFF; + return num_time(timegm_hack(&tms) + tms.gmtoff); + } +#elif HAVE_TIMEGM return num_time(timegm(&tms)); #else return num_time(timegm_hack(&tms)); |