1 /*	$NetBSD: calyearstart.c,v 1.1.1.1 2009/12/13 16:55:02 kardel Exp $	*/
2 
3 /*
4  * calyearstart - determine the NTP time at midnight of January 1 in
5  *		  the year of the given date.
6  */
7 #include <sys/types.h>
8 
9 #include "ntp_types.h"
10 #include "ntp_calendar.h"
11 #include "ntp_stdlib.h"
12 #include "ntp_assert.h"
13 
14 /*
15  * Juergen Perlinger, 2008-11-12
16  * Use the result of 'caljulian' to get the delta from the time stamp to the
17  * beginning of the year. Do not make a second trip through 'caltontp' after
18  * fixing the date, apart for invariant tests.
19  */
20 u_long
21 calyearstart(u_long ntp_time)
22 {
23 	struct calendar jt;
24 	ntp_u_int32_t   delta;
25 
26 	caljulian(ntp_time,&jt);
27 
28 	/*
29 	* Now we have days since yearstart (unity-based) and the time in that
30 	* day. Simply merge these together to seconds and subtract that from
31 	* input time. That's faster than going through the calendar stuff
32 	* again...
33 	*/
34 	delta = (ntp_u_int32_t)jt.yearday * SECSPERDAY
35 	      + (ntp_u_int32_t)jt.hour    * MINSPERHR * SECSPERMIN
36 	      + (ntp_u_int32_t)jt.minute  * SECSPERMIN
37 	      + (ntp_u_int32_t)jt.second
38 	      - SECSPERDAY;	/* yearday is unity-based... */
39 
40 #   if ISC_CHECK_INVARIANT
41 	/*
42 	 * check that this computes properly: do a roundtrip! That's the only
43 	 * sensible test here, but it's a rather expensive invariant...
44 	 */
45 	jt.yearday  = 0;
46 	jt.month    = 1;
47 	jt.monthday = 1;
48 	jt.hour     = 0;
49 	jt.minute   = 0;
50 	jt.second   = 0;
51 	NTP_INVARIANT((ntp_u_int32_t)(caltontp(&jt) + delta) == (ntp_u_int32_t)ntp_time);
52 #   endif
53 
54 	/* The NTP time stamps (l_fp) count seconds unsigned mod 2**32, so we
55 	 * have to calculate this in the proper way!
56 	 */
57 	return (ntp_u_int32_t)(ntp_time - delta);
58 }
59