1/*	$NetBSD$	*/
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 */
20u_long
21calyearstart(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