[tz] NetBSD and Android bionic APIs for tz values

Paul Eggert eggert at cs.ucla.edu
Mon Aug 25 07:32:47 UTC 2014


Paul Eggert wrote:
> A preliminary proposed patch to NetBSD-current sources attached.

Following up on this, I implemented it for tzcode; see

http://mm.icann.org/pipermail/tz/2014-August/021516.html

In doing so it struck me that the proposal for new functions tm_strftime 
and tm_strftime_l is overkill, and that it's better to simply fix 
strftime and strftime_l to do the right thing with %z and %Z, as that's 
what glibc does.  I understand there's an argument that POSIX doesn't 
allow this behavior, but it's not clear to me that the argument is 
correct, and anyway NetBSD would be in good company when it's compatible 
with tzcode and with GNU/Linux here.  So attached is a a revised patch 
that simply removes strftime_z/strftime_lz and fixes 
strftime/strftime_l.  The rest of the patch is the same as before.
-------------- next part --------------
Index: libc/compat/include/time.h
===================================================================
RCS file: /cvsroot/src/lib/libc/compat/include/time.h,v
retrieving revision 1.3
diff -u -b -w -r1.3 time.h
--- libc/compat/include/time.h	16 Dec 2010 18:38:06 -0000	1.3
+++ libc/compat/include/time.h	25 Aug 2014 07:22:52 -0000
@@ -92,15 +92,12 @@
 int32_t timeoff(struct tm *, long);
 int32_t time2posix(int32_t);
 int32_t posix2time(int32_t);
