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