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