timezone stuff on 64 bit machines

Arthur David Olson ado
Mon Oct 23 14:56:45 UTC 1995


>> The fix is to use the fact that--at least for now--the calendar operates on
>> a grand 2800-year cycle:  any set of 2800 consecutive years contains exactly
>> 1,022,679 days.  A bit of modular arithmetic will get us where we want to be.
> 
> To me this calls attention to a fundamental design flaw: any 
> computation of daylight savings time that involves looping a
> billion times, or even a thousand, cannot be right.  Under what
> circumstances does this happen?

The attached might be used to avoid thousands of loops.

				--ado

SCCS/s.localtime.c: 7.45 vs. 7.48
*** 7.45/localtime.c	Mon Oct 23 10:48:43 1995
--- 7.48/localtime.c	Mon Oct 23 10:48:45 1995
***************
*** 1,6 ****
  #ifndef lint
  #ifndef NOID
! static char	elsieid[] = "@(#)localtime.c	7.45";
  #endif /* !defined NOID */
  #endif /* !defined lint */
  
--- 1,6 ----
  #ifndef lint
  #ifndef NOID
! static char	elsieid[] = "@(#)localtime.c	7.48";
  #endif /* !defined NOID */
  #endif /* !defined lint */
  
***************
*** 1173,1191 ****
	if (tmp->tm_wday < 0)
		tmp->tm_wday += DAYSPERWEEK;
	y = EPOCH_YEAR;
! 	if (days >= 0)
! 		for ( ; ; ) {
! 			yleap = isleap(y);
! 			if (days < (long) year_lengths[yleap])
! 				break;
! 			++y;
! 			days = days - (long) year_lengths[yleap];
! 		}
! 	else do {
! 		--y;
! 		yleap = isleap(y);
! 		days = days + (long) year_lengths[yleap];
! 	} while (days < 0);
	tmp->tm_year = y - TM_YEAR_BASE;
	tmp->tm_yday = (int) days;
	ip = mon_lengths[yleap];
--- 1173,1190 ----
	if (tmp->tm_wday < 0)
		tmp->tm_wday += DAYSPERWEEK;
	y = EPOCH_YEAR;
! #define LEAPS_THRU_END_OF(y)	((y) / 4 - (y) / 100 + (y) / 400)
! 	while (days < 0 || days >= (long) year_lengths[yleap = isleap(y)]) {
! 		register int	newy;
! 		
! 		newy = y + days / DAYSPERNYEAR;
! 		if (days < 0)
! 			--newy;
! 		days -= (newy - y) * DAYSPERNYEAR +
! 			LEAPS_THRU_END_OF(newy - 1) -
! 			LEAPS_THRU_END_OF(y - 1);
! 		y = newy;
! 	}
	tmp->tm_year = y - TM_YEAR_BASE;
	tmp->tm_yday = (int) days;
	ip = mon_lengths[yleap];



More information about the tz mailing list