bug in mktime() normalization?

Olson, Arthur David OLSONA at dc37a.nci.nih.gov
Mon Aug 25 17:24:49 UTC 1997


Below find changes to localtime.c designed to deal with the situation
described by Tom Peterson.

The challenge we're faced with is that we don't want to prematurely
normalize the tm_sec field
in a structure passed to "mktime"--the field might contain a value
associated with a leap second.
The approach taken below is to first do things without normalizing but,
if that fails, to do things using normalization.

My check indicates that this approach gives the desired behavior in the
example program provided by Tom.

				--ado

*** 7.61/localtime.c	Mon Aug 25 13:23:24 1997
--- 7.62/localtime.c	Mon Aug 25 13:23:25 1997
***************
*** 5,11 ****
  
  #ifndef lint
  #ifndef NOID
! static char	elsieid[] = "@(#)localtime.c	7.61";
  #endif /* !defined NOID */
  #endif /* !defined lint */
  
--- 5,11 ----
  
  #ifndef lint
  #ifndef NOID
! static char	elsieid[] = "@(#)localtime.c	7.62";
  #endif /* !defined NOID */
  #endif /* !defined lint */
  
***************
*** 134,139 ****
--- 134,143 ----
  				void(*funcp) P((const time_t *,
  				long, struct tm*)),
  				long offset, int * okayp));
+ static time_t		time2sub P((struct tm *tmp,
+ 				void(*funcp) P((const time_t *,
+ 				long, struct tm*)),
+ 				long offset, int * okayp, int
do_norm_secs));
  static void		timesub P((const time_t * timep, long offset,
  				const struct state * sp, struct tm *
tmp));
  static int		tmcomp P((const struct tm * atmp,
***************
*** 1276,1286 ****
  }
  
  static time_t
! time2(tmp, funcp, offset, okayp)
  struct tm * const	tmp;
  void (* const		funcp) P((const time_t*, long, struct tm*));
  const long		offset;
  int * const		okayp;
  {
  	register const struct state *	sp;
  	register int			dir;
--- 1280,1291 ----
  }
  
  static time_t
! time2sub(tmp, funcp, offset, okayp, do_norm_secs)
  struct tm * const	tmp;
  void (* const		funcp) P((const time_t*, long, struct tm*));
  const long		offset;
  int * const		okayp;
+ const int		do_norm_secs;
  {
  	register const struct state *	sp;
  	register int			dir;
***************
*** 1293,1298 ****
--- 1298,1308 ----
  
  	*okayp = FALSE;
  	yourtm = *tmp;
+ 	if (do_norm_secs) {
+ 		if (normalize_overflow(&yourtm.tm_min, &yourtm.tm_sec,
+ 			SECSPERMIN))
+ 				return WRONG;
+ 	}
  	if (normalize_overflow(&yourtm.tm_hour, &yourtm.tm_min,
MINSPERHOUR))
  		return WRONG;
  	if (normalize_overflow(&yourtm.tm_mday, &yourtm.tm_hour,
HOURSPERDAY))
***************
*** 1421,1426 ****
--- 1431,1454 ----
  	return t;
  }
  
+ static time_t
+ time2(tmp, funcp, offset, okayp)
+ struct tm * const	tmp;
+ void (* const		funcp) P((const time_t*, long, struct tm*));
+ const long		offset;
+ int * const		okayp;
+ {
+ 	time_t	t;
+ 
+ 	/*
+ 	** First try without normalization of seconds
+ 	** (in case tm_sec contains a value associated with a leap
second).
+ 	** If that fails, try with normalization of seconds.
+ 	*/
+ 	t = time2sub(tmp, funcp, offset, okayp, FALSE);
+ 	return *okayp ? t : time2sub(tmp, funcp, offset, okayp, TRUE);
+ }
+ 
  static time_t
  time1(tmp, funcp, offset)
  struct tm * const	tmp;




More information about the tz mailing list