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