source: Sophya/trunk/SophyaExt/XephemAstroLib/mjd.c@ 1465

Last change on this file since 1465 was 1457, checked in by cmv, 24 years ago

import de la partie libastro de Xephem cmv+rz 10/4/2001

File size: 5.0 KB
Line 
1/* functions to manipulate the modified-julian-date used throughout xephem. */
2
3#include <stdio.h>
4#include <math.h>
5
6#include "P_.h"
7#include "astro.h"
8
9/* given a date in months, mn, days, dy, years, yr,
10 * return the modified Julian date (number of days elapsed since 1900 jan 0.5),
11 * *mjd.
12 */
13void
14cal_mjd (mn, dy, yr, mjd)
15int mn, yr;
16double dy;
17double *mjd;
18{
19 static double last_mjd, last_dy;
20 static int last_mn, last_yr;
21 int b, d, m, y;
22 long c;
23
24 if (mn == last_mn && yr == last_yr && dy == last_dy) {
25 *mjd = last_mjd;
26 return;
27 }
28
29 m = mn;
30 y = (yr < 0) ? yr + 1 : yr;
31 if (mn < 3) {
32 m += 12;
33 y -= 1;
34 }
35
36 if (yr < 1582 || (yr == 1582 && (mn < 10 || (mn == 10 && dy < 15))))
37 b = 0;
38 else {
39 int a;
40 a = y/100;
41 b = 2 - a + a/4;
42 }
43
44 if (y < 0)
45 c = (long)((365.25*y) - 0.75) - 694025L;
46 else
47 c = (long)(365.25*y) - 694025L;
48
49 d = (int)(30.6001*(m+1));
50
51 *mjd = b + c + d + dy - 0.5;
52
53 last_mn = mn;
54 last_dy = dy;
55 last_yr = yr;
56 last_mjd = *mjd;
57}
58
59/* given the modified Julian date (number of days elapsed since 1900 jan 0.5,),
60 * mjd, return the calendar date in months, *mn, days, *dy, and years, *yr.
61 */
62void
63mjd_cal (mjd, mn, dy, yr)
64double mjd;
65int *mn, *yr;
66double *dy;
67{
68 static double last_mjd, last_dy;
69 static int last_mn, last_yr;
70 double d, f;
71 double i, a, b, ce, g;
72
73 /* we get called with 0 quite a bit from unused epoch fields.
74 * 0 is noon the last day of 1899.
75 */
76 if (mjd == 0.0) {
77 *mn = 12;
78 *dy = 31.5;
79 *yr = 1899;
80 return;
81 }
82
83 if (mjd == last_mjd) {
84 *mn = last_mn;
85 *yr = last_yr;
86 *dy = last_dy;
87 return;
88 }
89
90 d = mjd + 0.5;
91 i = floor(d);
92 f = d-i;
93 if (f == 1) {
94 f = 0;
95 i += 1;
96 }
97
98 if (i > -115860.0) {
99 a = floor((i/36524.25)+.99835726)+14;
100 i += 1 + a - floor(a/4.0);
101 }
102
103 b = floor((i/365.25)+.802601);
104 ce = i - floor((365.25*b)+.750001)+416;
105 g = floor(ce/30.6001);
106 *mn = (int)(g - 1);
107 *dy = ce - floor(30.6001*g)+f;
108 *yr = (int)(b + 1899);
109
110 if (g > 13.5)
111 *mn = (int)(g - 13);
112 if (*mn < 2.5)
113 *yr = (int)(b + 1900);
114 if (*yr < 1)
115 *yr -= 1;
116
117 last_mn = *mn;
118 last_dy = *dy;
119 last_yr = *yr;
120 last_mjd = mjd;
121}
122
123/* given an mjd, set *dow to 0..6 according to which day of the week it falls
124 * on (0=sunday).
125 * return 0 if ok else -1 if can't figure it out.
126 */
127int
128mjd_dow (mjd, dow)
129double mjd;
130int *dow;
131{
132 /* cal_mjd() uses Gregorian dates on or after Oct 15, 1582.
133 * (Pope Gregory XIII dropped 10 days, Oct 5..14, and improved the leap-
134 * year algorithm). however, Great Britian and the colonies did not
135 * adopt it until Sept 14, 1752 (they dropped 11 days, Sept 3-13,
136 * due to additional accumulated error). leap years before 1752 thus
137 * can not easily be accounted for from the cal_mjd() number...
138 */
139 if (mjd < -53798.5) {
140 /* pre sept 14, 1752 too hard to correct |:-S */
141 return (-1);
142 }
143 *dow = ((long)floor(mjd-.5) + 1) % 7;/* 1/1/1900 (mjd 0.5) is a Monday*/
144 if (*dow < 0)
145 *dow += 7;
146 return (0);
147}
148
149/* given a year, return whether it is a leap year */
150int
151isleapyear (y)
152int y;
153{
154 return ((y%4==0 && y%100!=0) || y%400==0);
155}
156
157/* given a mjd, return the the number of days in the month. */
158void
159mjd_dpm (mjd, ndays)
160double mjd;
161int *ndays;
162{
163 static short dpm[] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
164 int m, y;
165 double d;
166
167 mjd_cal (mjd, &m, &d, &y);
168 *ndays = (m==2 && isleapyear(y)) ? 29 : dpm[m-1];
169}
170
171/* given a mjd, return the year and number of days since 00:00 Jan 1 */
172void
173mjd_dayno (mjd, yr, dy)
174double mjd;
175int *yr;
176double *dy;
177{
178 double yrd;
179 int yri;
180 int dpy;
181
182 mjd_year (mjd, &yrd);
183 *yr = yri = (int)yrd;
184 dpy = isleapyear(yri) ? 366 : 365;
185 *dy = dpy*(yrd-yri);
186}
187
188/* given a mjd, return the year as a double. */
189void
190mjd_year (mjd, yr)
191double mjd;
192double *yr;
193{
194 static double last_mjd, last_yr;
195 int m, y;
196 double d;
197 double e0, e1; /* mjd of start of this year, start of next year */
198
199 if (mjd == last_mjd) {
200 *yr = last_yr;
201 return;
202 }
203
204 mjd_cal (mjd, &m, &d, &y);
205 if (y == -1) y = -2;
206 cal_mjd (1, 1.0, y, &e0);
207 cal_mjd (1, 1.0, y+1, &e1);
208 *yr = y + (mjd - e0)/(e1 - e0);
209
210 last_mjd = mjd;
211 last_yr = *yr;
212}
213
214/* given a decimal year, return mjd */
215void
216year_mjd (y, mjd)
217double y;
218double *mjd;
219{
220 double e0, e1; /* mjd of start of this year, start of next year */
221 int yf = (int)floor (y);
222 if (yf == -1) yf = -2;
223
224 cal_mjd (1, 1.0, yf, &e0);
225 cal_mjd (1, 1.0, yf+1, &e1);
226 *mjd = e0 + (y - yf)*(e1-e0);
227}
228
229/* round a time in days, *t, to the nearest second, IN PLACE. */
230void
231rnd_second (t)
232double *t;
233{
234 *t = floor(*t*SPD+0.5)/SPD;
235}
236
237/* given an mjd, truncate it to the beginning of the whole day */
238double
239mjd_day(jd)
240double jd;
241{
242 return (floor(jd-0.5)+0.5);
243}
244
245/* given an mjd, return the number of hours past midnight of the whole day */
246double
247mjd_hr(jd)
248double jd;
249{
250 return ((jd-mjd_day(jd))*24.0);
251}
252
253/* insure 0 <= *v < r.
254 */
255void
256range (v, r)
257double *v, r;
258{
259 *v -= r*floor(*v/r);
260}
261
262/* For RCS Only -- Do Not Edit */
263static char *rcsid[2] = {(char *)rcsid, "@(#) $RCSfile: mjd.c,v $ $Date: 2001-04-10 14:40:46 $ $Revision: 1.1.1.1 $ $Name: not supported by cvs2svn $"};
Note: See TracBrowser for help on using the repository browser.