1 /*
2  * ntp_calendar.h - definitions for the calendar time-of-day routine
3  */
4 #ifndef GUARD_NTP_CALENDAR_H
5 #define GUARD_NTP_CALENDAR_H
6 
7 #include <time.h>
8 
9 #include "ntp_types.h"
10 
11 /* gregorian calendar date */
12 struct calendar {
13 	uint16_t year;		/* year (A.D.) */
14 	uint16_t yearday;	/* day of year, 1 = January 1 */
15 	uint8_t  month;		/* month, 1 = January */
16 	uint8_t  monthday;	/* day of month */
17 	uint8_t  hour;		/* hour of day, midnight = 0 */
18 	uint8_t  minute;	/* minute of hour */
19 	uint8_t  second;	/* second of minute */
20 	uint8_t  weekday;	/* 0..7, 0=Sunday */
21 };
22 
23 /* general split representation */
24 typedef struct {
25 	int32_t hi;
26 	int32_t lo;
27 } ntpcal_split;
28 
29 typedef time_t (*systime_func_ptr)(time_t *);
30 
31 /*
32  * We deal in a 4 year cycle starting at March 1, 1900.	 We assume
33  * we will only want to deal with dates since then, and not to exceed
34  * the rollover day in 2036.
35  */
36 #define	SECSPERMIN	(60)			/* seconds per minute */
37 #define	MINSPERHR	(60)			/* minutes per hour */
38 #define	HRSPERDAY	(24)			/* hours per day */
39 #define	DAYSPERWEEK	(7)			/* days per week */
40 #define	DAYSPERYEAR	(365)			/* days per year */
41 
42 #define	SECSPERHR	(SECSPERMIN * MINSPERHR)
43 #define	SECSPERDAY	(SECSPERHR * HRSPERDAY)
44 #define	SECSPERWEEK	(DAYSPERWEEK * SECSPERDAY)
45 #define	SECSPERYEAR	(365 * SECSPERDAY)	/* regular year */
46 #define	SECSPERLEAPYEAR	(366 * SECSPERDAY)	/* leap year */
47 #define	SECSPERAVGYEAR	31556952	/* mean year length over 400yrs */
48 
49 /*
50  * Get the build date & time in UTC.  This depends on the BUILD_EPOCH
51  * which is fixed at configure time.
52  */
53 extern bool
54 ntpcal_get_build_date(struct calendar * /* jd */);
55 
56 /*
57  * Convert a timestamp in NTP scale to a time_t value in the UN*X
58  * scale with proper epoch unfolding around a given pivot or the
59  * current system time.
60  */
61 extern time64_t
62 ntpcal_ntp_to_time(uint32_t /* ntp */, time_t /* pivot */);
63 
64 /*
65  * Convert a timestamp in NTP scale to a 64bit seconds value in the NTP
66  * scale with proper epoch unfolding around a given pivot or the current
67  * system time.
68  * Note: The pivot must be given in UN*X time scale!
69  */
70 extern time64_t
71 ntpcal_ntp_to_ntp(uint32_t /* ntp */, time_t /* pivot */);
72 
73 /*
74  * Split a time stamp in seconds into elapsed days and elapsed seconds
75  * since midnight.
76  */
77 extern ntpcal_split
78 ntpcal_daysplit(const time64_t);
79 
80 /*
81  * Merge a number of days and a number of seconds into seconds,
82  * expressed in 64 bits to avoid overflow.
83  */
84 extern time64_t
85 ntpcal_dayjoin(int32_t /* days */, int32_t /* seconds */) __attribute__((const));
86 
87 /*
88  * Convert elapsed years in Era into elapsed days in Era.
89  */
90 extern int32_t
91 ntpcal_days_in_years(int32_t /* years */) __attribute__((const));
92 
93 #define days_per_year(x)	((x) % 4 ? 365 : ((x % 400) ? ((x % 100) ? 366 : 365) : 366))
94 
95 /*
96  * Convert ELAPSED years/months/days of gregorian calendar to elapsed
97  * days in Gregorian epoch. No range checks done here!
98  */
99 extern int32_t
100 ntpcal_edate_to_eradays(int32_t /* years */, int32_t /* months */, int32_t /* mdays */);
101 
102 /*
103  * Convert a time spec to seconds. No range checks done here!
104  */
105 extern int32_t
106 ntpcal_etime_to_seconds(int32_t /* hours */, int32_t /* minutes */,
107                         int32_t /* seconds */) __attribute__((const));
108 
109 /*
110  * Convert the date part of a 'struct tm' (that is, year, month,
111  * day-of-month) into the RataDie of that day.
112  */
113 extern int32_t
114 ntpcal_tm_to_rd(const struct tm * /* utm */);
115 
116 /*
117  * Convert the date part of a 'struct calendar' (that is, year, month,
118  * day-of-month) into the RataDie of that day.
119  */
120 extern int32_t
121 ntpcal_date_to_rd(const struct calendar * /* jt */);
122 
123 /*
124  * Given the number of elapsed days in the calendar era, split this
125  * number into the number of elapsed years in 'res.quot' and the
126  * number of elapsed days of that year in 'res.rem'.
127  *
128  * if 'isleapyear' is not NULL, it will receive an integer that is 0
129  * for regular years and a non-zero value for leap years.
130  */
131 extern ntpcal_split
132 ntpcal_split_eradays(int32_t /* days */, int32_t * /* isleapyear */);
133 
134 /*
135  * Given a number of elapsed days in a year and a leap year indicator,
136  * split the number of elapsed days into the number of elapsed months
137  * in 'res.quot' and the number of elapsed days of that month in
138  * 'res.rem'.
139  */
140 extern ntpcal_split
141 ntpcal_split_yeardays(int32_t /* eyd */, bool /* isleapyear */);
142 
143 /*
144  * Convert a RataDie number into the date part of a 'struct
145  * calendar'. Return 0 if the year is regular year, 1 if the year is
146  * a leap year, -1 if the calculation overflowed.
147  */
148 extern int
149 ntpcal_rd_to_date(struct calendar * /* jt */, int32_t /* rd */);
150 
151 /*
152  * Take a value of seconds since midnight and split it into hhmmss in
153  * a 'struct calendar'. Return excessive days.
154  */
155 /* used by ntpd/refclock_nmea.c */
156 extern int32_t
157 ntpcal_daysec_to_date(struct calendar * /* jt */, int32_t /* secs */);
158 
159 /*
160  * Take the time part of a 'struct calendar' and return the seconds
161  * since midnight.
162  */
163 /* used by ntpd/refclock_nmea.c */
164 extern int32_t
165 ntpcal_date_to_daysec(const struct calendar *);
166 
167 extern int32_t
168 ntpcal_tm_to_daysec(const struct tm * /* utm */);
169 
170 extern int
171 ntpcal_time_to_date(struct calendar * /* jd */, const time64_t /* ts */);
172 
173 extern int32_t
174 ntpcal_periodic_extend(int32_t /* pivot */, int32_t /* value */,
175 		       int32_t /* cycle */) __attribute__((const));
176 
177 extern int
178 ntpcal_ntp64_to_date(struct calendar * /* jd */, const time64_t /* ntp */);
179 
180 extern int
181 ntpcal_ntp_to_date(struct calendar * /* jd */,	uint32_t /* ntp */,
182 		   time_t /* pivot */);
183 
184 extern time_t
185 ntpcal_date_to_time(const struct calendar * /* jd */);
186 
187 
188 /*
189  * Additional support stuff for Ed Rheingold's calendrical calculations
190  */
191 
192 /*
193  * Start day of NTP time as days past the imaginary date 12/1/1 BC.
194  * (This is the beginning of the Christian Era, or BCE.)
195  */
196 #define	DAY_NTP_STARTS 693596
197 
198 /*
199  * Start day of the UNIX epoch. This is the Rata Die of 1970-01-01.
200  */
201 #define DAY_UNIX_STARTS 719163
202 
203 /*
204  * Difference between UN*X and NTP epoch (25567).
205  */
206 #define NTP_TO_UNIX_DAYS (DAY_UNIX_STARTS - DAY_NTP_STARTS)
207 
208 /*
209  * Days in a normal 4 year leap year calendar cycle (1461).
210  */
211 #define	GREGORIAN_NORMAL_LEAP_CYCLE_DAYS	(3 * 365 + 366)
212 
213 /*
214  * Days in a normal 100 year leap year calendar (36524).  We lose a
215  * leap day in years evenly divisible by 100 but not by 400.
216  */
217 #define	GREGORIAN_NORMAL_CENTURY_DAYS	\
218 			(25 * GREGORIAN_NORMAL_LEAP_CYCLE_DAYS - 1)
219 
220 /*
221  * The Gregorian calendar is based on a 400 year cycle. This is the
222  * number of days in each cycle (146097).  We gain a leap day in years
223  * divisible by 400 relative to the "normal" century.
224  */
225 #define	GREGORIAN_CYCLE_DAYS (4 * GREGORIAN_NORMAL_CENTURY_DAYS + 1)
226 
227 /*
228  * Number of weeks in 400 years (20871).
229  */
230 #define	GREGORIAN_CYCLE_WEEKS (GREGORIAN_CYCLE_DAYS / 7)
231 
232 #define	is_leapyear(y)	(!((y) % 4) && !(!((y) % 100) && (y) % 400))
233 
234 /*
235  * Time of day conversion constant.  NTP's time scale starts in 1900,
236  * Unix in 1970.  The value is 1970 - 1900 in seconds, 0x83aa7e80 or
237  * 2208988800.  This is larger than 32-bit INT_MAX, so unsigned
238  * type is forced.
239  */
240 #define	JAN_1970 ((unsigned int)NTP_TO_UNIX_DAYS * (unsigned int)SECSPERDAY)
241 
242 #endif
243