"Olson, Arthur David (NIH/NCI)" <olsona@dc37a.nci.nih.gov> writes:
Absent any objections, ...
I found a bug on 32-bit hosts: it misformats %Y, %y, %C, etc., when t->tm_year is close to INT_MAX. This is because tm_year + 1900 t->overflows. In the common 32-bit case where 'long' is the same width as 'int', converting to 'long' first doesn't help. This bug was present in the old version too, but we might as well fix it while we're in the neighborhood. I'll send a proposed fix in my next email, but first I'll give an illustration of the bug. The following test program (derived from the program you emailed) will output lines that look like this (modulo white space): Y-1900 %C %Y %y %G %g ... 2147483647 -21474817 -2147481749 49 -2147481749 49 2147483646 -21474817 -2147481750 50 -2147481750 50 2147483645 -21474817 -2147481751 51 -2147481751 51 2147481748 -21474836 -2147483648 48 -2147483648 48 instead of the correct answers, which look like this: Y-1900 %C %Y %y %G %g ... 2147483647 21474855 2147485547 47 2147485547 47 2147483646 21474855 2147485546 46 2147485546 46 2147483645 21474855 2147485545 45 2147485545 45 2147481748 21474836 2147483648 48 2147483648 48 #include <limits.h> #include <stdio.h> #include <time.h> static int years[] = { 10001 - 1900, 10000 - 1900, 9999 - 1900, 1001 - 1900, 1000 - 1900, 999 - 1900, 101 - 1900, 100 - 1900, 99 - 1900, 11 - 1900, 10 - 1900, 9 - 1900, 1 - 1900, 0 - 1900, -1 - 1900, -9 - 1900, -10 - 1900, -11 - 1900, -99 - 1900, -100 - 1900, -101 - 1900, -999 - 1900, -1000 - 1900, -1001 - 1900, -9999 - 1900, -10000 - 1900, -10001 - 1900, INT_MAX, INT_MAX - 1, INT_MAX - 2, INT_MAX - 1900 + 1, INT_MAX - 1900, INT_MAX - 1 - 1900, INT_MIN + 2, INT_MIN + 1, INT_MIN }; #define NVALUES ((sizeof years) / (sizeof years[0])) static char *formats[] = { "%C", "%Y", "%y", "%G", "%g" }; #define NFORMATS ((sizeof formats) / (sizeof formats[0])) #define TM_BASE_YEAR 1900 main () { static struct tm tm; int i; int j; char buf[1024]; tm.tm_mon = 0; /* months since January => January */ tm.tm_mday = 8; /* day of the month */ tm.tm_yday = 7; /* days since January 1 */ (void) printf ("Y-1900"); for (j = 0; j < NFORMATS; ++j) { (void) printf ("\t%s", formats[j]); } (void) printf ("\n"); for (i = 0; i < NVALUES; ++i) { (void) printf ("%d", years[i]); tm.tm_year = years[i]; for (j = 0; j < NFORMATS; ++j) { (void) strftime (buf, sizeof buf, formats[j], &tm); (void) printf ("\t%s", buf); } (void) printf ("\n"); } return 0; }