aboutsummaryrefslogtreecommitdiff
path: root/libntp/calyearstart.c
diff options
context:
space:
mode:
Diffstat (limited to 'libntp/calyearstart.c')
-rw-r--r--libntp/calyearstart.c48
1 files changed, 41 insertions, 7 deletions
diff --git a/libntp/calyearstart.c b/libntp/calyearstart.c
index 0f7ca4f9d065..c5a63f729b39 100644
--- a/libntp/calyearstart.c
+++ b/libntp/calyearstart.c
@@ -7,16 +7,50 @@
#include "ntp_types.h"
#include "ntp_calendar.h"
#include "ntp_stdlib.h"
+#include "ntp_assert.h"
+/*
+ * Juergen Perlinger, 2008-11-12
+ * Use the result of 'caljulian' to get the delta from the time stamp to the
+ * beginning of the year. Do not make a second trip through 'caltontp' after
+ * fixing the date, apart for invariant tests.
+ */
u_long
calyearstart(u_long ntp_time)
{
- struct calendar jt;
+ struct calendar jt;
+ ntp_u_int32_t delta;
+
+ caljulian(ntp_time,&jt);
+
+ /*
+ * Now we have days since yearstart (unity-based) and the time in that
+ * day. Simply merge these together to seconds and subtract that from
+ * input time. That's faster than going through the calendar stuff
+ * again...
+ */
+ delta = (ntp_u_int32_t)jt.yearday * SECSPERDAY
+ + (ntp_u_int32_t)jt.hour * MINSPERHR * SECSPERMIN
+ + (ntp_u_int32_t)jt.minute * SECSPERMIN
+ + (ntp_u_int32_t)jt.second
+ - SECSPERDAY; /* yearday is unity-based... */
+
+# if ISC_CHECK_INVARIANT
+ /*
+ * check that this computes properly: do a roundtrip! That's the only
+ * sensible test here, but it's a rather expensive invariant...
+ */
+ jt.yearday = 0;
+ jt.month = 1;
+ jt.monthday = 1;
+ jt.hour = 0;
+ jt.minute = 0;
+ jt.second = 0;
+ NTP_INVARIANT((ntp_u_int32_t)(caltontp(&jt) + delta) == (ntp_u_int32_t)ntp_time);
+# endif
- caljulian(ntp_time,&jt);
- jt.yearday = 1;
- jt.monthday = 1;
- jt.month = 1;
- jt.hour = jt.minute = jt.second = 0;
- return caltontp(&jt);
+ /* The NTP time stamps (l_fp) count seconds unsigned mod 2**32, so we
+ * have to calculate this in the proper way!
+ */
+ return (ntp_u_int32_t)(ntp_time - delta);
}