xref: /freebsd/contrib/ntp/libntp/caljulian.c (revision 2a4a1db342263067035ce69a4017c645da63455d)
1 /*
2  * caljulian - determine the Julian date from an NTP time.
3  */
4 #include <sys/types.h>
5 
6 #include "ntp_types.h"
7 #include "ntp_calendar.h"
8 #include "ntp_stdlib.h"
9 
10 /*
11  * calmonthtab - days-in-the-month table
12  */
13 static u_short calmonthtab[11] = {
14 	JAN,
15 	FEB,
16 	MAR,
17 	APR,
18 	MAY,
19 	JUN,
20 	JUL,
21 	AUG,
22 	SEP,
23 	OCT,
24 	NOV
25 };
26 
27 void
28 caljulian(
29 	u_long		  		ntptime,
30 	register struct calendar	*jt
31 	)
32 {
33 	u_long ntp_day;
34 	u_long minutes;
35 	/*
36 	 * Absolute, zero-adjusted Christian era day, starting from the
37 	 * mythical day 12/1/1 BC
38 	 */
39 	u_long acez_day;
40 
41 	u_long d400;				 /* Days into a Gregorian cycle */
42 	u_long d100;				 /* Days into a normal century */
43 	u_long d4;					 /* Days into a 4-year cycle */
44 	u_long n400;				 /* # of Gregorian cycles */
45 	u_long n100;				 /* # of normal centuries */
46 	u_long n4;					 /* # of 4-year cycles */
47 	u_long n1;					 /* # of years into a leap year */
48 						 /*   cycle */
49 
50 	/*
51 	 * Do the easy stuff first: take care of hh:mm:ss, ignoring leap
52 	 * seconds
53 	 */
54 	jt->second = (u_char)(ntptime % SECSPERMIN);
55 	minutes    = ntptime / SECSPERMIN;
56 	jt->minute = (u_char)(minutes % MINSPERHR);
57 	jt->hour   = (u_char)((minutes / MINSPERHR) % HRSPERDAY);
58 
59 	/*
60 	 * Find the day past 1900/01/01 00:00 UTC
61 	 */
62 	ntp_day = ntptime / SECSPERDAY;
63 	acez_day = DAY_NTP_STARTS + ntp_day - 1;
64 	n400	 = acez_day/GREGORIAN_CYCLE_DAYS;
65 	d400	 = acez_day%GREGORIAN_CYCLE_DAYS;
66 	n100	 = d400 / GREGORIAN_NORMAL_CENTURY_DAYS;
67 	d100	 = d400 % GREGORIAN_NORMAL_CENTURY_DAYS;
68 	n4		 = d100 / GREGORIAN_NORMAL_LEAP_CYCLE_DAYS;
69 	d4		 = d100 % GREGORIAN_NORMAL_LEAP_CYCLE_DAYS;
70 	n1		 = d4 / DAYSPERYEAR;
71 
72 	/*
73 	 * Calculate the year and year-of-day
74 	 */
75 	jt->yearday = (u_short)(1 + d4%DAYSPERYEAR);
76 	jt->year	= (u_short)(400*n400 + 100*n100 + n4*4 + n1);
77 
78 	if (n100 == 4 || n1 == 4)
79 	{
80 	/*
81 	 * If the cycle year ever comes out to 4, it must be December 31st
82 	 * of a leap year.
83 	 */
84 	jt->month	 = 12;
85 	jt->monthday = 31;
86 	jt->yearday  = 366;
87 	}
88 	else
89 	{
90 	/*
91 	 * Else, search forwards through the months to get the right month
92 	 * and date.
93 	 */
94 	int monthday;
95 
96 	jt->year++;
97 	monthday = jt->yearday;
98 
99 	for (jt->month=0;jt->month<11; jt->month++)
100 	{
101 		int t;
102 
103 		t = monthday - calmonthtab[jt->month];
104 		if (jt->month == 1 && is_leapyear(jt->year))
105 		t--;
106 
107 		if (t > 0)
108 		monthday = t;
109 		else
110 		break;
111 	}
112 	jt->month++;
113 	jt->monthday = monthday;
114 	}
115 }
116