errors in ISO week number

Hume Smith hclsmith at localhost.isisnet.com
Mon Jan 1 23:00:56 UTC 1996

```>
> Me:
> > > I think I disagree rather strongly with this. Dec 31 should always be
> > > in the last week of the year.  This just makes sense.

so does having Jan 1 in the first week of next year, but
that doesn't seem to be the way it works.  ISO's
concerned with a week-oriented calendar, the week being
the one cycle which has dominated Western civilisation
unchanged for millenia.

a better person to ask this may be Eduard Rheingold <rheingold at cs.uiuc.edu> -
he wrote the emacs 19.30 calendar package which has been my reference.

> Sigh. Not what I wanted to hear (TM).  Oh well. I'll take a look at my

well, i'm not tor, but i'll tell you what i did.  compute
an absolute week number, work out what year it's in, work
out what week that year starts.  it's very simple for any
part of the calendar not involving the Gregorian correction,
and right now we're in the middle of a 200-year span not
affected by it.  it takes two calculations, both of the
form (Ax+B)/C.  no branches, no loops... it really can't
get much simpler.

it's possible that the same thing will work for a complete
Gregorian cycle, changing A to 20871, C to 400, and B to something,
but i haven't tried it yet (i need to work out all the numbers
with another method before i can try to find a B).
...
===============================================================================
SCCS/s.strftime.c: 7.38 vs. 7.42
*** 7.38/strftime.c	Tue Jan  2 17:21:43 1996
--- 7.42/strftime.c	Tue Jan  2 17:21:44 1996
***************
*** 1,6 ****
#ifndef lint
#ifndef NOID
! static char	elsieid[] = "@(#)strftime.c	7.38";
/*
** 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.42";
/*
** Based on the UCB version with the ID appearing below.
** This is ANSIish only when "multibyte character == plain character".
***************
*** 296,361 ****
"%d", pt, ptlim);
continue;
case 'V':
! 				/*
! 				** From Arnold Robbins' strftime version 3.0:
! 				** "the week number of the year (the first
! 				** Monday as the first day of week 1) as a
! 				** decimal number (01-53).  The method for
! 				** determining the week number is as specified
! 				** by ISO 8601 (to wit: if the week containing
! 				** January 1 has four or more days in the new
! 				** year, then it is week 1, otherwise it is
! 				** week 53 of the previous year and the next
! 				** week is week 1)."
! 				*/
! 				/*
! 				** XXX--If January 1 falls on a Friday,
! 				** January 1-3 are part of week 53 of the
! 				** previous year.  By analogy, if January
! 				** 1 falls on a Thursday, are December 29-31
! 				** of the PREVIOUS year part of week 1???
! 				*/
! 				/*
! 				** You are understood not to expect this.
! 				*/
{
! 					int	i;

! 					i = (t->tm_yday + 10 - (t->tm_wday ?
! 						(t->tm_wday - 1) : 6)) / 7;
! 					if (i == 0) {
/*
! 						** What day of the week does
! 						** January 1 fall on?
*/
! 						i = t->tm_wday -
! 							(t->tm_yday - 1);
/*
! 						** Fri Jan 1: 53
! 						** Sun Jan 1: 52
! 						** Sat Jan 1: 53 if previous
! 						**		 year a leap
! 						**		 year, else 52
*/
! 						if (i == TM_FRIDAY)
! 							i = 53;
! 						else if (i == TM_SUNDAY)
! 							i = 52;
! 						else	i = isleap(t->tm_year +
! 								TM_YEAR_BASE) ?
! 								53 : 52;
! #ifdef XPG4_1994_04_09
! 						/*
! 						** As of 4/9/94, though,
! 						** XPG4 calls for 53
! 						** unconditionally.
! 						*/
! 						i = 53;
! #endif /* defined XPG4_1994_04_09 */
}
! 					pt = _conv(i, "%02d", pt, ptlim);
}
continue;
case 'v':
--- 296,366 ----
"%d", pt, ptlim);
continue;
case 'V':
! /*
! ** From Arnold Robbins' strftime version 3.0:  "the week number of the
! ** year (the first Monday as the first day of week 1) as a decimal number
! ** (01-53)."
! **
! ** From "http://www.ft.uni-erlangen.de/~mskuhn/iso-time.html" by Markus Kuhn:
! ** "Week 01 of a year is per definition the first week which has the
! ** Thursday in this year, which is equivalent to the week which contains
! ** the fourth day of January. In other words, the first week of a new year
! ** is the week which has the majority of its days in the new year. Week 01
! ** might also contain days from the previous year and the week before week
! ** 01 of a year is the last week (52 or 53) of the previous year even if
! ** it contains days from the new year. A week starts with Monday (day 1)
! ** and ends with Sunday (day 7).  For example, the first week of the year
! ** 1997 lasts from 1996-12-30 to 1997-01-05..."
! */
{
! 					int	year;
! 					int	yday;
! 					int	wday;
! 					int	w;

! 					year = t->tm_year + TM_YEAR_BASE;
! 					yday = t->tm_yday;
! 					wday = t->tm_wday;
! 					for ( ; ; ) {
! 						int	len;
! 						int	bot;
! 						int	top;
!
! 						len = isleap(year) ?
! 							DAYSPERLYEAR :
! 							DAYSPERNYEAR;
/*
! 						** What yday (-3 ... 3) does
! 						** the ISO year begin on?
*/
! 						bot = ((yday + 11 - wday) %
! 							DAYSPERWEEK) - 3;
/*
! 						** What yday does the NEXT
! 						** ISO year begin on?
*/
! 						top = bot -
! 							(len % DAYSPERWEEK);
! 						if (top < -3)
! 							top += DAYSPERWEEK;
! 						top += len;
! 						if (yday >= top) {
! 							w = 1;
! 							break;
! 						}
! 						if (yday >= bot) {
! 							w = 1 + ((yday - bot) /
! 								DAYSPERWEEK);
! 							break;
! 						}
! 						--year;
! 						yday += isleap(year) ?
! 							DAYSPERLYEAR :
! 							DAYSPERNYEAR;
}
! 					pt = _conv(w, "%02d", pt, ptlim);
}
continue;
case 'v':

```