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