-struct tm *localtime_rz(const timezone_t, const int32_t * __restrict,
+struct tm *localtime_rz(timezone_t __restrict, const int32_t * __restrict,
     struct tm * __restrict);
-char *ctime_rz(const timezone_t, const int32_t *, char *);
-int32_t mktime_z(const timezone_t, struct tm *);
-int32_t timelocal_z(const timezone_t, struct tm *);
-int32_t time2posix_z(const timezone_t, int32_t);
-int32_t posix2time_z(const timezone_t, int32_t);
+int32_t mktime_z(timezone_t __restrict, struct tm * __restrict);
+int32_t time2posix_z(timezone_t, int32_t);
+int32_t posix2time_z(timezone_t, int32_t);
 timezone_t tzalloc(const char *);
-void tzfree(const timezone_t);
-const char *tzgetname(const timezone_t, int);
+void tzfree(timezone_t);
 
 #endif /* !_COMPAT_TIME_H_ */
Index: libc/compat/time/compat_localtime.c
===================================================================
RCS file: /cvsroot/src/lib/libc/compat/time/compat_localtime.c,v
retrieving revision 1.3
diff -u -b -w -r1.3 compat_localtime.c
--- libc/compat/time/compat_localtime.c	21 Feb 2011 22:07:44 -0000	1.3
+++ libc/compat/time/compat_localtime.c	25 Aug 2014 07:22:52 -0000
@@ -16,7 +16,6 @@
 
 #ifdef __weak_alias
 __weak_alias(ctime_r,_ctime_r)
-__weak_alias(ctime_rz,_ctime_rz)
 __weak_alias(gmtime_r,_gmtime_r)
 __weak_alias(localtime_r,_localtime_r)
 __weak_alias(localtime_rz,_localtime_rz)
@@ -35,9 +34,6 @@
 __warn_references(ctime_r,
     "warning: reference to compatibility ctime_r();"
     " include <time.h> for correct reference")
-__warn_references(ctime_rz,
-    "warning: reference to compatibility ctime_rz();"
-    " include <time.h> for correct reference")
 __warn_references(gmtime_r,
     "warning: reference to compatibility gmtime_r();"
     " include <time.h> for correct reference")
Index: libc/include/namespace.h
===================================================================
RCS file: /cvsroot/src/lib/libc/include/namespace.h,v
retrieving revision 1.174
diff -u -b -w -r1.174 namespace.h
--- libc/include/namespace.h	13 Jun 2014 15:45:05 -0000	1.174
+++ libc/include/namespace.h	25 Aug 2014 07:22:52 -0000
@@ -244,7 +244,6 @@
 #define csetexpandtc		_csetexpandtc
 #define ctermid			_ctermid
 #define ctime_r			_ctime_r
-#define ctime_rz		_ctime_rz
 #define daemon			_daemon
 #define dbopen			_dbopen
 #define devname			_devname
@@ -629,8 +628,6 @@
 #define strdup			_strdup
 #define stresep			_stresep
 #define strftime_l		_strftime_l
-#define strftime_lz		_strftime_lz
-#define strftime_z		_strftime_z
 #define strndup			_strndup
 #define strncasecmp		_strncasecmp
 #define strptime		_strptime
Index: libc/time/Makefile.inc
===================================================================
RCS file: /cvsroot/src/lib/libc/time/Makefile.inc,v
retrieving revision 1.18
diff -u -b -w -r1.18 Makefile.inc
--- libc/time/Makefile.inc	16 Jan 2014 20:31:43 -0000	1.18
+++ libc/time/Makefile.inc	25 Aug 2014 07:22:52 -0000
@@ -8,7 +8,6 @@
 CPPFLAGS+=-DALL_STATE -DUSG_COMPAT
 
 MLINKS+=ctime.3 ctime_r.3	\
-	ctime.3 ctime_rz.3	\
 	ctime.3 asctime.3	\
 	ctime.3 asctime_r.3	\
 	ctime.3 difftime.3	\
@@ -21,7 +20,6 @@
 	ctime.3 mktime_z.3	\
 	ctime.3 tzalloc.3	\
 	ctime.3 tzfree.3	\
-	ctime.3 tzgetname.3	\
 	getdate.3 getdate_err.3	\
 	offtime.3 offtime_r.3	\
 	offtime.3 timeoff.3	\
@@ -31,7 +29,6 @@
 	time2posix.3 posix2time_z.3 \
 	time2posix.3 time2posix_z.3 \
 	tzset.3 daylight.3	\
-	tzset.3 tzsetwall.3	\
-	strftime.3 strftime_z.3
+	tzset.3 tzsetwall.3
 
 COPTS.strftime.c = -Wno-format-nonliteral
Index: libc/time/ctime.3
===================================================================
RCS file: /cvsroot/src/lib/libc/time/ctime.3,v
retrieving revision 1.50
diff -u -b -w -r1.50 ctime.3
--- libc/time/ctime.3	15 Aug 2014 11:04:07 -0000	1.50
+++ libc/time/ctime.3	25 Aug 2014 07:22:52 -0000
@@ -10,7 +10,6 @@
 .Nm asctime_r ,
 .Nm ctime ,
 .Nm ctime_r ,
-.Nm ctime_rz ,
 .Nm difftime ,
 .Nm gmtime ,
 .Nm gmtime_r ,
@@ -20,7 +19,6 @@
 .Nm mktime ,
 .Nm mktime_z ,
 .Nm tzalloc ,
-.Nm tzgetname ,
 .Nm tzfree ,
 .Nd convert date and time
 .Sh LIBRARY
@@ -36,8 +34,6 @@
 .Fn ctime "const time_t *clock"
 .Ft char *
 .Fn ctime_r "const time_t *clock"  "char *buf"
-.Ft char *
-.Fn ctime_rz "const timezone_t tz" "const time_t *clock"  "char *buf"
 .Ft double
 .Fn difftime "time_t time1" "time_t time0"
 .Ft struct tm *
@@ -49,17 +45,16 @@
 .Ft struct tm *
 .Fn localtime_r "const time_t * restrict clock" "struct tm * restrict result"
 .Ft struct tm *
-.Fn localtime_rz "const timezone_t tz" "const time_t * restrict clock" "struct tm * restrict result"
+.Fn localtime_rz "timezone_t restrict tz" "const time_t * restrict clock" "struct tm * restrict result"
 .Ft time_t
 .Fn mktime "struct tm *tm"
 .Ft time_t
-.Fn mktime_z "const timezone_t tz" "struct tm *tm"
+.Fn mktime_z "timezone_t restrict tz" "struct tm * restrict tm"
 .Ft timezone_t
 .Fn tzalloc "const char *zone"
 .Ft void
-.Fn tzfree "const timezone_t tz"
+.Fn tzfree "timezone_t tz"
 .Ft const char *
-.Fn tzgetname "const timezone_t tz" "int isdst"
 .Sh DESCRIPTION
 The
 .Nm
@@ -127,18 +122,6 @@
 .Fa buf
 argument, which should be 26 or more bytes long,
 instead of using a global static buffer.
-.It Fn ctime_rz "tz" "clock" "buf"
-The
-.Fn ctime_rz
-function is similar to
-.Fn ctime_r ,
-but it also takes a
-.Ft "const timezone_t"
-argument, as returned by a previous call to
-.Fn tzalloc ,
-or a null pointer denoting
-Coordinated Universal Time
-.Pq Tn UTC .
 .It Fn difftime "time1" "time2"
 The
 .Fn difftime
@@ -200,7 +183,7 @@
 function is similar to
 .Fn localtime_r ,
 but it also takes a
-.Ft "const timezone_t"
+.Ft timezone_t
 argument, returned by a previous call to
 .Fn tzalloc ,
 or a null pointer denoting
@@ -280,7 +263,7 @@
 function is similar to
 .Fn mktime
 but it also takes a
-.Ft "const timezone_t"
+.Ft timezone_t
 argument, returned by a previous call to
 .Fn tzalloc ,
 or a null pointer denoting
@@ -292,8 +275,7 @@
 function takes as an argument a timezone name and returns a
 .Ft timezone_t
 object suitable to be used in the
-.Fn ctime_rz ,
-.Fn localtime_rz ,
+.Fn localtime_rz
 and
 .Fn mktime_z
 functions.
@@ -321,23 +303,6 @@
 .Fa tz ,
 which was previously allocated by
 .Fn tzalloc .
-.It Fn "tzgetname"
-Finally,
-.Fn tzgetname
-returns the name for the given
-.Fa tz .
-If
-.Fa isdst
-is
-.Va 0 ,
-the call is equivalent to
-.Va tzname[0] .
-If
-.Fa isdst
-is set to
-.Va 1
-the call is equivalent to
-.Va tzname[1] .
 .El
 .Pp
 Declarations of all the functions and externals, and the 
@@ -389,11 +354,10 @@
 and
 .Fn ctime
 functions return a pointer to a static character buffer, and the
-.Fn asctime_r ,
-.Fn ctime_r ,
+.Fn asctime_r
 and
-.Fn ctime_rz
-function return a pointer to the user-supplied buffer.
+.Fn ctime_r
+functions return a pointer to the user-supplied buffer.
 On failure they all return
 .Dv NULL
 and no errors are defined for them.
Index: libc/time/localtime.c
===================================================================
RCS file: /cvsroot/src/lib/libc/time/localtime.c,v
retrieving revision 1.85
diff -u -b -w -r1.85 localtime.c
--- libc/time/localtime.c	16 Aug 2014 16:22:21 -0000	1.85
+++ libc/time/localtime.c	25 Aug 2014 07:22:52 -0000
@@ -286,19 +286,6 @@
 	return result;
 }
 
