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