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