1 /*********************************************************
2
3 swe_date_conversion()
4 swe_revjul()
5 swe_julday()
6
7 ************************************************************/
8 /* Copyright (C) 1997 - 2021 Astrodienst AG, Switzerland. All rights reserved.
9
10 License conditions
11 ------------------
12
13 This file is part of Swiss Ephemeris.
14
15 Swiss Ephemeris is distributed with NO WARRANTY OF ANY KIND. No author
16 or distributor accepts any responsibility for the consequences of using it,
17 or for whether it serves any particular purpose or works at all, unless he
18 or she says so in writing.
19
20 Swiss Ephemeris is made available by its authors under a dual licensing
21 system. The software developer, who uses any part of Swiss Ephemeris
22 in his or her software, must choose between one of the two license models,
23 which are
24 a) GNU Affero General Public License (AGPL)
25 b) Swiss Ephemeris Professional License
26
27 The choice must be made before the software developer distributes software
28 containing parts of Swiss Ephemeris to others, and before any public
29 service using the developed software is activated.
30
31 If the developer choses the AGPL software license, he or she must fulfill
32 the conditions of that license, which includes the obligation to place his
33 or her whole software project under the AGPL or a compatible license.
34 See https://www.gnu.org/licenses/agpl-3.0.html
35
36 If the developer choses the Swiss Ephemeris Professional license,
37 he must follow the instructions as found in http://www.astro.com/swisseph/
38 and purchase the Swiss Ephemeris Professional Edition from Astrodienst
39 and sign the corresponding license contract.
40
41 The License grants you the right to use, copy, modify and redistribute
42 Swiss Ephemeris, but only under certain conditions described in the License.
43 Among other things, the License requires that the copyright notices and
44 this notice be preserved on all copies.
45
46 Authors of the Swiss Ephemeris: Dieter Koch and Alois Treindl
47
48 The authors of Swiss Ephemeris have no control or influence over any of
49 the derived works, i.e. over software or services created by other
50 programmers which use Swiss Ephemeris functions.
51
52 The names of the authors or of the copyright holder (Astrodienst) must not
53 be used for promoting any software, product or service which uses or contains
54 the Swiss Ephemeris. This copyright notice is the ONLY place where the
55 names of the authors can legally appear, except in cases where they have
56 given special permission in writing.
57
58 The trademarks 'Swiss Ephemeris' and 'Swiss Ephemeris inside' may be used
59 for promoting such software, products or services.
60 */
61
62 /*
63 swe_date_conversion():
64 This function converts some date+time input {y,m,d,uttime}
65 into the Julian day number tjd.
66 The function checks that the input is a legal combination
67 of dates; for illegal dates like 32 January 1993 it returns ERR
68 but still converts the date correctly, i.e. like 1 Feb 1993.
69 The function is usually used to convert user input of birth data
70 into the Julian day number. Illegal dates should be notified to the user.
71
72 Be aware that we always use astronomical year numbering for the years
73 before Christ, not the historical year numbering.
74 Astronomical years are done with negative numbers, historical
75 years with indicators BC or BCE (before common era).
76 Year 0 (astronomical) = 1 BC historical.
77 year -1 (astronomical) = 2 BC
78 etc.
79 Many users of Astro programs do not know about this difference.
80
81 Return: OK or ERR (for illegal date)
82 *********************************************************/
83
84 # include "swephexp.h"
85 # include "sweph.h"
86
87 static TLS AS_BOOL init_leapseconds_done = FALSE;
88
89
swe_date_conversion(int y,int m,int d,double uttime,char c,double * tjd)90 int CALL_CONV swe_date_conversion(int y,
91 int m,
92 int d, /* day, month, year */
93 double uttime, /* UT in hours (decimal) */
94 char c, /* calendar g[regorian]|j[ulian] */
95 double *tjd)
96 {
97 int rday, rmon, ryear;
98 double rut, jd;
99 int gregflag = SE_JUL_CAL;
100 if (c == 'g')
101 gregflag = SE_GREG_CAL;
102 rut = uttime; /* hours UT */
103 jd = swe_julday(y, m, d, rut, gregflag);
104 swe_revjul(jd, gregflag, &ryear, &rmon, &rday, &rut);
105 *tjd = jd;
106 if (rmon == m && rday == d && ryear == y) {
107 return OK;
108 } else {
109 return ERR;
110 }
111 }
112
113 /*************** swe_julday ********************************************
114 * This function returns the absolute Julian day number (JD)
115 * for a given calendar date.
116 * The arguments are a calendar date: day, month, year as integers,
117 * hour as double with decimal fraction.
118 * If gregflag = SE_GREG_CAL (1), Gregorian calendar is assumed,
119 * if gregflag = SE_JUL_CAL (0),Julian calendar is assumed.
120
121 The Julian day number is a system of numbering all days continously
122 within the time range of known human history. It should be familiar
123 to every astrological or astronomical programmer. The time variable
124 in astronomical theories is usually expressed in Julian days or
125 Julian centuries (36525 days per century) relative to some start day;
126 the start day is called 'the epoch'.
127 The Julian day number is a double representing the number of
128 days since JD = 0.0 on 1 Jan -4712, 12:00 noon (in the Julian calendar).
129
130 Midnight has always a JD with fraction .5, because traditionally
131 the astronomical day started at noon. This was practical because
132 then there was no change of date during a night at the telescope.
133 From this comes also the fact the noon ephemerides were printed
134 before midnight ephemerides were introduced early in the 20th century.
135
136 NOTE: The Julian day number must not be confused with the Julian
137 calendar system.
138
139 Be aware the we always use astronomical year numbering for the years
140 before Christ, not the historical year numbering.
141 Astronomical years are done with negative numbers, historical
142 years with indicators BC or BCE (before common era).
143 Year 0 (astronomical) = 1 BC
144 year -1 (astronomical) = 2 BC
145 etc.
146
147 Original author: Marc Pottenger, Los Angeles.
148 with bug fix for year < -4711 15-aug-88 by Alois Treindl
149
150 References: Oliver Montenbruck, Grundlagen der Ephemeridenrechnung,
151 Verlag Sterne und Weltraum (1987), p.49 ff
152
153 related functions: swe_revjul() reverse Julian day number: compute the
154 calendar date from a given JD
155 swe_date_conversion() includes test for legal date values
156 and notifies errors like 32 January.
157 ****************************************************************/
158
swe_julday(int year,int month,int day,double hour,int gregflag)159 double CALL_CONV swe_julday(int year, int month, int day, double hour, int gregflag)
160 {
161 double jd;
162 double u,u0,u1,u2;
163 u = year;
164 if (month < 3) u -=1;
165 u0 = u + 4712.0;
166 u1 = month + 1.0;
167 if (u1 < 4) u1 += 12.0;
168 jd = floor(u0*365.25)
169 + floor(30.6*u1+0.000001)
170 + day + hour/24.0 - 63.5;
171 if (gregflag == SE_GREG_CAL) {
172 u2 = floor(fabs(u) / 100) - floor(fabs(u) / 400);
173 if (u < 0.0) u2 = -u2;
174 jd = jd - u2 + 2;
175 if ((u < 0.0) && (u/100 == floor(u/100)) && (u/400 != floor(u/400)))
176 jd -=1;
177 }
178 return jd;
179 }
180
181 /*** swe_revjul ******************************************************
182 swe_revjul() is the inverse function to swe_julday(), see the description
183 there.
184 Arguments are julian day number, calendar flag (0=julian, 1=gregorian)
185 return values are the calendar day, month, year and the hour of
186 the day with decimal fraction (0 .. 23.999999).
187
188 Be aware the we use astronomical year numbering for the years
189 before Christ, not the historical year numbering.
190 Astronomical years are done with negative numbers, historical
191 years with indicators BC or BCE (before common era).
192 Year 0 (astronomical) = 1 BC historical year
193 year -1 (astronomical) = 2 BC historical year
194 year -234 (astronomical) = 235 BC historical year
195 etc.
196
197 Original author Mark Pottenger, Los Angeles.
198 with bug fix for year < -4711 16-aug-88 Alois Treindl
199 *************************************************************************/
swe_revjul(double jd,int gregflag,int * jyear,int * jmon,int * jday,double * jut)200 void CALL_CONV swe_revjul (double jd, int gregflag,
201 int *jyear, int *jmon, int *jday, double *jut)
202 {
203 double u0,u1,u2,u3,u4;
204 u0 = jd + 32082.5;
205 if (gregflag == SE_GREG_CAL) {
206 u1 = u0 + floor (u0/36525.0) - floor (u0/146100.0) - 38.0;
207 if (jd >= 1830691.5) u1 +=1;
208 u0 = u0 + floor (u1/36525.0) - floor (u1/146100.0) - 38.0;
209 }
210 u2 = floor (u0 + 123.0);
211 u3 = floor ( (u2 - 122.2) / 365.25);
212 u4 = floor ( (u2 - floor (365.25 * u3) ) / 30.6001);
213 *jmon = (int) (u4 - 1.0);
214 if (*jmon > 12) *jmon -= 12;
215 *jday = (int) (u2 - floor (365.25 * u3) - floor (30.6001 * u4));
216 *jyear = (int) (u3 + floor ( (u4 - 2.0) / 12.0) - 4800);
217 *jut = (jd - floor (jd + 0.5) + 0.5) * 24.0;
218 }
219
220 /* transform local time to UTC or UTC to local time
221 *
222 * input
223 * iyear ... dsec date and time
224 * d_timezone timezone offset
225 * output
226 * iyear_out ... dsec_out
227 *
228 * For time zones east of Greenwich, d_timezone is positive.
229 * For time zones west of Greenwich, d_timezone is negative.
230 *
231 * For conversion from local time to utc, use +d_timezone.
232 * For conversion from utc to local time, use -d_timezone.
233 */
swe_utc_time_zone(int32 iyear,int32 imonth,int32 iday,int32 ihour,int32 imin,double dsec,double d_timezone,int32 * iyear_out,int32 * imonth_out,int32 * iday_out,int32 * ihour_out,int32 * imin_out,double * dsec_out)234 void CALL_CONV swe_utc_time_zone(
235 int32 iyear, int32 imonth, int32 iday,
236 int32 ihour, int32 imin, double dsec,
237 double d_timezone,
238 int32 *iyear_out, int32 *imonth_out, int32 *iday_out,
239 int32 *ihour_out, int32 *imin_out, double *dsec_out
240 )
241 {
242 double tjd, d;
243 AS_BOOL have_leapsec = FALSE;
244 double dhour;
245 if (dsec >= 60.0) {
246 have_leapsec = TRUE;
247 dsec -= 1.0;
248 }
249 dhour = ((double) ihour) + ((double) imin) / 60.0 + dsec / 3600.0;
250 tjd = swe_julday(iyear, imonth, iday, 0, SE_GREG_CAL);
251 dhour -= d_timezone;
252 if (dhour < 0.0) {
253 tjd -= 1.0;
254 dhour += 24.0;
255 }
256 if (dhour >= 24.0) {
257 tjd += 1.0;
258 dhour -= 24.0;
259 }
260 swe_revjul(tjd + 0.001, SE_GREG_CAL, iyear_out, imonth_out, iday_out, &d);
261 *ihour_out = (int) dhour;
262 d = (dhour - (double) *ihour_out) * 60;
263 *imin_out = (int) d;
264 *dsec_out = (d - (double) *imin_out) * 60;
265 if (have_leapsec)
266 *dsec_out += 1.0;
267 }
268
269 /*
270 * functions for the handling of UTC
271 */
272
273 /* Leap seconds were inserted at the end of the following days:*/
274 #define NLEAP_SECONDS 27 // ignoring end mark '0'
275 #define NLEAP_SECONDS_SPACE 100
276 static TLS int leap_seconds[NLEAP_SECONDS_SPACE] = {
277 19720630,
278 19721231,
279 19731231,
280 19741231,
281 19751231,
282 19761231,
283 19771231,
284 19781231,
285 19791231,
286 19810630,
287 19820630,
288 19830630,
289 19850630,
290 19871231,
291 19891231,
292 19901231,
293 19920630,
294 19930630,
295 19940630,
296 19951231,
297 19970630,
298 19981231,
299 20051231,
300 20081231,
301 20120630,
302 20150630,
303 20161231,
304 0 /* keep this 0 as end mark */
305 };
306 #define J1972 2441317.5
307 #define NLEAP_INIT 10
308
309 /* Read additional leap second dates from external file, if given.
310 */
init_leapsec(void)311 static int init_leapsec(void)
312 {
313 FILE *fp;
314 int ndat, ndat_last;
315 int tabsiz = 0;
316 int i;
317 char s[AS_MAXCH];
318 char *sp;
319 if (!init_leapseconds_done) {
320 init_leapseconds_done = TRUE;
321 tabsiz = NLEAP_SECONDS;
322 ndat_last = leap_seconds[NLEAP_SECONDS - 1];
323 /* no error message if file is missing */
324 if ((fp = swi_fopen(-1, "seleapsec.txt", swed.ephepath, NULL)) == NULL)
325 return NLEAP_SECONDS;
326 while(fgets(s, AS_MAXCH, fp) != NULL) {
327 sp = s;
328 while (*sp == ' ' || *sp == '\t') sp++;
329 sp++;
330 if (*sp == '#' || *sp == '\n')
331 continue;
332 ndat = atoi(s);
333 if (ndat <= ndat_last)
334 continue;
335 /* table space is limited. no error msg, if exceeded */
336 if (tabsiz >= NLEAP_SECONDS_SPACE)
337 return tabsiz;
338 leap_seconds[tabsiz] = ndat;
339 tabsiz++;
340 }
341 if (tabsiz > NLEAP_SECONDS) leap_seconds[tabsiz] = 0; /* end mark */
342 fclose(fp);
343 return tabsiz;
344 }
345 /* find table size */
346 tabsiz = 0;
347 for (i = 0; i < NLEAP_SECONDS_SPACE; i++) {
348 if (leap_seconds[i] == 0)
349 break;
350 else
351 tabsiz++;
352 }
353 return tabsiz;
354 }
355
356 /*
357 * Input: Clock time UTC, year, month, day, hour, minute, second (decimal).
358 * gregflag Calendar flag
359 * serr error string
360 * Output: An array of doubles:
361 * dret[0] = Julian day number TT (ET)
362 * dret[1] = Julian day number UT1
363 *
364 * Function returns OK or Error.
365 *
366 * - Before 1972, swe_utc_to_jd() treats its input time as UT1.
367 * Note: UTC was introduced in 1961. From 1961 - 1971, the length of the
368 * UTC second was regularly changed, so that UTC remained very close to UT1.
369 * - From 1972 on, input time is treated as UTC.
370 * - If delta_t - nleap - 32.184 > 1, the input time is treated as UT1.
371 * Note: Like this we avoid errors greater than 1 second in case that
372 * the leap seconds table (or the Swiss Ephemeris version) is not updated
373 * for a long time.
374 */
swe_utc_to_jd(int32 iyear,int32 imonth,int32 iday,int32 ihour,int32 imin,double dsec,int32 gregflag,double * dret,char * serr)375 int32 CALL_CONV swe_utc_to_jd(int32 iyear, int32 imonth, int32 iday, int32 ihour, int32 imin, double dsec, int32 gregflag, double *dret, char *serr)
376 {
377 double tjd_ut1, tjd_et, tjd_et_1972, dhour, d;
378 int iyear2, imonth2, iday2;
379 int i, j, ndat, nleap, tabsiz_nleap;
380 /*
381 * error handling: invalid iyear etc.
382 */
383 tjd_ut1 = swe_julday(iyear, imonth, iday, 0, gregflag);
384 swe_revjul(tjd_ut1, gregflag, &iyear2, &imonth2, &iday2, &d);
385 if (iyear != iyear2 || imonth != imonth2 || iday != iday2) {
386 if (serr != NULL)
387 sprintf(serr, "invalid date: year = %d, month = %d, day = %d", iyear, imonth, iday);
388 return ERR;
389 }
390 if (ihour < 0 || ihour > 23
391 || imin < 0 || imin > 59
392 || dsec < 0 || dsec >= 61
393 || (dsec >= 60 && (imin < 59 || ihour < 23 || tjd_ut1 < J1972))) {
394 if (serr != NULL)
395 sprintf(serr, "invalid time: %d:%d:%.2f", ihour, imin, dsec);
396 return ERR;
397 }
398 dhour = (double) ihour + ((double) imin) / 60.0 + dsec / 3600.0;
399 /*
400 * before 1972, we treat input date as UT1
401 */
402 if (tjd_ut1 < J1972) {
403 dret[1] = swe_julday(iyear, imonth, iday, dhour, gregflag);
404 dret[0] = dret[1] + swe_deltat_ex(dret[1], -1, NULL);
405 return OK;
406 }
407 /*
408 * if gregflag = Julian calendar, convert to gregorian calendar
409 */
410 if (gregflag == SE_JUL_CAL) {
411 gregflag = SE_GREG_CAL;
412 swe_revjul(tjd_ut1, gregflag, &iyear, &imonth, &iday, &d);
413 }
414 /*
415 * number of leap seconds since 1972:
416 */
417 tabsiz_nleap = init_leapsec();
418 nleap = NLEAP_INIT; /* initial difference between UTC and TAI in 1972 */
419 ndat = iyear * 10000 + imonth * 100 + iday;
420 for (i = 0; i < tabsiz_nleap; i++) {
421 if (ndat <= leap_seconds[i])
422 break;
423 nleap++;
424 }
425 /*
426 * For input dates > today:
427 * If leap seconds table is not up to date, we'd better interpret the
428 * input time as UT1, not as UTC. How do we find out?
429 * Check, if delta_t - nleap - 32.184 > 0.9
430 */
431 d = swe_deltat_ex(tjd_ut1, -1, NULL) * 86400.0;
432 if (d - (double) nleap - 32.184 >= 1.0) {
433 dret[1] = tjd_ut1 + dhour / 24.0;
434 dret[0] = dret[1] + swe_deltat_ex(dret[1], -1, NULL);
435 return OK;
436 }
437 /*
438 * if input second is 60: is it a valid leap second ?
439 */
440 if (dsec >= 60) {
441 j = 0;
442 for (i = 0; i < tabsiz_nleap; i++) {
443 if (ndat == leap_seconds[i]) {
444 j = 1;
445 break;
446 }
447 }
448 if (j != 1) {
449 if (serr != NULL)
450 sprintf(serr, "invalid time (no leap second!): %d:%d:%.2f", ihour, imin, dsec);
451 return ERR;
452 }
453 }
454 /*
455 * convert UTC to ET and UT1
456 */
457 /* the number of days between input date and 1 jan 1972: */
458 d = tjd_ut1 - J1972;
459 /* SI time since 1972, ignoring leap seconds: */
460 d += (double) ihour / 24.0 + (double) imin / 1440.0 + dsec / 86400.0;
461 /* ET (TT) */
462 tjd_et_1972 = J1972 + (32.184 + NLEAP_INIT) / 86400.0;
463 tjd_et = tjd_et_1972 + d + ((double) (nleap - NLEAP_INIT)) / 86400.0;
464 d = swe_deltat_ex(tjd_et, -1, NULL);
465 tjd_ut1 = tjd_et - swe_deltat_ex(tjd_et - d, -1, NULL);
466 tjd_ut1 = tjd_et - swe_deltat_ex(tjd_ut1, -1, NULL);
467 dret[0] = tjd_et;
468 dret[1] = tjd_ut1;
469 return OK;
470 }
471
472 /*
473 * Input: tjd_et Julian day number, terrestrial time (ephemeris time).
474 * gregfalg Calendar flag
475 * Output: UTC year, month, day, hour, minute, second (decimal).
476 *
477 * - Before 1 jan 1972 UTC, output UT1.
478 * Note: UTC was introduced in 1961. From 1961 - 1971, the length of the
479 * UTC second was regularly changed, so that UTC remained very close to UT1.
480 * - From 1972 on, output is UTC.
481 * - If delta_t - nleap - 32.184 > 1, the output is UT1.
482 * Note: Like this we avoid errors greater than 1 second in case that
483 * the leap seconds table (or the Swiss Ephemeris version) has not been
484 * updated for a long time.
485 */
swe_jdet_to_utc(double tjd_et,int32 gregflag,int32 * iyear,int32 * imonth,int32 * iday,int32 * ihour,int32 * imin,double * dsec)486 void CALL_CONV swe_jdet_to_utc(double tjd_et, int32 gregflag, int32 *iyear, int32 *imonth, int32 *iday, int32 *ihour, int32 *imin, double *dsec)
487 {
488 int i;
489 int second_60 = 0;
490 int iyear2, imonth2, iday2, nleap, ndat, tabsiz_nleap;
491 double d, tjd, tjd_et_1972, tjd_ut, dret[10];
492 /*
493 * if tjd_et is before 1 jan 1972 UTC, return UT1
494 */
495 tjd_et_1972 = J1972 + (32.184 + NLEAP_INIT) / 86400.0;
496 d = swe_deltat_ex(tjd_et, -1, NULL);
497 tjd_ut = tjd_et - swe_deltat_ex(tjd_et - d, -1, NULL);
498 tjd_ut = tjd_et - swe_deltat_ex(tjd_ut, -1, NULL);
499 if (tjd_et < tjd_et_1972) {
500 swe_revjul(tjd_ut, gregflag, iyear, imonth, iday, &d);
501 *ihour = (int32) d;
502 d -= (double) *ihour;
503 d *= 60;
504 *imin = (int32) d;
505 *dsec = (d - (double) *imin) * 60.0;
506 return;
507 }
508 /*
509 * minimum number of leap seconds since 1972; we may be missing one leap
510 * second
511 */
512 tabsiz_nleap = init_leapsec();
513 swe_revjul(tjd_ut-1, SE_GREG_CAL, &iyear2, &imonth2, &iday2, &d);
514 ndat = iyear2 * 10000 + imonth2 * 100 + iday2;
515 nleap = 0;
516 for (i = 0; i < tabsiz_nleap; i++) {
517 if (ndat <= leap_seconds[i])
518 break;
519 nleap++;
520 }
521 /* date of potentially missing leapsecond */
522 if (nleap < tabsiz_nleap) {
523 i = leap_seconds[nleap];
524 iyear2 = i / 10000;
525 imonth2 = (i % 10000) / 100;;
526 iday2 = i % 100;
527 tjd = swe_julday(iyear2, imonth2, iday2, 0, SE_GREG_CAL);
528 swe_revjul(tjd+1, SE_GREG_CAL, &iyear2, &imonth2, &iday2, &d);
529 swe_utc_to_jd(iyear2,imonth2,iday2, 0, 0, 0, SE_GREG_CAL, dret, NULL);
530 d = tjd_et - dret[0];
531 if (d >= 0) {
532 nleap++;
533 } else if (d < 0 && d > -1.0/86400.0) {
534 second_60 = 1;
535 }
536 }
537 /*
538 * UTC, still unsure about one leap second
539 */
540 tjd = J1972 + (tjd_et - tjd_et_1972) - ((double) nleap + second_60) / 86400.0;
541 swe_revjul(tjd, SE_GREG_CAL, iyear, imonth, iday, &d);
542 *ihour = (int32) d;
543 d -= (double) *ihour;
544 d *= 60;
545 *imin = (int32) d;
546 *dsec = (d - (double) *imin) * 60.0 + second_60;
547 /*
548 * For input dates > today:
549 * If leap seconds table is not up to date, we'd better interpret the
550 * input time as UT1, not as UTC. How do we find out?
551 * Check, if delta_t - nleap - 32.184 > 0.9
552 */
553 d = swe_deltat_ex(tjd_et, -1, NULL);
554 d = swe_deltat_ex(tjd_et - d, -1, NULL);
555 if (d * 86400.0 - (double) (nleap + NLEAP_INIT) - 32.184 >= 1.0) {
556 swe_revjul(tjd_et - d, SE_GREG_CAL, iyear, imonth, iday, &d);
557 *ihour = (int32) d;
558 d -= (double) *ihour;
559 d *= 60;
560 *imin = (int32) d;
561 *dsec = (d - (double) *imin) * 60.0;
562 }
563 if (gregflag == SE_JUL_CAL) {
564 tjd = swe_julday(*iyear, *imonth, *iday, 0, SE_GREG_CAL);
565 swe_revjul(tjd, gregflag, iyear, imonth, iday, &d);
566 }
567 }
568
569 /*
570 * Input: tjd_ut Julian day number, universal time (UT1).
571 * gregfalg Calendar flag
572 * Output: UTC year, month, day, hour, minute, second (decimal).
573 *
574 * - Before 1 jan 1972 UTC, output UT1.
575 * Note: UTC was introduced in 1961. From 1961 - 1971, the length of the
576 * UTC second was regularly changed, so that UTC remained very close to UT1.
577 * - From 1972 on, output is UTC.
578 * - If delta_t - nleap - 32.184 > 1, the output is UT1.
579 * Note: Like this we avoid errors greater than 1 second in case that
580 * the leap seconds table (or the Swiss Ephemeris version) has not been
581 * updated for a long time.
582 */
swe_jdut1_to_utc(double tjd_ut,int32 gregflag,int32 * iyear,int32 * imonth,int32 * iday,int32 * ihour,int32 * imin,double * dsec)583 void CALL_CONV swe_jdut1_to_utc(double tjd_ut, int32 gregflag, int32 *iyear, int32 *imonth, int32 *iday, int32 *ihour, int32 *imin, double *dsec)
584 {
585 double tjd_et = tjd_ut + swe_deltat_ex(tjd_ut, -1, NULL);
586 swe_jdet_to_utc(tjd_et, gregflag, iyear, imonth, iday, ihour, imin, dsec);
587 }
588
589