xref: /freebsd/contrib/ntp/include/ntp_calendar.h (revision 788ca347b816afd83b2885e0c79aeeb88649b2ab)
1 /*
2  * ntp_calendar.h - definitions for the calendar time-of-day routine
3  */
4 #ifndef NTP_CALENDAR_H
5 #define 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 /* ISO week calendar date */
24 struct isodate {
25 	uint16_t year;		/* year (A.D.) */
26 	uint8_t	 week;		/* 1..53, week in year */
27 	uint8_t	 weekday;	/* 1..7, 1=Monday */
28 	uint8_t	 hour;		/* hour of day, midnight = 0 */
29 	uint8_t	 minute;	/* minute of hour */
30 	uint8_t	 second;	/* second of minute */
31 };
32 
33 /* general split representation */
34 typedef struct {
35 	int32_t hi;
36 	int32_t lo;
37 } ntpcal_split;
38 
39 typedef time_t (*systime_func_ptr)(time_t *);
40 
41 /*
42  * set the function for getting the system time. This is mostly used for
43  * unit testing to provide a fixed / shifted time stamp. Setting the
44  * value to NULL restores the original function, that is, 'time()',
45  * which is also the automatic default.
46  */
47 extern systime_func_ptr ntpcal_set_timefunc(systime_func_ptr);
48 
49 /*
50  * days-of-week
51  */
52 #define CAL_SUNDAY	0
53 #define CAL_MONDAY	1
54 #define CAL_TUESDAY	2
55 #define CAL_WEDNESDAY	3
56 #define CAL_THURSDAY	4
57 #define CAL_FRIDAY	5
58 #define CAL_SATURDAY	6
59 #define CAL_SUNDAY7	7	/* also sunday */
60 
61 /*
62  * Days in each month.	30 days hath September...
63  */
64 #define	JAN	31
65 #define	FEB	28
66 #define	FEBLEAP	29
67 #define	MAR	31
68 #define	APR	30
69 #define	MAY	31
70 #define	JUN	30
71 #define	JUL	31
72 #define	AUG	31
73 #define	SEP	30
74 #define	OCT	31
75 #define	NOV	30
76 #define	DEC	31
77 
78 /*
79  * We deal in a 4 year cycle starting at March 1, 1900.	 We assume
80  * we will only want to deal with dates since then, and not to exceed
81  * the rollover day in 2036.
82  */
83 #define	SECSPERMIN	(60)			/* seconds per minute */
84 #define	MINSPERHR	(60)			/* minutes per hour */
85 #define	HRSPERDAY	(24)			/* hours per day */
86 #define	DAYSPERYEAR	(365)			/* days per year */
87 
88 #define	SECSPERHR	(SECSPERMIN * MINSPERHR)
89 #define	SECSPERDAY	(SECSPERHR * HRSPERDAY)
90 #define	SECSPERYEAR	(365 * SECSPERDAY)	/* regular year */
91 #define	SECSPERLEAPYEAR	(366 * SECSPERDAY)	/* leap year */
92 #define SECSPERAVGYEAR	31556952		/* mean year length over 400yrs */
93 
94 /*
95  * Gross hacks.	 I have illicit knowlege that there won't be overflows
96  * here, the compiler often can't tell this.
97  */
98 #define	TIMES60(val)	((((val)<<4) - (val))<<2)	/* *(16 - 1) * 4 */
99 #define	TIMES24(val)	(((val)<<4) + ((val)<<3))	/* *16 + *8 */
100 #define	TIMES7(val)	(((val)<<3) - (val))		/* *8  - *1 */
101 #define	TIMESDPERC(val)	(((val)<<10) + ((val)<<8) \
102 			+ ((val)<<7) + ((val)<<5) \
103 			+ ((val)<<4) + ((val)<<2) + (val))	/* *big* hack */
104 
105 
106 extern	const char * const months[12];
107 extern	const char * const daynames[7];
108 
109 extern	void	 caljulian	(uint32_t, struct calendar *);
110 extern	uint32_t caltontp	(const struct calendar *);
111 
112 /*
113  * Convert between 'time_t' and 'vint64'
114  */
115 extern vint64 time_to_vint64(const time_t *);
116 extern time_t vint64_to_time(const vint64 *);
117 
118 /*
119  * Get the build date & time. ATTENTION: The time zone is not specified!
120  * This depends entirely on the C compilers' capabilities to properly
121  * expand the '__TIME__' and '__DATE__' macros, as required by the C
122  * standard.
123  */
124 extern int
125 ntpcal_get_build_date(struct calendar * /* jd */);
126 
127 /*
128  * Convert a timestamp in NTP scale to a time_t value in the UN*X
129  * scale with proper epoch unfolding around a given pivot or the
130  * current system time.
131  */
132 extern vint64
133 ntpcal_ntp_to_time(uint32_t /* ntp */, const time_t * /* pivot */);
134 
135 /*
136  * Convert a timestamp in NTP scale to a 64bit seconds value in the NTP
137  * scale with proper epoch unfolding around a given pivot or the current
138  * system time.
139  * Note: The pivot must be given in UN*X time scale!
140  */
141 extern vint64
142 ntpcal_ntp_to_ntp(uint32_t /* ntp */, const time_t * /* pivot */);
143 
144 /*
145  * Split a time stamp in seconds into elapsed days and elapsed seconds
146  * since midnight.
147  */
148 extern ntpcal_split
149 ntpcal_daysplit(const vint64 *);
150 
151 /*
152  * Merge a number of days and a number of seconds into seconds,
153  * expressed in 64 bits to avoid overflow.
154  */
155 extern vint64
156 ntpcal_dayjoin(int32_t /* days */, int32_t /* seconds */);
157 
158 /*
159  * Convert elapsed years in Era into elapsed days in Era.
160  */
161 extern int32_t
162 ntpcal_days_in_years(int32_t /* years */);
163 
164 /*
165  * Convert a number of elapsed month in a year into elapsed days
166  * in year.
167  *
168  * The month will be normalized, and 'res.hi' will contain the
169  * excessive years that must be considered when converting the years,
170  * while 'res.lo' will contain the days since start of the
171  * year. (Expect the resulting days to be negative, with a positive
172  * excess! But then, we need no leap year flag, either...)
173  */
174 extern ntpcal_split
175 ntpcal_days_in_months(int32_t /* months */);
176 
177 /*
178  * Convert ELAPSED years/months/days of gregorian calendar to elapsed
179  * days in Gregorian epoch. No range checks done here!
180  */
181 extern int32_t
182 ntpcal_edate_to_eradays(int32_t /* years */, int32_t /* months */, int32_t /* mdays */);
183 
184 /*
185  * Convert a time spec to seconds. No range checks done here!
186  */
187 extern int32_t
188 ntpcal_etime_to_seconds(int32_t /* hours */, int32_t /* minutes */, int32_t /* seconds */);
189 
190 /*
191  * Convert ELAPSED years/months/days of gregorian calendar to elapsed
192  * days in year.
193  *
194  * Note: This will give the true difference to the start of the given year,
195  * even if months & days are off-scale.
196  */
197 extern int32_t
198 ntpcal_edate_to_yeardays(int32_t /* years */, int32_t /* months */, int32_t /* mdays */);
199 
200 /*
201  * Convert the date part of a 'struct tm' (that is, year, month,
202  * day-of-month) into the RataDie of that day.
203  */
204 extern int32_t
205 ntpcal_tm_to_rd(const struct tm * /* utm */);
206 
207 /*
208  * Convert the date part of a 'struct calendar' (that is, year, month,
209  * day-of-month) into the RataDie of that day.
210  */
211 extern int32_t
212 ntpcal_date_to_rd(const struct calendar * /* jt */);
213 
214 /*
215  * Given the number of elapsed days in the calendar era, split this
216  * number into the number of elapsed years in 'res.quot' and the
217  * number of elapsed days of that year in 'res.rem'.
218  *
219  * if 'isleapyear' is not NULL, it will receive an integer that is 0
220  * for regular years and a non-zero value for leap years.
221  */
222 extern ntpcal_split
223 ntpcal_split_eradays(int32_t /* days */, int/*BOOL*/ * /* isleapyear */);
224 
225 /*
226  * Given a number of elapsed days in a year and a leap year indicator,
227  * split the number of elapsed days into the number of elapsed months
228  * in 'res.quot' and the number of elapsed days of that month in
229  * 'res.rem'.
230  */
231 extern ntpcal_split
232 ntpcal_split_yeardays(int32_t /* eyd */, int/*BOOL*/ /* isleapyear */);
233 
234 /*
235  * Convert a RataDie number into the date part of a 'struct
236  * calendar'. Return 0 if the year is regular year, !0 if the year is
237  * a leap year.
238  */
239 extern int/*BOOL*/
240 ntpcal_rd_to_date(struct calendar * /* jt */, int32_t /* rd */);
241 
242 /*
243  * Convert a RataDie number into the date part of a 'struct
244  * tm'. Return 0 if the year is regular year, !0 if the year is a leap
245  * year.
246  */
247 extern int/*BOOL*/
248 ntpcal_rd_to_tm(struct tm * /* utm */, int32_t /* rd */);
249 
250 /*
251  * Take a value of seconds since midnight and split it into hhmmss in
252  * a 'struct calendar'. Return excessive days.
253  */
254 extern int32_t
255 ntpcal_daysec_to_date(struct calendar * /* jt */, int32_t /* secs */);
256 
257 /*
258  * Take the time part of a 'struct calendar' and return the seconds
259  * since midnight.
260  */
261 extern int32_t
262 ntpcal_date_to_daysec(const struct calendar *);
263 
264 /*
265  * Take a value of seconds since midnight and split it into hhmmss in
266  * a 'struct tm'. Return excessive days.
267  */
268 extern int32_t
269 ntpcal_daysec_to_tm(struct tm * /* utm */, int32_t /* secs */);
270 
271 extern int32_t
272 ntpcal_tm_to_daysec(const struct tm * /* utm */);
273 
274 /*
275  * convert a year number to rata die of year start
276  */
277 extern int32_t
278 ntpcal_year_to_ystart(int32_t /* year */);
279 
280 /*
281  * For a given RataDie, get the RataDie of the associated year start,
282  * that is, the RataDie of the last January,1st on or before that day.
283  */
284 extern int32_t
285 ntpcal_rd_to_ystart(int32_t /* rd */);
286 
287 /*
288  * convert a RataDie to the RataDie of start of the calendar month.
289  */
290 extern int32_t
291 ntpcal_rd_to_mstart(int32_t /* year */);
292 
293 
294 extern int
295 ntpcal_daysplit_to_date(struct calendar * /* jt */,
296 			const ntpcal_split * /* ds */, int32_t /* dof */);
297 
298 extern int
299 ntpcal_daysplit_to_tm(struct tm * /* utm */, const ntpcal_split * /* ds */,
300 		      int32_t /* dof */);
301 
302 extern int
303 ntpcal_time_to_date(struct calendar * /* jd */, const vint64 * /* ts */);
304 
305 extern int32_t
306 ntpcal_periodic_extend(int32_t /* pivot */, int32_t /* value */,
307 		       int32_t /* cycle */);
308 
309 extern int
310 ntpcal_ntp64_to_date(struct calendar * /* jd */, const vint64 * /* ntp */);
311 
312 extern int
313 ntpcal_ntp_to_date(struct calendar * /* jd */,	uint32_t /* ntp */,
314 		   const time_t * /* pivot */);
315 
316 extern vint64
317 ntpcal_date_to_ntp64(const struct calendar * /* jd */);
318 
319 extern uint32_t
320 ntpcal_date_to_ntp(const struct calendar * /* jd */);
321 
322 extern time_t
323 ntpcal_date_to_time(const struct calendar * /* jd */);
324 
325 /*
326  * ISO week-calendar conversions
327  */
328 extern int32_t
329 isocal_weeks_in_years(int32_t  /* years */);
330 
331 extern ntpcal_split
332 isocal_split_eraweeks(int32_t /* weeks */);
333 
334 extern int
335 isocal_ntp64_to_date(struct isodate * /* id */, const vint64 * /* ntp */);
336 
337 extern int
338 isocal_ntp_to_date(struct isodate * /* id */, uint32_t /* ntp */,
339 		   const time_t * /* pivot */);
340 
341 extern vint64
342 isocal_date_to_ntp64(const struct isodate * /* id */);
343 
344 extern uint32_t
345 isocal_date_to_ntp(const struct isodate * /* id */);
346 
347 
348 /*
349  * day-of-week calculations
350  *
351  * Given a RataDie and a day-of-week, calculate a RDN that is reater-than,
352  * greater-or equal, closest, less-or-equal or less-than the given RDN
353  * and denotes the given day-of-week
354  */
355 extern int32_t
356 ntpcal_weekday_gt(int32_t  /* rdn */, int32_t /* dow */);
357 
358 extern int32_t
359 ntpcal_weekday_ge(int32_t /* rdn */, int32_t /* dow */);
360 
361 extern int32_t
362 ntpcal_weekday_close(int32_t /* rdn */, int32_t  /* dow */);
363 
364 extern int32_t
365 ntpcal_weekday_le(int32_t /* rdn */, int32_t /* dow */);
366 
367 extern int32_t
368 ntpcal_weekday_lt(int32_t /* rdn */, int32_t /* dow */);
369 
370 /*
371  * Additional support stuff for Ed Rheingold's calendrical calculations
372  */
373 
374 /*
375  * Start day of NTP time as days past the imaginary date 12/1/1 BC.
376  * (This is the beginning of the Christian Era, or BCE.)
377  */
378 #define	DAY_NTP_STARTS 693596
379 
380 /*
381  * Start day of the UNIX epoch. This is the Rata Die of 1970-01-01.
382  */
383 #define DAY_UNIX_STARTS 719163
384 
385 /*
386  * Difference between UN*X and NTP epoch (25567).
387  */
388 #define NTP_TO_UNIX_DAYS (DAY_UNIX_STARTS - DAY_NTP_STARTS)
389 
390 /*
391  * Days in a normal 4 year leap year calendar cycle (1461).
392  */
393 #define	GREGORIAN_NORMAL_LEAP_CYCLE_DAYS	(3 * 365 + 366)
394 
395 /*
396  * Days in a normal 100 year leap year calendar (36524).  We lose a
397  * leap day in years evenly divisible by 100 but not by 400.
398  */
399 #define	GREGORIAN_NORMAL_CENTURY_DAYS	\
400 			(25 * GREGORIAN_NORMAL_LEAP_CYCLE_DAYS - 1)
401 
402 /*
403  * The Gregorian calendar is based on a 400 year cycle. This is the
404  * number of days in each cycle (146097).  We gain a leap day in years
405  * divisible by 400 relative to the "normal" century.
406  */
407 #define	GREGORIAN_CYCLE_DAYS (4 * GREGORIAN_NORMAL_CENTURY_DAYS + 1)
408 
409 /*
410  * Number of weeks in 400 years (20871).
411  */
412 #define	GREGORIAN_CYCLE_WEEKS (GREGORIAN_CYCLE_DAYS / 7)
413 
414 #define	is_leapyear(y)	(!((y) % 4) && !(!((y) % 100) && (y) % 400))
415 
416 #endif
417