-const char *
-tzgetname(const timezone_t sp, int isdst)
-{
-	int i;
-	for (i = 0; i < sp->timecnt; ++i) {
-		const struct ttinfo *const ttisp = &sp->ttis[sp->types[i]];
-
-		if (ttisp->tt_isdst == isdst)
-			return &sp->chars[ttisp->tt_abbrind];
-	}
-	return NULL;
-}
-
 static void
 settzname_z(timezone_t sp)
 {
@@ -1728,17 +1715,6 @@
 	return asctime_r(rtm, buf);
 }
 
-char *
-ctime_rz(const timezone_t sp, const time_t * timep, char *buf)
-{
-	struct tm	mytm, *rtm;
-
-	rtm = localtime_rz(sp, timep, &mytm);
-	if (rtm == NULL)
-		return NULL;
-	return asctime_r(rtm, buf);
-}
-
 /*
 ** Adapted from code provided by Robert Elz, who writes:
 **	The "best" way to do mktime I think is based on an idea of Bob
@@ -2158,14 +2134,6 @@
 #ifdef STD_INSPIRED
 
 time_t
-timelocal_z(const timezone_t sp, struct tm *const tmp)
-{
-	if (tmp != NULL)
-		tmp->tm_isdst = -1;	/* in case it wasn't initialized */
-	return mktime_z(sp, tmp);
-}
-
-time_t
 timelocal(struct tm *const tmp)
 {
 	if (tmp != NULL)
Index: libc/time/strftime.3
===================================================================
RCS file: /cvsroot/src/lib/libc/time/strftime.3,v
retrieving revision 1.30
diff -u -b -w -r1.30 strftime.3
--- libc/time/strftime.3	20 Sep 2013 19:06:54 -0000	1.30
+++ libc/time/strftime.3	25 Aug 2014 07:22:52 -0000
@@ -36,8 +36,7 @@
 .Dt STRFTIME 3
 .Os
 .Sh NAME
-.Nm strftime ,
-.Nm strftime_z
+.Nm strftime
 .Nd format date and time
 .Sh LIBRARY
 .Lb libc
@@ -45,8 +44,6 @@
 .In time.h
 .Ft size_t
 .Fn strftime "char * restrict buf" "size_t maxsize" "const char * restrict format" "const struct tm * restrict timeptr"
-.Ft size_t
-.Fn strftime_z "const timezone_t tz" "char * restrict buf" "size_t maxsize" "const char * restrict format" "const struct tm * restrict timeptr"
 .Sh DESCRIPTION
 The
 .Fn strftime
@@ -199,15 +196,6 @@
 is replaced by
 .Ql % .
 .El
-.Pp
-The
-.Fn strftime_z
-function is similar to
-.Fn strftime ,
-but it also takes a
-.Ft "const timezone_t"
-.Fa tz
-argument.
 .Sh SEE ALSO
 .Xr date 1 ,
 .Xr printf 1 ,
Index: libc/time/strftime.c
===================================================================
RCS file: /cvsroot/src/lib/libc/time/strftime.c,v
retrieving revision 1.31
diff -u -b -w -r1.31 strftime.c
--- libc/time/strftime.c	15 Aug 2014 11:04:07 -0000	1.31
+++ libc/time/strftime.c	25 Aug 2014 07:22:52 -0000
@@ -27,17 +27,6 @@
 #include "private.h"
 
 /*
-** We don't use these extensions in strftime operation even when
-** supported by the local tzcode configuration.  A strictly
-** conforming C application may leave them in undefined state.
-*/
-
-#ifdef _LIBC
-#undef TM_ZONE
-#undef TM_GMTOFF
-#endif
-
-/*
 ** Copyright (c) 1989, 1993
 **	The Regents of the University of California.  All rights reserved.
 **
@@ -76,8 +65,6 @@
 
 #ifdef __weak_alias
 __weak_alias(strftime_l, _strftime_l)
-__weak_alias(strftime_lz, _strftime_lz)
-__weak_alias(strftime_z, _strftime_z)
 #endif
 
 #include "sys/localedef.h"
@@ -87,7 +74,7 @@
 
 static char *	_add(const char *, char *, const char *);
 static char *	_conv(int, const char *, char *, const char *);
-static char *	_fmt(const timezone_t, const char *, const struct tm *, char *,
+static char *	_fmt(const char *, const struct tm *, char *,
 			const char *, int *, locale_t);
 static char *	_yconv(int, int, int, int, char *, const char *);
 
@@ -103,21 +90,14 @@
 #define IN_ALL	3
 
 size_t
-strftime_z(const timezone_t sp, char * __restrict s, size_t maxsize,
-    const char * __restrict format, const struct tm * __restrict t)
-{
-	return strftime_lz(sp, s, maxsize, format, t, _current_locale());
-}
-
-size_t
-strftime_lz(const timezone_t sp, char *const s, const size_t maxsize,
-    const char *const format, const struct tm *const t, locale_t loc)
+strftime_l(char * __restrict s, size_t maxsize, const char * __restrict format,
+    const struct tm * __restrict t, locale_t loc)
 {
 	char *	p;
 	int	warn;
 
 	warn = IN_NONE;
-	p = _fmt(sp, ((format == NULL) ? "%c" : format), t, s, s + maxsize,
+	p = _fmt(((format == NULL) ? "%c" : format), t, s, s + maxsize,
 	    &warn, loc);
 #ifndef NO_RUN_TIME_WARNINGS_ABOUT_YEAR_2000_PROBLEMS_THANK_YOU
 	if (warn != IN_NONE && getenv(YEAR_2000_NAME) != NULL) {
@@ -142,7 +122,7 @@
 }
 
 static char *
-_fmt(const timezone_t sp, const char *format, const struct tm *const t,
+_fmt(const char *format, const struct tm *const t,
 	char *pt, const char *const ptlim, int *warnp, locale_t loc)
 {
 	for ( ; *format; ++format) {
@@ -192,7 +172,7 @@
 				{
 				int warn2 = IN_SOME;
 
-				pt = _fmt(sp, _TIME_LOCALE(loc)->c_fmt, t, pt,
+				pt = _fmt(_TIME_LOCALE(loc)->c_fmt, t, pt,
 				    ptlim, &warn2, loc);
 				if (warn2 == IN_ALL)
 					warn2 = IN_THIS;
@@ -201,7 +181,7 @@
 				}
 				continue;
 			case 'D':
-				pt = _fmt(sp, "%m/%d/%y", t, pt, ptlim, warnp,
+				pt = _fmt("%m/%d/%y", t, pt, ptlim, warnp,
 				    loc);
 				continue;
 			case 'd':
@@ -223,7 +203,7 @@
 				pt = _conv(t->tm_mday, "%2d", pt, ptlim);
 				continue;
 			case 'F':
-				pt = _fmt(sp, "%Y-%m-%d", t, pt, ptlim, warnp,
+				pt = _fmt("%Y-%m-%d", t, pt, ptlim, warnp,
 				    loc);
 				continue;
 			case 'H':
@@ -288,11 +268,11 @@
 					pt, ptlim);
 				continue;
 			case 'R':
-				pt = _fmt(sp, "%H:%M", t, pt, ptlim, warnp,
+				pt = _fmt("%H:%M", t, pt, ptlim, warnp,
 				    loc);
 				continue;
 			case 'r':
-				pt = _fmt(sp, _TIME_LOCALE(loc)->t_fmt_ampm, t,
+				pt = _fmt(_TIME_LOCALE(loc)->t_fmt_ampm, t,
 				    pt, ptlim, warnp, loc);
 				continue;
 			case 'S':
@@ -317,7 +297,7 @@
 				}
 				continue;
 			case 'T':
-				pt = _fmt(sp, "%H:%M:%S", t, pt, ptlim, warnp,
+				pt = _fmt("%H:%M:%S", t, pt, ptlim, warnp,
 				    loc);
 				continue;
 			case 't':
@@ -433,7 +413,7 @@
 				** "date as dd-bbb-YYYY"
 				** (ado, 1993-05-24)
 				*/
-				pt = _fmt(sp, "%e-%b-%Y", t, pt, ptlim, warnp,
+				pt = _fmt("%e-%b-%Y", t, pt, ptlim, warnp,
 				    loc);
 				continue;
 			case 'W':
@@ -447,14 +427,14 @@
 				pt = _conv(t->tm_wday, "%d", pt, ptlim);
 				continue;
 			case 'X':
-				pt = _fmt(sp, _TIME_LOCALE(loc)->t_fmt, t, pt,
+				pt = _fmt(_TIME_LOCALE(loc)->t_fmt, t, pt,
 				    ptlim, warnp, loc);
 				continue;
 			case 'x':
 				{
 				int	warn2 = IN_SOME;
 
-				pt = _fmt(sp, _TIME_LOCALE(loc)->d_fmt, t, pt,
+				pt = _fmt(_TIME_LOCALE(loc)->d_fmt, t, pt,
 				    ptlim, &warn2, loc);
 				if (warn2 == IN_ALL)
 					warn2 = IN_THIS;
@@ -472,94 +452,14 @@
 					pt, ptlim);
 				continue;
 			case 'Z':
-#ifdef TM_ZONE
-				if (t->TM_ZONE != NULL)
-					pt = _add(t->TM_ZONE, pt, ptlim);
-				else
-#endif /* defined TM_ZONE */
-				if (t->tm_isdst >= 0)
-					pt = _add((sp ?
-					    tzgetname(sp, t->tm_isdst) :
-					    tzname[t->tm_isdst != 0]),
-					    pt, ptlim);
-				/*
-				** C99 says that %Z must be replaced by the
-				** empty string if the time zone is not
-				** determinable.
-				*/
+				pt = _add(t->tm_zone, pt, ptlim);
 				continue;
 			case 'z':
 				{
 				long		diff;
 				char const *	sign;
 
-				if (t->tm_isdst < 0)
-					continue;
-#ifdef TM_GMTOFF
-				diff = (int)t->TM_GMTOFF;
-#else /* !defined TM_GMTOFF */
-				/*
-				** C99 says that the UT offset must
-				** be computed by looking only at
-				** tm_isdst. This requirement is
-				** incorrect, since it means the code
-				** must rely on magic (in this case
-				** altzone and timezone), and the
-				** magic might not have the correct
-				** offset. Doing things correctly is
-				** tricky and requires disobeying C99;
-				** see GNU C strftime for details.
-				** For now, punt and conform to the
-				** standard, even though it's incorrect.
-				**
-				** C99 says that %z must be replaced by the
-				** empty string if the time zone is not
-				** determinable, so output nothing if the
-				** appropriate variables are not available.
-				*/
-#ifndef STD_INSPIRED
-				if (t->tm_isdst == 0)
-#ifdef USG_COMPAT
-					diff = -timezone;
-#else /* !defined USG_COMPAT */
-					continue;
-#endif /* !defined USG_COMPAT */
-				else
-#ifdef ALTZONE
-					diff = -altzone;
-#else /* !defined ALTZONE */
-					continue;
-#endif /* !defined ALTZONE */
-#else /* defined STD_INSPIRED */
-				{
-					struct tm tmp;
-					time_t lct, gct;
-
-					/*
-					** Get calendar time from t
-					** being treated as local.
-					*/
-					tmp = *t; /* mktime discards const */
-					lct = mktime(&tmp);
-
-					if (lct == (time_t)-1)
-						continue;
-
-					/*
-					** Get calendar time from t
-					** being treated as GMT.
-					**/
-					tmp = *t; /* mktime discards const */
-					gct = timegm(&tmp);
-
-					if (gct == (time_t)-1)
-						continue;
-
-					/* LINTED difference will fit int */
-					diff = (intmax_t)gct - (intmax_t)lct;
-				}
-#endif /* defined STD_INSPIRED */
-#endif /* !defined TM_GMTOFF */
+				diff = t->tm_gmtoff;
 				if (diff < 0) {
 					sign = "-";
 					diff = -diff;
@@ -574,7 +474,7 @@
 				continue;
 #if 0
 			case '+':
-				pt = _fmt(sp, _TIME_LOCALE(loc)->date_fmt, t,
+				pt = _fmt(_TIME_LOCALE(loc)->date_fmt, t,
 				    pt, ptlim, warnp, loc);
 				continue;
 #endif
@@ -599,16 +499,7 @@
 strftime(char * const s, const size_t maxsize,
     const char * const format, const struct tm * const	t)
 {
-	tzset();
-	return strftime_z(NULL, s, maxsize, format, t);
-}
-
-size_t
-strftime_l(char * __restrict s, size_t maxsize, const char * __restrict format,
-    const struct tm * __restrict t, locale_t loc)
-{
-	tzset();
-	return strftime_lz(NULL, s, maxsize, format, t, loc);
+	return strftime_l(s, maxsize, format, t, _current_locale());
 }
 
 static char *
Index: libc/time/time2posix.3
===================================================================
RCS file: /cvsroot/src/lib/libc/time/time2posix.3,v
retrieving revision 1.18
diff -u -b -w -r1.18 time2posix.3
--- libc/time/time2posix.3	15 Aug 2014 11:04:07 -0000	1.18
+++ libc/time/time2posix.3	25 Aug 2014 07:22:52 -0000
@@ -15,11 +15,11 @@
 .Ft time_t
 .Fn time2posix "time_t t"
 .Ft time_t
-.Fn time2posix_z "const timezone_t tz" "time_t t"
+.Fn time2posix_z "timezone_t tz" "time_t t"
 .Ft time_t
 .Fn posix2time "time_t t"
 .Ft time_t
-.Fn posix2time_z "const timezone_t tz" "time_t t"
+.Fn posix2time_z "timezone_t tz" "time_t t"
 .Sh DESCRIPTION
 .St -p1003.1
 legislates that a


More information about the tz mailing list