Strftime's %C and %y formats versus wide-ranging tm_year values

Ken Pizzini tz. at explicate.org
Thu Oct 7 00:36:07 UTC 2004


On Wed, Oct 06, 2004 at 04:12:46PM -0700, Paul Eggert wrote:
> OK, here's a proposed patch to the tz code.  It is relative to the
> latest published code on elsie.  It incorporates most of Arthur's
> patch circulated yesterday, except it addresses the issues I mentioned
> with C99IPMOD, with floating point, and with integer overflow
> checking; the resulting code uses int arithmetic instead of assuming
> that long and double are wider than int.

For the most part, I like it.  Two things bother me a little though:

  1) I think it's a shame that isleap_sum() needs the compiler to
     do a % more than isleap() does, but I certainly don't see any
     clean way of getting around this.  (There are ways, but the
     cures I'm coming up with are all worse than the "disease".)
     Not a big deal, but I felt a need to mention it in case someone
     else does have a bright idea.

  2) More importantly, I think that there are too many duplicate
     definitions in zdump.c.  Given the comment about independence
     at the top of zdump.c this means that or tzfile.h should be broken
     up into two files: one which includes basic #define's such as
     isleap(), TM_YEAR_BASE, and SECSPERMIN (all conditionalized as
     zdump.c currently does), and the other which contains the more
     internals-specific definitions of tzcode.h.  Attached is a
     patch, relative to Paul's most recent patch, which does this.

		--Ken Pizzini
-------------- next part --------------
diff -Nu orig/caldefs.h caldefs.h
--- orig/caldefs.h	1969-12-31 16:00:00.000000000 -0800
+++ caldefs.h	2004-10-06 17:15:41.580409504 -0700
@@ -0,0 +1,72 @@
+/*
+** This file is in the public domain.
+*/
+
+/*
+** These #define's all pertain to the proleptic Gregorian calendar
+** which is pervasively assumed by the C time APIs.
+*/
+
+#ifndef SECSPERMIN
+#define SECSPERMIN	60
+#endif /* !defined SECSPERMIN */
+
+#ifndef MINSPERHOUR
+#define MINSPERHOUR	60
+#endif /* !defined MINSPERHOUR */
+
+#ifndef HOURSPERDAY
+#define HOURSPERDAY	24
+#endif /* !defined HOURSPERDAY */
+
+#ifndef DAYSPERWEEK
+#define DAYSPERWEEK	7
+#endif /* !defined DAYSPERWEEK */
+
+#ifndef DAYSPERNYEAR
+#define DAYSPERNYEAR	365
+#endif /* !defined DAYSPERNYEAR */
+
+#ifndef DAYSPERLYEAR
+#define DAYSPERLYEAR	366
+#endif /* !defined DAYSPERLYEAR */
+
+#ifndef SECSPERHOUR
+#define SECSPERHOUR	(SECSPERMIN * MINSPERHOUR)
+#endif /* !defined SECSPERHOUR */
+
+#ifndef SECSPERDAY
+#define SECSPERDAY	((long) SECSPERHOUR * HOURSPERDAY)
+#endif /* !defined SECSPERDAY */
+
+#ifndef MONSPERYEAR
+#define MONSPERYEAR	12
+#endif /* !defined MONSPERYEAR */
+
+#ifndef EPOCH_YEAR
+#define EPOCH_YEAR	1970
+#endif /* !defined EPOCH_YEAR */
+
+#ifndef TM_YEAR_BASE
+#define TM_YEAR_BASE	1900
+#endif /* !defined TM_YEAR_BASE */
+
+#ifndef isleap
+#define isleap(y) (((y) % 4) == 0 && (((y) % 100) != 0 || ((y) % 400) == 0))
+#endif /* !defined isleap */
+
+#ifndef isleap_sum
+/*
+** Since everything in isleap is modulo 400 (or a factor of 400), we know that
+**	isleap(y) == isleap(y % 400)
+** and so
+**	isleap(a + b) == isleap((a + b) % 400)
+** or
+**	isleap(a + b) == isleap(a % 400 + b % 400)
+** This is true even if % means modulo rather than Fortran remainder
+** (which is allowed by C89 but not C99).
+** We use this to avoid addition overflow problems.
+*/
+
+#define isleap_sum(a, b)	isleap((a) % 400 + (b) % 400)
+#endif /* !defined isleap_sum */
diff -Nu orig/tzfile.h tzfile.h
--- orig/tzfile.h	2004-10-06 16:48:57.089329224 -0700
+++ tzfile.h	2004-10-06 17:16:26.844528312 -0700
@@ -25,6 +25,8 @@
 #endif /* !defined NOID */
 #endif /* !defined lint */
 
