Home | History | Annotate | Line # | Download | only in libntp
      1 /*	$NetBSD: caltontp.c,v 1.7 2024/08/18 20:47:13 christos Exp $	*/
      2 
      3 /*
      4  * caltontp - convert a date to an NTP time
      5  */
      6 #include <config.h>
      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 #include "ntp_unixtime.h"
     14 
     15 /*
     16  * Juergen Perlinger, 2008-11-12
     17  * Add support for full calendar calculations. If the day-of-year is provided
     18  * (that is, not zero) it will be used instead of month and day-of-month;
     19  * otherwise a full turn through the calendar calculations will be taken.
     20  *
     21  * I know that Harlan Stenn likes to see assertions in production code, and I
     22  * agree in general. But here we set 'errno' and try to do our best instead.
     23  * Also note that the bounds check is a bit sloppy: It permits off-by-one
     24  * on the input quantities. That permits some simple/naive adjustments to
     25  * be made before calling this function.
     26  *
     27  * Apart from that the calendar is perfectly capable of dealing with
     28  * off-scale input values!
     29  *
     30  * BTW: A total roundtrip using 'caljulian' would be a quite shaky thing:
     31  * Because of the truncation of the NTP time stamp to 32 bits and the epoch
     32  * unfolding around the current time done by 'caljulian' the roundtrip does
     33  * *not* necessarily reproduce the input, especially if the time spec is more
     34  * than 68 years off from the current time...
     35  */
     36 
     37 uint32_t
     38 caltontp(
     39 	const struct calendar *jt
     40 	)
     41 {
     42 	int32_t eraday;	/* CE Rata Die number	*/
     43 	vint64  ntptime;/* resulting NTP time	*/
     44 
     45 	if (NULL == jt) {
     46 		errno = EINVAL;
     47 		return 0;
     48 	}
     49 
     50 	if (   (jt->month > 13)	/* permit month 0..13! */
     51 	    || (jt->monthday > 32)
     52 	    || (jt->yearday > 366)
     53 	    || (jt->hour > 24)
     54 	    || (jt->minute > MINSPERHR)
     55 	    || (jt->second > SECSPERMIN))
     56 		errno = ERANGE;
     57 
     58 	/*
     59 	 * First convert the date to he corresponding RataDie
     60 	 * number. If yearday is not zero, assume that it contains a
     61 	 * useable value and avoid all calculations involving month
     62 	 * and day-of-month. Do a full evaluation otherwise.
     63 	 */
     64 	if (jt->yearday)
     65 		eraday = ntpcal_year_to_ystart(jt->year)
     66 		       + jt->yearday - 1;
     67 	else
     68 		eraday = ntpcal_date_to_rd(jt);
     69 
     70 	ntptime = ntpcal_dayjoin(eraday - DAY_NTP_STARTS,
     71 				 ntpcal_etime_to_seconds(jt->hour, jt->minute,
     72 							 jt->second));
     73 	return ntptime.d_s.lo;
     74 }
     75