xref: /freebsd/contrib/ntp/libntp/caljulian.c (revision ea906c4152774dff300bb26fbfc1e4188351c89a)
1c0b746e5SOllivier Robert /*
2c0b746e5SOllivier Robert  * caljulian - determine the Julian date from an NTP time.
3c0b746e5SOllivier Robert  */
4c0b746e5SOllivier Robert #include <sys/types.h>
5c0b746e5SOllivier Robert 
6c0b746e5SOllivier Robert #include "ntp_types.h"
7c0b746e5SOllivier Robert #include "ntp_calendar.h"
8c0b746e5SOllivier Robert #include "ntp_stdlib.h"
9ea906c41SOllivier Robert #include "ntp_fp.h"
10c0b746e5SOllivier Robert 
11ea906c41SOllivier Robert #if 0
12c0b746e5SOllivier Robert /*
13c0b746e5SOllivier Robert  * calmonthtab - days-in-the-month table
14c0b746e5SOllivier Robert  */
15c0b746e5SOllivier Robert static u_short calmonthtab[11] = {
16c0b746e5SOllivier Robert 	JAN,
17c0b746e5SOllivier Robert 	FEB,
18c0b746e5SOllivier Robert 	MAR,
19c0b746e5SOllivier Robert 	APR,
20c0b746e5SOllivier Robert 	MAY,
21c0b746e5SOllivier Robert 	JUN,
22c0b746e5SOllivier Robert 	JUL,
23c0b746e5SOllivier Robert 	AUG,
24c0b746e5SOllivier Robert 	SEP,
25c0b746e5SOllivier Robert 	OCT,
26c0b746e5SOllivier Robert 	NOV
27c0b746e5SOllivier Robert };
28c0b746e5SOllivier Robert 
29c0b746e5SOllivier Robert void
30c0b746e5SOllivier Robert caljulian(
31c0b746e5SOllivier Robert 	u_long		  		ntptime,
32c0b746e5SOllivier Robert 	register struct calendar	*jt
33c0b746e5SOllivier Robert 	)
34c0b746e5SOllivier Robert {
35c0b746e5SOllivier Robert 	u_long ntp_day;
36c0b746e5SOllivier Robert 	u_long minutes;
37c0b746e5SOllivier Robert 	/*
38c0b746e5SOllivier Robert 	 * Absolute, zero-adjusted Christian era day, starting from the
39c0b746e5SOllivier Robert 	 * mythical day 12/1/1 BC
40c0b746e5SOllivier Robert 	 */
41c0b746e5SOllivier Robert 	u_long acez_day;
42c0b746e5SOllivier Robert 
43c0b746e5SOllivier Robert 	u_long d400;				 /* Days into a Gregorian cycle */
44c0b746e5SOllivier Robert 	u_long d100;				 /* Days into a normal century */
45c0b746e5SOllivier Robert 	u_long d4;					 /* Days into a 4-year cycle */
46c0b746e5SOllivier Robert 	u_long n400;				 /* # of Gregorian cycles */
47c0b746e5SOllivier Robert 	u_long n100;				 /* # of normal centuries */
48c0b746e5SOllivier Robert 	u_long n4;					 /* # of 4-year cycles */
49c0b746e5SOllivier Robert 	u_long n1;					 /* # of years into a leap year */
50c0b746e5SOllivier Robert 						 /*   cycle */
51c0b746e5SOllivier Robert 
52c0b746e5SOllivier Robert 	/*
53c0b746e5SOllivier Robert 	 * Do the easy stuff first: take care of hh:mm:ss, ignoring leap
54c0b746e5SOllivier Robert 	 * seconds
55c0b746e5SOllivier Robert 	 */
56c0b746e5SOllivier Robert 	jt->second = (u_char)(ntptime % SECSPERMIN);
57c0b746e5SOllivier Robert 	minutes    = ntptime / SECSPERMIN;
58c0b746e5SOllivier Robert 	jt->minute = (u_char)(minutes % MINSPERHR);
59c0b746e5SOllivier Robert 	jt->hour   = (u_char)((minutes / MINSPERHR) % HRSPERDAY);
60c0b746e5SOllivier Robert 
61c0b746e5SOllivier Robert 	/*
62c0b746e5SOllivier Robert 	 * Find the day past 1900/01/01 00:00 UTC
63c0b746e5SOllivier Robert 	 */
64c0b746e5SOllivier Robert 	ntp_day = ntptime / SECSPERDAY;
65c0b746e5SOllivier Robert 	acez_day = DAY_NTP_STARTS + ntp_day - 1;
66c0b746e5SOllivier Robert 	n400	 = acez_day/GREGORIAN_CYCLE_DAYS;
67c0b746e5SOllivier Robert 	d400	 = acez_day%GREGORIAN_CYCLE_DAYS;
68c0b746e5SOllivier Robert 	n100	 = d400 / GREGORIAN_NORMAL_CENTURY_DAYS;
69c0b746e5SOllivier Robert 	d100	 = d400 % GREGORIAN_NORMAL_CENTURY_DAYS;
70c0b746e5SOllivier Robert 	n4		 = d100 / GREGORIAN_NORMAL_LEAP_CYCLE_DAYS;
71c0b746e5SOllivier Robert 	d4		 = d100 % GREGORIAN_NORMAL_LEAP_CYCLE_DAYS;
72c0b746e5SOllivier Robert 	n1		 = d4 / DAYSPERYEAR;
73c0b746e5SOllivier Robert 
74c0b746e5SOllivier Robert 	/*
75c0b746e5SOllivier Robert 	 * Calculate the year and year-of-day
76c0b746e5SOllivier Robert 	 */
77c0b746e5SOllivier Robert 	jt->yearday = (u_short)(1 + d4%DAYSPERYEAR);
78c0b746e5SOllivier Robert 	jt->year	= (u_short)(400*n400 + 100*n100 + n4*4 + n1);
79c0b746e5SOllivier Robert 
80c0b746e5SOllivier Robert 	if (n100 == 4 || n1 == 4)
81c0b746e5SOllivier Robert 	{
82c0b746e5SOllivier Robert 	/*
83c0b746e5SOllivier Robert 	 * If the cycle year ever comes out to 4, it must be December 31st
84c0b746e5SOllivier Robert 	 * of a leap year.
85c0b746e5SOllivier Robert 	 */
86c0b746e5SOllivier Robert 	jt->month	 = 12;
87c0b746e5SOllivier Robert 	jt->monthday = 31;
88c0b746e5SOllivier Robert 	jt->yearday  = 366;
89c0b746e5SOllivier Robert 	}
90c0b746e5SOllivier Robert 	else
91c0b746e5SOllivier Robert 	{
92c0b746e5SOllivier Robert 	/*
93c0b746e5SOllivier Robert 	 * Else, search forwards through the months to get the right month
94c0b746e5SOllivier Robert 	 * and date.
95c0b746e5SOllivier Robert 	 */
96c0b746e5SOllivier Robert 	int monthday;
97c0b746e5SOllivier Robert 
98c0b746e5SOllivier Robert 	jt->year++;
99c0b746e5SOllivier Robert 	monthday = jt->yearday;
100c0b746e5SOllivier Robert 
101c0b746e5SOllivier Robert 	for (jt->month=0;jt->month<11; jt->month++)
102c0b746e5SOllivier Robert 	{
103c0b746e5SOllivier Robert 		int t;
104c0b746e5SOllivier Robert 
105c0b746e5SOllivier Robert 		t = monthday - calmonthtab[jt->month];
106c0b746e5SOllivier Robert 		if (jt->month == 1 && is_leapyear(jt->year))
107c0b746e5SOllivier Robert 		t--;
108c0b746e5SOllivier Robert 
109c0b746e5SOllivier Robert 		if (t > 0)
110c0b746e5SOllivier Robert 		monthday = t;
111c0b746e5SOllivier Robert 		else
112c0b746e5SOllivier Robert 		break;
113c0b746e5SOllivier Robert 	}
114c0b746e5SOllivier Robert 	jt->month++;
1159c2daa00SOllivier Robert 	jt->monthday = (u_char) monthday;
116c0b746e5SOllivier Robert 	}
117c0b746e5SOllivier Robert }
118ea906c41SOllivier Robert #else
119ea906c41SOllivier Robert 
120ea906c41SOllivier Robert /* Updated 2003-12-30 TMa
121ea906c41SOllivier Robert 
122ea906c41SOllivier Robert    Uses common code with the *prettydate functions to convert an ntp
123ea906c41SOllivier Robert    seconds count into a calendar date.
124ea906c41SOllivier Robert    Will handle ntp epoch wraparound as long as the underlying os/library
125ea906c41SOllivier Robert    does so for the unix epoch, i.e. works after 2038.
126ea906c41SOllivier Robert */
127ea906c41SOllivier Robert 
128ea906c41SOllivier Robert void
129ea906c41SOllivier Robert caljulian(
130ea906c41SOllivier Robert 	u_long		  		ntptime,
131ea906c41SOllivier Robert 	register struct calendar	*jt
132ea906c41SOllivier Robert 	)
133ea906c41SOllivier Robert {
134ea906c41SOllivier Robert 	struct tm *tm;
135ea906c41SOllivier Robert 
136ea906c41SOllivier Robert 	tm = ntp2unix_tm(ntptime, 0);
137ea906c41SOllivier Robert 
138ea906c41SOllivier Robert 	jt->hour = (u_char) tm->tm_hour;
139ea906c41SOllivier Robert 	jt->minute = (u_char) tm->tm_min;
140ea906c41SOllivier Robert 	jt->month = (u_char) (tm->tm_mon + 1);
141ea906c41SOllivier Robert 	jt->monthday = (u_char) tm->tm_mday;
142ea906c41SOllivier Robert 	jt->second = (u_char) tm->tm_sec;
143ea906c41SOllivier Robert 	jt->year = (u_short) (tm->tm_year + 1900);
144ea906c41SOllivier Robert 	jt->yearday = (u_short) (tm->tm_yday + 1);  /* Assumes tm_yday starts with day 0! */
145ea906c41SOllivier Robert }
146ea906c41SOllivier Robert #endif
147