From 489e4213a4223a831e2886c324d56e6019188163 Mon Sep 17 00:00:00 2001 From: Kaz Kylheku <kaz@kylheku.com> Date: Mon, 13 Feb 2023 18:32:42 -0800 Subject: Support gmtoff and zone in time formatting. The glibc strftime function can refer to the character string zone, and numeric zone via %Z and %z. So let us populate these from the Lisp structure. * time.c (time_fields_to_tm): Take gmtoff and zone arguments. Store these values in the struct tm, suitably converted, instead of zeros and nulls. In the case of zone, we dynamically allocate a utf-8 string, which will have to be freed. (time_fields_cleanup): New static function. Called to clean up any allocations performed by time_fields_to_tm. (time_struct_to_tm): Drop the strict parameter. This is useless because the underlying function time_fields_to_tm checks for nils and substitutes zeros. This silliness was introduced in a commit made in 2016. Extract the gmtoff and zone, passing these to time_fields_to_tm. (make_time_impl): Pass nil for gmtoff and zone, call time_fields_cleanup. (time_string_meth, time_parse_meth): No need to pass strict parameter to time_struct_to_tm. Need to call time_fields_cleanup. --- time.c | 42 ++++++++++++++++++++++-------------------- 1 file changed, 22 insertions(+), 20 deletions(-) diff --git a/time.c b/time.c index dd2945b5..18a000d7 100644 --- a/time.c +++ b/time.c @@ -237,7 +237,8 @@ static void time_fields_to_tm(struct tm *ptm, val year, val month, val day, val hour, val min, val sec, val wday, val yday, - val dst, val self) + val dst, val gmtoff, val zone, + val self) { uses_or2; ptm->tm_year = c_num(or2(year, zero), self) - 1900; @@ -257,15 +258,21 @@ static void time_fields_to_tm(struct tm *ptm, ptm->tm_isdst = 1; #if HAVE_TM_GMTOFF - ptm->TM_GMTOFF = 0; + ptm->TM_GMTOFF = c_num(or2(gmtoff, zero), self); #endif #if HAVE_TM_ZONE - ptm->TM_ZONE = 0; + ptm->TM_ZONE = if3(zone, utf8_dup_to(c_str(zone, self)), 0); #endif } -static void time_struct_to_tm(struct tm *ptm, val time_struct, val strict, - val self) +static void time_fields_cleanup(struct tm *ptm) +{ +#if HAVE_TM_ZONE + free(strip_qual(char *, ptm->TM_ZONE)); +#endif +} + +static void time_struct_to_tm(struct tm *ptm, val time_struct, val self) { val year = slot(time_struct, year_s); val month = slot(time_struct, month_s); @@ -276,20 +283,11 @@ static void time_struct_to_tm(struct tm *ptm, val time_struct, val strict, val wday = slot(time_struct, wday_s); val yday = slot(time_struct, yday_s); val dst = slot(time_struct, dst_s); - - if (!strict) { - year = (year ? year : zero); - month = (month ? month : zero); - day = (day ? day : zero); - hour = (hour ? hour : zero); - min = (min ? min : zero); - sec = (sec ? sec : zero); - wday = (wday ? wday : zero); - yday = (yday ? yday : zero); - } + val gmtoff = slot(time_struct, gmtoff_s); + val zone = slot(time_struct, zone_s); time_fields_to_tm(ptm, year, month, day, hour, min, sec, - wday, yday, dst, self); + wday, yday, dst, gmtoff, zone, self); } static val make_time_impl(time_t (*pmktime)(struct tm *), @@ -301,8 +299,9 @@ static val make_time_impl(time_t (*pmktime)(struct tm *), time_t time; time_fields_to_tm(&local, year, month, day, - hour, minute, second, nil, nil, isdst, self); + hour, minute, second, nil, nil, isdst, nil, nil, self); time = pmktime(&local); + time_fields_cleanup(&local); return time == -1 ? nil : num_time(time); } @@ -426,12 +425,13 @@ static val time_string_meth(val time_struct, val format) char buffer[512] = ""; char *fmt = utf8_dup_to(c_str(format, self)); - time_struct_to_tm(&tms, time_struct, t, self); + time_struct_to_tm(&tms, time_struct, self); if (strftime(buffer, sizeof buffer, fmt, &tms) == 0) buffer[0] = 0; free(fmt); + time_fields_cleanup(&tms); return string_own(utf8_dup_from(buffer)); } @@ -444,7 +444,7 @@ static val time_parse_meth(val time_struct, val format, val string) struct tm tms = all_zero_init; val ret = nil; - time_struct_to_tm(&tms, time_struct, nil, self); + time_struct_to_tm(&tms, time_struct, self); { const wchar_t *w_str = c_str(string, self); @@ -462,6 +462,8 @@ static val time_parse_meth(val time_struct, val format, val string) free(str); } + time_fields_cleanup(&tms); + return ret; } -- cgit v1.2.3