+#include "caldefs.h"
+
 /*
 ** Information about time zone files.
 */
@@ -120,16 +122,6 @@
 #define TZ_MAX_LEAPS	50	/* Maximum number of leap second corrections */
 #endif /* !defined TZ_MAX_LEAPS */
 
-#define SECSPERMIN	60
-#define MINSPERHOUR	60
-#define HOURSPERDAY	24
-#define DAYSPERWEEK	7
-#define DAYSPERNYEAR	365
-#define DAYSPERLYEAR	366
-#define SECSPERHOUR	(SECSPERMIN * MINSPERHOUR)
-#define SECSPERDAY	((long) SECSPERHOUR * HOURSPERDAY)
-#define MONSPERYEAR	12
-
 #define TM_SUNDAY	0
 #define TM_MONDAY	1
 #define TM_TUESDAY	2
@@ -151,27 +143,8 @@
 #define TM_NOVEMBER	10
 #define TM_DECEMBER	11
 
-#define TM_YEAR_BASE	1900
-
-#define EPOCH_YEAR	1970
 #define EPOCH_WDAY	TM_THURSDAY
 
-#define isleap(y) (((y) % 4) == 0 && (((y) % 100) != 0 || ((y) % 400) == 0))
-
-/*
-** Since everything in isleap is modulo 400 (or a factor of 400), we know that
-**	isleap(y) == isleap(y % 400)
-** and so
-**	isleap(a + b) == isleap((a + b) % 400)
-** or
-**	isleap(a + b) == isleap(a % 400 + b % 400)
-** This is true even if % means modulo rather than Fortran remainder
-** (which is allowed by C89 but not C99).
-** We use this to avoid addition overflow problems.
-*/
-
-#define isleap_sum(a, b)	isleap((a) % 400 + (b) % 400)
-
 #ifndef USG
 
 /*
diff -Nu orig/zdump.c zdump.c
--- orig/zdump.c	2004-10-06 16:48:57.125323752 -0700
+++ zdump.c	2004-10-06 17:17:03.985881968 -0700
@@ -12,6 +12,8 @@
 #include "time.h"	/* for struct tm */
 #include "stdlib.h"	/* for exit, malloc, atoi */
 
+#include "caldefs.h"
+
 #ifndef MAX_STRING_LENGTH
 #define MAX_STRING_LENGTH	1024
 #endif /* !defined MAX_STRING_LENGTH */
@@ -32,54 +34,6 @@
 #define EXIT_FAILURE	1
 #endif /* !defined EXIT_FAILURE */
 
-#ifndef SECSPERMIN
-#define SECSPERMIN	60
-#endif /* !defined SECSPERMIN */
-
-#ifndef MINSPERHOUR
-#define MINSPERHOUR	60
-#endif /* !defined MINSPERHOUR */
-
-#ifndef SECSPERHOUR
-#define SECSPERHOUR	(SECSPERMIN * MINSPERHOUR)
-#endif /* !defined SECSPERHOUR */
-
-#ifndef HOURSPERDAY
-#define HOURSPERDAY	24
-#endif /* !defined HOURSPERDAY */
-
-#ifndef EPOCH_YEAR
-#define EPOCH_YEAR	1970
-#endif /* !defined EPOCH_YEAR */
-
-#ifndef TM_YEAR_BASE
-#define TM_YEAR_BASE	1900
-#endif /* !defined TM_YEAR_BASE */
-
-#ifndef DAYSPERNYEAR
-#define DAYSPERNYEAR	365
-#endif /* !defined DAYSPERNYEAR */
-
-#ifndef isleap
-#define isleap(y) (((y) % 4) == 0 && (((y) % 100) != 0 || ((y) % 400) == 0))
-#endif /* !defined isleap */
-
-#ifndef isleap_sum
-/*
-** Since everything in isleap is modulo 400 (or a factor of 400), we know that
-**	isleap(y) == isleap(y % 400)
-** and so
-**	isleap(a + b) == isleap((a + b) % 400)
-** or
-**	isleap(a + b) == isleap(a % 400 + b % 400)
-** This is true even if % means modulo rather than Fortran remainder
-** (which is allowed by C89 but not C99).
-** We use this to avoid addition overflow problems.
-*/
-
-#define isleap_sum(a, b)	isleap((a) % 400 + (b) % 400)
-#endif /* !defined isleap_sum */
-
 #if HAVE_GETTEXT
 #include "locale.h"	/* for setlocale */
 #include "libintl.h"


More information about the tz mailing list