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

Last change on this file since 3586 was 3477, checked in by cmv, 18 years ago

mise a jour Xephem 3.7.3 , cmv 25/03/2008

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