summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKaz Kylheku <kaz@kylheku.com>2023-02-13 17:58:50 -0800
committerKaz Kylheku <kaz@kylheku.com>2023-02-13 17:58:50 -0800
commit8d54fdb9967429c46c8dc84d1c07d994b5c79856 (patch)
treeb92bcf6d096e089ed9f20b46d31c5b9ee2a3c1b9
parent53586222a4184fcbb72c993efeab8fd7ae74bbee (diff)
downloadtxr-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.
-rw-r--r--time.c30
-rw-r--r--txr.122
2 files changed, 49 insertions, 3 deletions
diff --git a/time.c b/time.c
index bec85fbc..dd2945b5 100644
--- a/time.c
+++ b/time.c
@@ -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));
diff --git a/txr.1 b/txr.1
index 5133dde9..66016541 100644
--- a/txr.1
+++ b/txr.1
@@ -66896,6 +66896,22 @@ Note: the availability of these three functions
depends on the availability of
.codn strptime .
+Note: on some platforms, like the GNU C Library, the
+.code strptime
+function supports the parsing of numeric and symbolic time zones. The
+.code gmtoff
+slot of the structure ends up being set accordingly.
+The
+.code time-local
+and
+.code time-utc
+functions take the
+.code gmtoff
+field into account, adjusting the returned time accordingly.
+
+
+If these are specified.
+
.coNP Methods @ time-local and @ time-utc
.synb
.mets << time-struct .(time-local)
@@ -66931,6 +66947,12 @@ which are applied to
or
.codn make-time-utc .
+Note: if the
+.code gmtoff
+slot is not
+.codn nil ,
+its value is added to the returned result.
+
.coNP Method @ time-string
.synb
.mets << time-struct .(time-string << format )