Strftime's %C and %y formats versus wide-ranging tm_year valu es
Olson, Arthur David (NIH/NCI)
olsona at dc37a.nci.nih.gov
Thu Sep 23 19:39:37 UTC 2004
At the end of this message you'll find proposed changes to strftime.c to do
the right thing for wide-ranging years.
I compiled it with this quick-and-dirty source code...
#include "stdio.h"
#include "sys/types.h"
#include "time.h"
static int years[] = {
10001, 10000, 9999,
1001, 1000, 999,
101, 100, 99,
11, 10, 9,
1, 0, -1,
-9, -10, -11,
-99, -100, -101,
-999, -1000, -1001,
-9999, -10000, -10001
};
#define NVALUES ((sizeof years) / (sizeof years[0]))
static char * formats[] = { "%C", "%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("YEAR");
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] - TM_BASE_YEAR;
for (j = 0; j < NFORMATS; ++j) {
(void) strftime(buf, sizeof buf, formats[j],
&tm);
(void) printf("\t%s", buf);
}
(void) printf("\n");
}
return 0;
}
...and got these results...
YEAR %C %y %G %g
10001 100 01 10001 01
10000 100 00 10000 00
9999 99 99 9999 99
1001 10 01 1001 01
1000 10 00 1000 00
999 09 99 0999 99
101 01 01 0101 01
100 01 00 0100 00
99 00 99 0099 99
11 00 11 0011 11
10 00 10 0010 10
9 00 09 0009 09
1 00 01 0001 01
0 00 00 0000 00
-1 -0 01 -001 01
-9 -0 09 -009 09
-10 -0 10 -010 10
-11 -0 11 -011 11
-99 -0 99 -099 99
-100 -1 00 -100 00
-101 -1 01 -101 01
-999 -9 99 -999 99
-1000 -10 00 -1000 00
-1001 -10 01 -1001 01
-9999 -99 99 -9999 99
-10000 -100 00 -10000 00
-10001 -100 01 -10001 01
Absent any objections, I'll promulgate these changes next week (along with
Paul Eggert's revised update to tz-link.htm).
--ado
------- strftime.c -------
*** /tmp/geta12949 Thu Sep 23 15:27:03 2004
--- /tmp/getb12949 Thu Sep 23 15:27:03 2004
***************
*** 1,12 ****
- /*
- ** XXX To do: figure out correct (as distinct from standard-mandated)
- ** output for "two digits of year" and "century" formats when
- ** the year is negative or less than 100. --ado, 2004-09-09
- */
-
#ifndef lint
#ifndef NOID
! static char elsieid[] = "@(#)strftime.c 7.67";
/*
** Based on the UCB version with the ID appearing below.
** This is ANSIish only when "multibyte character == plain character".
--- 1,6 ----
#ifndef lint
#ifndef NOID
! static char elsieid[] = "@(#)strftime.c 7.69";
/*
** Based on the UCB version with the ID appearing below.
** This is ANSIish only when "multibyte character == plain character".
***************
*** 217,225 ****
** something completely different.
** (ado, 1993-05-24)
*/
! pt = _conv((int) ((t->tm_year +
! (long) TM_YEAR_BASE) / 100),
! "%02d", pt, ptlim);
continue;
case 'c':
{
--- 211,230 ----
** something completely different.
** (ado, 1993-05-24)
*/
! {
! long year;
! int top;
!
! year = t->tm_year;
! year += TM_YEAR_BASE;
! top = year / 100;
! if (top == 0 && year < 0) {
! pt = _add("-0", pt, ptlim);
! } else {
! pt = _conv(top, "%02d",
! pt, ptlim);
! }
! }
continue;
case 'c':
{
***************
*** 445,453 ****
pt = _conv(w, "%02d",
pt, ptlim);
else if (*format == 'g') {
*warnp = IN_ALL;
! pt = _conv(int(year % 100),
! "%02d", pt, ptlim);
} else pt = _lconv(year, "%04ld",
pt, ptlim);
}
--- 450,464 ----
pt = _conv(w, "%02d",
pt, ptlim);
else if (*format == 'g') {
+ int i;
+
*warnp = IN_ALL;
! i = year % 100;
! if (i < 0) {
! i = -i;
! }
! pt = _conv(i, "%02d",
! pt, ptlim);
} else pt = _lconv(year, "%04ld",
pt, ptlim);
}
***************
*** 486,494 ****
continue;
case 'y':
*warnp = IN_ALL;
! pt = _conv((int) ((t->tm_year +
! (long) TM_YEAR_BASE) % 100),
! "%02d", pt, ptlim);
continue;
case 'Y':
pt = _lconv(t->tm_year + (long)
TM_YEAR_BASE,
--- 497,512 ----
continue;
case 'y':
*warnp = IN_ALL;
! {
! int i;
!
! i = (t->tm_year +
! (long) TM_YEAR_BASE) % 100;
! if (i < 0) {
! i = -i;
! }
! pt = _conv(i, "%02d", pt, ptlim);
! }
continue;
case 'Y':
pt = _lconv(t->tm_year + (long)
TM_YEAR_BASE,
***************
*** 556,564 ****
diff = -diff;
} else sign = "+";
pt = _add(sign, pt, ptlim);
! diff /= 60;
! pt = _conv((diff/60)*100 + diff%60,
! "%04d", pt, ptlim);
}
continue;
case '+':
--- 574,583 ----
diff = -diff;
} else sign = "+";
pt = _add(sign, pt, ptlim);
! diff /= SECSPERMIN;
! diff = (diff / MINSPERHOUR) * 100 +
! (diff % MINSPERHOUR);
! pt = _conv(diff, "%04d", pt, ptlim);
}
continue;
case '+':
More information about the tz
mailing list