support for C99 strftime %F and %z formats, plus Solaris 8 fix
Paul Eggert
eggert at twinsun.com
Thu Apr 13 19:16:41 UTC 2000
The new C Standard specifies two new formats for strftime: %F and %z.
Here's a proposed patch to add support for this. I ran into a Solaris 8
porting problem when debugging this, and enclose a patch for this as well.
===================================================================
RCS file: RCS/Makefile,v
retrieving revision 2000.1
retrieving revision 2000.1.0.1
diff -pu -r2000.1 -r2000.1.0.1
--- Makefile 2000/01/18 14:21:10 2000.1
+++ Makefile 2000/04/13 19:11:13 2000.1.0.1
@@ -88,6 +88,8 @@ LDLIBS=
# Add the following to the end of the "CFLAGS=" line as needed.
# -DHAVE_ADJTIME=0 if `adjtime' does not exist (SVR0?)
# -DHAVE_GETTEXT=1 if `gettext' works (GNU, Linux, Solaris); also see LDLIBS
+# -DHAVE_INCOMPATIBLE_CTIME_R=1 if your system's time.h declares
+# ctime_r and asctime_r incompatibly with the POSIX standard.
# -DHAVE_LONG_DOUBLE=1 if your compiler supports the `long double' type
# -DHAVE_SETTIMEOFDAY=0 if settimeofday does not exist (SVR0?)
# -DHAVE_SETTIMEOFDAY=1 if settimeofday has just 1 arg (SVR4)
===================================================================
RCS file: RCS/private.h,v
retrieving revision 1999.5
retrieving revision 1999.5.0.1
diff -pu -r1999.5 -r1999.5.0.1
--- private.h 1999/08/17 18:09:09 1999.5
+++ private.h 2000/04/13 19:11:13 1999.5.0.1
@@ -38,6 +38,10 @@ static char privatehid[] = "@(#)private.
#define HAVE_GETTEXT 0
#endif /* !defined HAVE_GETTEXT */
+#ifndef HAVE_INCOMPATIBLE_CTIME_R
+#define HAVE_INCOMPATIBLE_CTIME_R 1
+#endif /* !defined INCOMPATIBLE_CTIME_R */
+
#ifndef HAVE_SETTIMEOFDAY
#define HAVE_SETTIMEOFDAY 3
#endif /* !defined HAVE_SETTIMEOFDAY */
@@ -66,6 +70,11 @@ static char privatehid[] = "@(#)private.
#define LOCALE_HOME "/usr/lib/locale"
#endif /* !defined LOCALE_HOME */
+#if HAVE_INCOMPATIBLE_CTIME_R
+#define asctime_r _incompatible_asctime_r
+#define ctime_r _incompatible_ctime_r
+#endif /* HAVE_INCOMPATIBLE_CTIME_R */
+
/*
** Nested includes
*/
@@ -203,6 +212,28 @@ void icfree P((char * pointer));
void ifree P((char * pointer));
char * scheck P((const char *string, const char *format));
+/*
+** External declarations, possibly renamed to private identifiers.
+*/
+#ifndef USG_COMPAT
+#define timezone _timezone
+#define daylight _daylight
+#endif
+#ifndef ALTZONE
+#define altzone _altzone
+#endif
+/* strftime needs these variables if TM_GMTOFF is not defined. */
+#ifndef TM_GMTOFF
+#define USG_COMPAT
+#define ALTZONE
+#endif
+#ifdef USG_COMPAT
+extern time_t timezone;
+extern int daylight;
+#endif
+#ifdef ALTZONE
+extern time_t altzone;
+#endif
/*
** Finally, some convenience items.
@@ -277,6 +308,13 @@ char * scheck P((const char *string, con
#define TZ_DOMAIN "tz"
#endif /* !defined TZ_DOMAIN */
+#if HAVE_INCOMPATIBLE_CTIME_R
+#undef asctime_r
+#undef ctime_r
+char *asctime_r P((struct tm const *, char *));
+char *ctime_r P((time_t const *, char *));
+#endif /* HAVE_INCOMPATIBLE_CTIME_R */
+
/*
** UNIX was a registered trademark of UNIX System Laboratories in 1993.
*/
===================================================================
RCS file: RCS/strftime.c,v
retrieving revision 1999.9
retrieving revision 1999.9.0.1
diff -pu -r1999.9 -r1999.9.0.1
--- strftime.c 1999/11/08 19:54:36 1999.9
+++ strftime.c 2000/04/13 19:11:13 1999.9.0.1
@@ -247,6 +247,9 @@ label:
case 'e':
pt = _conv(t->tm_mday, "%2d", pt, ptlim);
continue;
+ case 'F':
+ pt = _fmt("%Y-%m-%d", t, pt, ptlim, warnp);
+ continue;
case 'H':
pt = _conv(t->tm_hour, "%02d", pt, ptlim);
continue;
@@ -489,10 +492,46 @@ label:
pt = _add(t->TM_ZONE, pt, ptlim);
else
#endif /* defined TM_ZONE */
- if (t->tm_isdst == 0 || t->tm_isdst == 1) {
- pt = _add(tzname[t->tm_isdst],
+ if (0 <= t->tm_isdst)
+ pt = _add(tzname[t->tm_isdst != 0],
pt, ptlim);
- } else pt = _add("?", pt, ptlim);
+ continue;
+ case 'z':
+ {
+ int diff;
+ char const *sign;
+ if (t->tm_isdst < 0)
+ continue;
+#ifdef TM_GMTOFF
+ diff = t->TM_GMTOFF;
+#else /* !defined TM_GMTOFF */
+ /*
+ ** C99 says that the UTC 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.
+ **
+ */
+ diff = - (t->tm_isdst ? altzone : timezone);
+#endif /* !defined TM_GMTOFF */
+ if (diff < 0) {
+ sign = "-";
+ diff = -diff;
+ } else
+ sign = "+";
+ pt = _add(sign, pt, ptlim);
+ diff /= 60;
+ pt = _conv((diff/60)*100 + diff%60,
+ "%04d", pt, ptlim);
+ }
continue;
case '+':
pt = _fmt(Locale->date_fmt, t, pt, ptlim,
More information about the tz
mailing list