diff options
Diffstat (limited to 'funtools/wcs/dateutil.c')
-rw-r--r-- | funtools/wcs/dateutil.c | 4554 |
1 files changed, 4554 insertions, 0 deletions
diff --git a/funtools/wcs/dateutil.c b/funtools/wcs/dateutil.c new file mode 100644 index 0000000..ada0c95 --- /dev/null +++ b/funtools/wcs/dateutil.c @@ -0,0 +1,4554 @@ +/*** File libwcs/dateutil.c + *** October 19, 2012 + *** By Jessica Mink, jmink@cfa.harvard.edu + *** Harvard-Smithsonian Center for Astrophysics + *** Copyright (C) 1999-2012 + *** Smithsonian Astrophysical Observatory, Cambridge, MA, USA + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + Correspondence concerning WCSTools should be addressed as follows: + Internet email: jmink@cfa.harvard.edu + Postal address: Jessica Mink + Smithsonian Astrophysical Observatory + 60 Garden St. + Cambridge, MA 02138 USA + */ + +/* Date and time conversion routines using the following conventions: + ang = Angle in fractional degrees + deg = Angle in degrees as dd:mm:ss.ss + doy = 2 floating point numbers: year and day, including fraction, of year + *** First day of year is 1, not zero. + dt = 2 floating point numbers: yyyy.mmdd, hh.mmssssss + ep = fractional year, often epoch of a position including proper motion + epb = Besselian epoch = 365.242198781-day years based on 1900.0 + epj = Julian epoch = 365.25-day years based on 2000.0 + fd = FITS date string which may be any of the following: + yyyy.ffff (fractional year) + dd/mm/yy (FITS standard before 2000) + dd-mm-yy (nonstandard FITS use before 2000) + yyyy-mm-dd (FITS standard after 1999) + yyyy-mm-ddThh:mm:ss.ss (FITS standard after 1999) + hr = Sexigesimal hours as hh:mm:dd.ss + jd = Julian Date + lt = Local time + mjd = modified Julian Date = JD - 2400000.5 + ofd = FITS date string (dd/mm/yy before 2000, else no return) + time = use fd2* with no date to convert time as hh:mm:ss.ss to sec, day, year + ts = UT seconds since 1950-01-01T00:00 (used for ephemeris computations) + tsi = local seconds since 1980-01-01T00:00 (used by IRAF as a time tag) + tsu = UT seconds since 1970-01-01T00:00 (used as Unix system time) + tsd = UT seconds of current day + ut = Universal Time (UTC) + et = Ephemeris Time (or TDB or TT) = TAI + 32.184 seconds + tai = International Atomic Time (Temps Atomique International) = ET - 32.184 seconds + gps = GPS time = TAI - 19 seconds + mst = Mean Greenwich Sidereal Time + gst = Greenwich Sidereal Time (includes nutation) + lst = Local Sidereal Time (includes nutation) (longitude must be set) + hjd = Heliocentric Julian Date + mhjd = modified Heliocentric Julian Date = HJD - 2400000.5 + + * ang2hr (angle) + * Convert angle in decimal floating point degrees to hours as hh:mm:ss.ss + * ang2deg (angle) + * Convert angle in decimal floating point degrees to degrees as dd:mm:ss.ss + * deg2ang (angle as dd:mm:ss.ss) + * Convert angle in degrees as dd:mm:ss.ss to decimal floating point degrees + * ang2hr (angle) + * Convert angle in hours as hh:mm:ss.ss to decimal floating point degrees + * + * doy2dt (year, doy, date, time) + * Convert year and day of year to date as yyyy.ddmm and time as hh.mmsss + * doy2ep, doy2epb, doy2epj (date, time) + * Convert year and day of year to fractional year + * doy2fd (year, doy) + * Convert year and day of year to FITS date string + * doy2mjd (year, doy) + * Convert year and day of year to modified Julian date + * + * dt2doy (date, time, year, doy) + * Convert date as yyyy.ddmm and time as hh.mmsss to year and day of year + * dt2ep, dt2epb, dt2epj (date, time) + * Convert date as yyyy.ddmm and time as hh.mmsss to fractional year + * dt2fd (date, time) + * Convert date as yyyy.ddmm and time as hh.mmsss to FITS date string + * dt2i (date,time,iyr,imon,iday,ihr,imn,sec, ndsec) + * Convert yyyy.mmdd hh.mmssss to year month day hours minutes seconds + * dt2jd (date,time) + * Convert date as yyyy.ddmm and time as hh.mmsss to Julian date + * dt2mjd (date,time) + * Convert date as yyyy.ddmm and time as hh.mmsss to modified Julian date + * dt2ts (date,time) + * Convert date (yyyy.ddmm) and time (hh.mmsss) to seconds since 1950-01-01 + * dt2tsi (date,time) + * Convert date (yyyy.ddmm) and time (hh.mmsss) to seconds since 1980-01-01 + * dt2tsu (date,time) + * Convert date (yyyy.ddmm) and time (hh.mmsss) to seconds since 1970-01-01 + * + * ep2dt, epb2dt, epj2dt (epoch,date, time) + * Convert fractional year to date as yyyy.ddmm and time as hh.mmsss + * ep2fd, epb2fd, epj2fd (epoch) + * Convert epoch to FITS ISO date string + * ep2i, epb2i, epj2i (epoch,iyr,imon,iday,ihr,imn,sec, ndsec) + * Convert fractional year to year month day hours minutes seconds + * ep2jd, epb2jd, epj2jd (epoch) + * Convert fractional year as used in epoch to Julian date + * ep2mjd, epb2mjd, epj2mjd (epoch) + * Convert fractional year as used in epoch to modified Julian date + * ep2ts, epb2ts, epj2ts (epoch) + * Convert fractional year to seconds since 1950.0 + * + * et2fd (string) + * Convert from ET (or TDT or TT) in FITS format to UT in FITS format + * fd2et (string) + * Convert from UT in FITS format to ET (or TDT or TT) in FITS format + * jd2jed (dj) + * Convert from Julian Date to Julian Ephemeris Date + * jed2jd (dj) + * Convert from Julian Ephemeris Date to Julian Date + * dt2et (date, time) + * Convert date (yyyy.ddmm) and time (hh.mmsss) to ephemeris time + * edt2dt (date, time) + * Convert ephemeris date (yyyy.ddmm) and time (hh.mmsss) to UT + * dt2tai (date, time) + * Convert date (yyyy.ddmm) and time (hh.mmsss) to TAI date and time + * tai2dt (date, time) + * Convert TAI date (yyyy.ddmm) and time (hh.mmsss) to UT + * ts2ets (tsec) + * Convert from UT in seconds since 1950-01-01 to ET in same format + * ets2ts (tsec) + * Convert from ET in seconds since 1950-01-01 to UT in same format + * + * fd2ep, fd2epb, fd2epj (string) + * Convert FITS date string to fractional year + * Convert time alone to fraction of Besselian year + * fd2doy (string, year, doy) + * Convert FITS standard date string to year and day of year + * fd2dt (string, date, time) + * Convert FITS date string to date as yyyy.ddmm and time as hh.mmsss + * Convert time alone to hh.mmssss with date set to 0.0 + * fd2i (string,iyr,imon,iday,ihr,imn,sec, ndsec) + * Convert FITS standard date string to year month day hours min sec + * Convert time alone to hours min sec, year month day are zero + * fd2jd (string) + * Convert FITS standard date string to Julian date + * Convert time alone to fraction of day + * fd2mjd (string) + * Convert FITS standard date string to modified Julian date + * fd2ts (string) + * Convert FITS standard date string to seconds since 1950.0 + * Convert time alone to seconds of day + * fd2fd (string) + * Convert FITS standard date string to ISO FITS date string + * fd2of (string) + * Convert FITS standard date string to old-format FITS date and time + * fd2ofd (string) + * Convert FITS standard date string to old-format FITS date string + * fd2oft (string) + * Convert time part of FITS standard date string to FITS date string + * + * jd2doy (dj, year, doy) + * Convert Julian date to year and day of year + * jd2dt (dj,date,time) + * Convert Julian date to date as yyyy.mmdd and time as hh.mmssss + * jd2ep, jd2epb, jd2epj (dj) + * Convert Julian date to fractional year as used in epoch + * jd2fd (dj) + * Convert Julian date to FITS ISO date string + * jd2i (dj,iyr,imon,iday,ihr,imn,sec, ndsec) + * Convert Julian date to year month day hours min sec + * jd2mjd (dj) + * Convert Julian date to modified Julian date + * jd2ts (dj) + * Convert Julian day to seconds since 1950.0 + * + * lt2dt() + * Return local time as yyyy.mmdd and time as hh.mmssss + * lt2fd() + * Return local time as FITS ISO date string + * lt2tsi() + * Return local time as IRAF seconds since 1980-01-01 00:00 + * lt2tsu() + * Return local time as Unix seconds since 1970-01-01 00:00 + * lt2ts() + * Return local time as Unix seconds since 1950-01-01 00:00 + * + * mjd2doy (dj,year,doy) + * Convert modified Julian date to date as year and day of year + * mjd2dt (dj,date,time) + * Convert modified Julian date to date as yyyy.mmdd and time as hh.mmssss + * mjd2ep, mjd2epb, mjd2epj (dj) + * Convert modified Julian date to fractional year as used in epoch + * mjd2fd (dj) + * Convert modified Julian date to FITS ISO date string + * mjd2i (dj,iyr,imon,iday,ihr,imn,sec, ndsec) + * Convert modified Julian date to year month day hours min sec + * mjd2jd (dj) + * Convert modified Julian date to Julian date + * mjd2ts (dj) + * Convert modified Julian day to seconds since 1950.0 + * + * ts2dt (tsec,date,time) + * Convert seconds since 1950.0 to date as yyyy.ddmm and time as hh.mmsss + * ts2ep, ts2epb, ts2epj (tsec) + * Convert seconds since 1950.0 to fractional year + * ts2fd (tsec) + * Convert seconds since 1950.0 to FITS standard date string + * ts2i (tsec,iyr,imon,iday,ihr,imn,sec, ndsec) + * Convert sec since 1950.0 to year month day hours minutes seconds + * ts2jd (tsec) + * Convert seconds since 1950.0 to Julian date + * ts2mjd (tsec) + * Convert seconds since 1950.0 to modified Julian date + * tsi2fd (tsec) + * Convert seconds since 1980-01-01 to FITS standard date string + * tsi2dt (tsec,date,time) + * Convert seconds since 1980-01-01 to date as yyyy.ddmm, time as hh.mmsss + * tsu2fd (tsec) + * Convert seconds since 1970-01-01 to FITS standard date string + * tsu2tsi (tsec) + * Convert UT seconds since 1970-01-01 to local seconds since 1980-01-01 + * tsu2dt (tsec,date,time) + * Convert seconds since 1970-01-01 to date as yyyy.ddmm, time as hh.mmsss + * + * tsd2fd (tsec) + * Convert seconds since start of day to FITS time, hh:mm:ss.ss + * tsd2dt (tsec) + * Convert seconds since start of day to hh.mmssss + * + * fd2gst (string) + * convert from FITS date Greenwich Sidereal Time + * dt2gst (date, time) + * convert from UT as yyyy.mmdd hh.mmssss to Greenwich Sidereal Time + * ts2gst (tsec) + * Calculate Greenwich Sidereal Time given Universal Time + * in seconds since 1951-01-01T0:00:00 + * fd2mst (string) + * convert from FITS UT date to Mean Sidereal Time + * dt2gmt (date, time) + * convert from UT as yyyy.mmdd hh.mmssss to Mean Sidereal Time + * ts2mst (tsec) + * Calculate Mean Sidereal Time given Universal Time + * in seconds since 1951-01-01T0:00:00 + * jd2mst (string) + * convert from Julian Date to Mean Sidereal Time + * mst2fd (string) + * convert to current UT in FITS format given Greenwich Mean Sidereal Time + * mst2jd (dj) + * convert to current UT as Julian Date given Greenwich Mean Sidereal Time + * jd2lst (dj) + * Calculate Local Sidereal Time from Julian Date + * ts2lst (tsec) + * Calculate Local Sidereal Time given UT in seconds since 1951-01-01T0:00 + * fd2lst (string) + * Calculate Local Sidereal Time given Universal Time as FITS ISO date + * lst2jd (dj, lst) + * Calculate Julian Date given current Julian date and Local Sidereal Time + * lst2fd (string, lst) + * Calculate Julian Date given current UT date and Local Sidereal Time + * gst2fd (string) + * Calculate current UT given UT date and Greenwich Sidereal Time + * gst2jd (dj) + * Calculate current UT given UT date and Greenwich Sidereal Time as JD + * + * compnut (dj, dpsi, deps, eps0) + * Compute the longitude and obliquity components of nutation and + * mean obliquity from the IAU 1980 theory + * + * utdt (dj) + * Compute difference between UT and dynamical time (ET-UT) + * ut2dt (year, doy) + * Current Universal Time to year and day of year + * ut2dt (date, time) + * Current Universal Time to date (yyyy.mmdd) and time (hh.mmsss) + * ut2ep(), ut2epb(), ut2epj() + * Current Universal Time to fractional year, Besselian, Julian epoch + * ut2fd() + * Current Universal Time to FITS ISO date string + * ut2jd() + * Current Universal Time to Julian Date + * ut2mjd() + * Current Universal Time to Modified Julian Date + * ut2tsi() + * Current Universal Time to IRAF seconds since 1980-01-01T00:00 + * ut2tsu() + * Current Universal Time to Unix seconds since 1970-01-01T00:00 + * ut2ts() + * Current Universal Time to seconds since 1950-01-01T00:00 + * isdate (string) + * Return 1 if string is a FITS date (old or ISO) + * + * Internally-used subroutines + * + * fixdate (iyr, imon, iday, ihr, imn, sec, ndsec) + * Round seconds and make sure date and time numbers are within limits + * caldays (year, month) + * Calculate days in month 1-12 given year (Gregorian calendar only + * dint (dnum) + * Return integer part of floating point number + * dmod (dnum) + * Return Mod of floating point number + */ + +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <math.h> +#include <time.h> +#include <sys/time.h> +#include "wcs.h" +#include "fitsfile.h" + +static double suntl(); +static void fixdate(); +static int caldays(); +static double dint(); +static double dmod(); + +static double longitude = 0.0; /* longitude of observatory in degrees (+=west) */ +void +setlongitude (longitude0) +double longitude0; +{ longitude = longitude0; return; } + +static int ndec = 3; +void +setdatedec (nd) +int nd; +{ ndec = nd; return; } + +/* ANG2HR -- Convert angle in fraction degrees to hours as hh:mm:ss.ss */ + +void +ang2hr (angle, lstr, string) + +double angle; /* Angle in fractional degrees */ +int lstr; /* Maximum number of characters in string */ +char *string; /* Character string (hh:mm:ss.ss returned) */ + +{ + angle = angle / 15.0; + dec2str (string, lstr, angle, ndec); + return; +} + + +/* ANG2DEG -- Convert angle in fraction degrees to degrees as dd:mm:ss.ss */ + +void +ang2deg (angle, lstr, string) + +double angle; /* Angle in fractional degrees */ +int lstr; /* Maximum number of characters in string */ +char *string; /* Character string (dd:mm:ss.ss returned) */ +{ + dec2str (string, lstr, angle, ndec); + return; +} + + +/* DEG2ANG -- Convert angle in degrees as dd:mm:ss.ss to fractional degrees */ + +double +deg2ang (angle) + +char *angle; /* Angle as dd:mm:ss.ss */ +{ + double deg; + + deg = str2dec (angle); + return (deg); +} + +/* HR2ANG -- Convert angle in hours as hh:mm:ss.ss to fractional degrees */ + +double +hr2ang (angle) + +char *angle; /* Angle in sexigesimal hours (hh:mm:ss.sss) */ + +{ + double deg; + + deg = str2dec (angle); + deg = deg * 15.0; + return (deg); +} + + +/* DT2FD-- convert vigesimal date and time to FITS date, yyyy-mm-ddThh:mm:ss.ss */ + +char * +dt2fd (date, time) + +double date; /* Date as yyyy.mmdd + yyyy = calendar year (e.g. 1973) + mm = calendar month (e.g. 04 = april) + dd = calendar day (e.g. 15) */ +double time; /* Time as hh.mmssxxxx + *if time<0, it is time as -(fraction of a day) + hh = hour of day (0 .le. hh .le. 23) + nn = minutes (0 .le. nn .le. 59) + ss = seconds (0 .le. ss .le. 59) + xxxx = tenths of milliseconds (0 .le. xxxx .le. 9999) */ +{ + int iyr,imon,iday,ihr,imn; + double sec; + int nf; + char *string; + char tstring[32], dstring[32]; + char outform[64]; + + dt2i (date, time, &iyr,&imon,&iday,&ihr,&imn,&sec, ndec); + + /* Convert to ISO date format */ + string = (char *) calloc (32, sizeof (char)); + + /* Make time string */ + if (time != 0.0 || ndec > 0) { + if (ndec == 0) + nf = 2; + else + nf = 3 + ndec; + if (ndec > 0) { + sprintf (outform, "%%02d:%%02d:%%0%d.%df", nf, ndec); + sprintf (tstring, outform, ihr, imn, sec); + } + else { + sprintf (outform, "%%02d:%%02d:%%0%dd", nf); + sprintf (tstring, outform, ihr, imn, (int)(sec+0.5)); + } + } + + /* Make date string */ + if (date != 0.0) + sprintf (dstring, "%4d-%02d-%02d", iyr, imon, iday); + + /* Make FITS (ISO) date string */ + if (date == 0.0) + strcpy (string, tstring); + else if (time == 0.0 && ndec < 1) + strcpy (string, dstring); + else + sprintf (string, "%sT%s", dstring, tstring); + + return (string); +} + + +/* DT2JD-- convert from date as yyyy.mmdd and time as hh.mmsss to Julian Date + * Return fractional days if date is zero */ + +double +dt2jd (date,time) + +double date; /* Date as yyyy.mmdd + yyyy = calendar year (e.g. 1973) + mm = calendar month (e.g. 04 = april) + dd = calendar day (e.g. 15) */ +double time; /* Time as hh.mmssxxxx + *if time<0, it is time as -(fraction of a day) + hh = hour of day (0 .le. hh .le. 23) + nn = minutes (0 .le. nn .le. 59) + ss = seconds (0 .le. ss .le. 59) + xxxx = tenths of milliseconds (0 .le. xxxx .le. 9999) */ +{ + double dj; /* Julian date (returned) */ + double tsec; /* seconds since 1950.0 */ + + tsec = dt2ts (date, time); + if (date == 0.0) + dj = tsec / 86400.0; + else + dj = ts2jd (tsec); + + return (dj); +} + + +/* DT2MJD-- convert from date yyyy.mmdd time hh.mmsss to modified Julian Date + * Return fractional days if date is zero */ + +double +dt2mjd (date,time) + +double date; /* Date as yyyy.mmdd + yyyy = calendar year (e.g. 1973) + mm = calendar month (e.g. 04 = april) + dd = calendar day (e.g. 15) */ +double time; /* Time as hh.mmssxxxx + *if time<0, it is time as -(fraction of a day) + hh = hour of day (0 .le. hh .le. 23) + nn = minutes (0 .le. nn .le. 59) + ss = seconds (0 .le. ss .le. 59) + xxxx = tenths of milliseconds (0 .le. xxxx .le. 9999) */ +{ + double dj; /* Modified Julian date (returned) */ + double tsec; /* seconds since 1950.0 */ + + tsec = dt2ts (date, time); + if (date == 0.0) + dj = tsec / 86400.0; + else + dj = ts2jd (tsec); + + return (dj - 2400000.5); +} + + +/* HJD2JD-- convert Heliocentric Julian Date to (geocentric) Julian date */ + +double +hjd2jd (dj, ra, dec, sys) + +double dj; /* Heliocentric Julian date */ +double ra; /* Right ascension (degrees) */ +double dec; /* Declination (degrees) */ +int sys; /* J2000, B1950, GALACTIC, ECLIPTIC */ +{ + double lt; /* Light travel difference to the Sun (days) */ + + lt = suntl (dj, ra, dec, sys); + + /* Return Heliocentric Julian Date */ + return (dj - lt); +} + + +/* JD2HJD-- convert (geocentric) Julian date to Heliocentric Julian Date */ + +double +jd2hjd (dj, ra, dec, sys) + +double dj; /* Julian date (geocentric) */ +double ra; /* Right ascension (degrees) */ +double dec; /* Declination (degrees) */ +int sys; /* J2000, B1950, GALACTIC, ECLIPTIC */ +{ + double lt; /* Light travel difference to the Sun (days) */ + + lt = suntl (dj, ra, dec, sys); + + /* Return Heliocentric Julian Date */ + return (dj + lt); +} + + +/* MHJD2MJD-- convert modified Heliocentric Julian Date to + modified geocentric Julian date */ + +double +mhjd2mjd (mhjd, ra, dec, sys) + +double mhjd; /* Modified Heliocentric Julian date */ +double ra; /* Right ascension (degrees) */ +double dec; /* Declination (degrees) */ +int sys; /* J2000, B1950, GALACTIC, ECLIPTIC */ +{ + double lt; /* Light travel difference to the Sun (days) */ + double hjd; /* Heliocentric Julian date */ + + hjd = mjd2jd (mhjd); + + lt = suntl (hjd, ra, dec, sys); + + /* Return Heliocentric Julian Date */ + return (jd2mjd (hjd - lt)); +} + + +/* MJD2MHJD-- convert modified geocentric Julian date tp + modified Heliocentric Julian Date */ + +double +mjd2mhjd (mjd, ra, dec, sys) + +double mjd; /* Julian date (geocentric) */ +double ra; /* Right ascension (degrees) */ +double dec; /* Declination (degrees) */ +int sys; /* J2000, B1950, GALACTIC, ECLIPTIC */ +{ + double lt; /* Light travel difference to the Sun (days) */ + double dj; /* Julian date (geocentric) */ + + dj = mjd2jd (mjd); + + lt = suntl (dj, ra, dec, sys); + + /* Return Heliocentric Julian Date */ + return (jd2mjd (dj + lt)); +} + + +/* SUNTL-- compute light travel time to heliocentric correction in days */ +/* Translated into C from IRAF SPP noao.astutils.asttools.asthjd.x */ + +static double +suntl (dj, ra, dec, sys) + +double dj; /* Julian date (geocentric) */ +double ra; /* Right ascension (degrees) */ +double dec; /* Declination (degrees) */ +int sys; /* J2000, B1950, GALACTIC, ECLIPTIC */ +{ + double t; /* Number of Julian centuries since J1900 */ + double manom; /* Mean anomaly of the Earth's orbit (degrees) */ + double lperi; /* Mean longitude of perihelion (degrees) */ + double oblq; /* Mean obliquity of the ecliptic (degrees) */ + double eccen; /* Eccentricity of the Earth's orbit (dimensionless) */ + double eccen2, eccen3; + double tanom; /* True anomaly (approximate formula) (radians) */ + double slong; /* True longitude of the Sun from the Earth (radians) */ + double rs; /* Distance to the sun (AU) */ + double lt; /* Light travel difference to the Sun (days) */ + double l; /* Longitude of star in orbital plane of Earth (radians) */ + double b; /* Latitude of star in orbital plane of Earth (radians) */ + double epoch; /* Epoch of obervation */ + double rs1,rs2; + + t = (dj - 2415020.0) / 36525.0; + + /* Compute earth orbital parameters */ + manom = 358.47583 + (t * (35999.04975 - t * (0.000150 + t * 0.000003))); + lperi = 101.22083 + (t * (1.7191733 + t * (0.000453 + t * 0.000003))); + oblq = 23.452294 - (t * (0.0130125 + t * (0.00000164 - t * 0.000000503))); + eccen = 0.01675104 - (t * (0.00004180 + t * 0.000000126)); + eccen2 = eccen * eccen; + eccen3 = eccen * eccen2; + + /* Convert to principle angles */ + manom = manom - (360.0 * (dint) (manom / 360.0)); + lperi = lperi - (360.0 * (dint) (lperi / 360.0)); + + /* Convert to radians */ + manom = degrad (manom); + lperi = degrad (lperi); + oblq = degrad (oblq); + + /* True anomaly */ + tanom = manom + (2 * eccen - 0.25 * eccen3) * sin (manom) + + 1.25 * eccen2 * sin (2 * manom) + + 13./12. * eccen3 * sin (3 * manom); + + /* Distance to the Sun */ + rs1 = 1.0 - eccen2; + rs2 = 1.0 + (eccen * cos (tanom)); + rs = rs1 / rs2; + + /* True longitude of the Sun seen from the Earth */ + slong = lperi + tanom + PI; + + /* Longitude and latitude of star in orbital plane of the Earth */ + epoch = jd2ep (dj); + wcscon (sys, WCS_ECLIPTIC, 0.0, 0.0, &ra, &dec, epoch); + l = degrad (ra); + b = degrad (dec); + + /* Light travel difference to the Sun */ + lt = -0.005770 * rs * cos (b) * cos (l - slong); + + /* Return light travel difference */ + return (lt); +} + + +/* JD2DT-- convert Julian date to date as yyyy.mmdd and time as hh.mmssss */ + +void +jd2dt (dj,date,time) + +double dj; /* Julian date */ +double *date; /* Date as yyyy.mmdd (returned) */ +double *time; /* Time as hh.mmssxxxx (returned) */ +{ + int iyr,imon,iday,ihr,imn; + double sec; + + /* Convert Julian Date to date and time */ + jd2i (dj, &iyr, &imon, &iday, &ihr, &imn, &sec, 4); + + /* Convert date to yyyy.mmdd */ + if (iyr < 0) { + *date = (double) (-iyr) + 0.01 * (double) imon + 0.0001 * (double) iday; + *date = -(*date); + } + else + *date = (double) iyr + 0.01 * (double) imon + 0.0001 * (double) iday; + + /* Convert time to hh.mmssssss */ + *time = (double) ihr + 0.01 * (double) imn + 0.0001 * sec; + + return; +} + + +/* JD2I-- convert Julian date to date as year, month, and day, and time hours, + minutes, and seconds */ +/* after Fliegel and Van Flander, CACM 11, 657 (1968) */ + + +void +jd2i (dj, iyr, imon, iday, ihr, imn, sec, ndsec) + +double dj; /* Julian date */ +int *iyr; /* year (returned) */ +int *imon; /* month (returned) */ +int *iday; /* day (returned) */ +int *ihr; /* hours (returned) */ +int *imn; /* minutes (returned) */ +double *sec; /* seconds (returned) */ +int ndsec; /* Number of decimal places in seconds (0=int) */ + +{ + double tsec; + double frac, dts, ts, sday; + int jd, l, n, i, j; + + tsec = jd2ts (dj); + /* ts2i (tsec, iyr, imon, iday, ihr, imn, sec, ndsec); */ + + /* Round seconds to 0 - 4 decimal places */ + if (tsec < 0.0) + dts = -0.5; + else + dts = 0.5; + if (ndsec < 1) + ts = dint (tsec + dts); + else if (ndsec < 2) + ts = dint (tsec * 10.0 + dts) / 10.0; + else if (ndsec < 3) + ts = dint (tsec * 100.0 + dts) / 100.0; + else if (ndsec < 4) + ts = dint (tsec * 1000.0 + dts) / 1000.0; + else + ts = dint (tsec * 10000.0 + dts) / 10000.0; + + /* Convert back to Julian Date */ + dj = ts2jd (ts); + + /* Compute time from fraction of a day */ + frac = dmod (dj, 1.0); + if (frac < 0.5) { + jd = (int) (dj - frac); + sday = (frac + 0.5) * 86400.0; + } + else { + jd = (int) (dj - frac) + 1; + sday = (frac - 0.5) * 86400.0; + } + + *ihr = (int) (sday / 3600.0); + sday = sday - (double) (*ihr * 3600); + *imn = (int) (sday / 60.0); + *sec = sday - (double) (*imn * 60); + + /* Compute day, month, year */ + l = jd + 68569; + n = (4 * l) / 146097; + l = l - (146097 * n + 3) / 4; + i = (4000 * (l + 1)) / 1461001; + l = l - (1461 * i) / 4 + 31; + j = (80 * l) / 2447; + *iday = l - (2447 * j) / 80; + l = j / 11; + *imon = j + 2 - (12 * l); + *iyr = 100 * (n - 49) + i + l; + + return; +} + + +/* JD2MJD-- convert Julian Date to Modified Julian Date */ + +double +jd2mjd (dj) + +double dj; /* Julian Date */ + +{ + return (dj - 2400000.5); +} + + +/* JD2EP-- convert Julian date to fractional year as used in epoch */ + +double +jd2ep (dj) + +double dj; /* Julian date */ + +{ + double date, time; + jd2dt (dj, &date, &time); + return (dt2ep (date, time)); +} + + +/* JD2EPB-- convert Julian date to Besselian epoch */ + +double +jd2epb (dj) + +double dj; /* Julian date */ + +{ + return (1900.0 + (dj - 2415020.31352) / 365.242198781); +} + + +/* JD2EPJ-- convert Julian date to Julian epoch */ + +double +jd2epj (dj) + +double dj; /* Julian date */ + +{ + return (2000.0 + (dj - 2451545.0) / 365.25); +} + + +/* LT2DT-- Return local time as yyyy.mmdd and time as hh.mmssss */ + +void +lt2dt(date, time) + +double *date; /* Date as yyyy.mmdd (returned) */ +double *time; /* Time as hh.mmssxxxx (returned) */ + +{ + time_t tsec; + struct timeval tp; + struct timezone tzp; + struct tm *ts; + + gettimeofday (&tp,&tzp); + + tsec = tp.tv_sec; + ts = localtime (&tsec); + + if (ts->tm_year < 1000) + *date = (double) (ts->tm_year + 1900); + else + *date = (double) ts->tm_year; + *date = *date + (0.01 * (double) (ts->tm_mon + 1)); + *date = *date + (0.0001 * (double) ts->tm_mday); + *time = (double) ts->tm_hour; + *time = *time + (0.01 * (double) ts->tm_min); + *time = *time + (0.0001 * (double) ts->tm_sec); + + return; +} + + +/* LT2FD-- Return current local time as FITS ISO date string */ + +char * +lt2fd() +{ + time_t tsec; + struct tm *ts; + struct timeval tp; + struct timezone tzp; + int month, day, year, hour, minute, second; + char *isotime; + + gettimeofday (&tp,&tzp); + tsec = tp.tv_sec; + + ts = localtime (&tsec); + + year = ts->tm_year; + if (year < 1000) + year = year + 1900; + month = ts->tm_mon + 1; + day = ts->tm_mday; + hour = ts->tm_hour; + minute = ts->tm_min; + second = ts->tm_sec; + + isotime = (char *) calloc (32, sizeof (char)); + sprintf (isotime, "%04d-%02d-%02dT%02d:%02d:%02d", + year, month, day, hour, minute, second); + return (isotime); +} + + +/* LT2TSI-- Return local time as IRAF seconds since 1980-01-01 00:00 */ + +int +lt2tsi() +{ + return ((int)(lt2ts() - 946684800.0)); +} + + +/* LT2TSU-- Return local time as Unix seconds since 1970-01-01 00:00 */ + +time_t +lt2tsu() +{ + return ((time_t)(lt2ts() - 631152000.0)); +} + +/* LT2TS-- Return local time as Unix seconds since 1950-01-01 00:00 */ + +double +lt2ts() +{ + double tsec; + char *datestring; + datestring = lt2fd(); + tsec = fd2ts (datestring); + free (datestring); + return (tsec); +} + + +/* MJD2DT-- convert Modified Julian Date to date (yyyy.mmdd) time (hh.mmssss) */ + +void +mjd2dt (dj,date,time) + +double dj; /* Modified Julian Date */ +double *date; /* Date as yyyy.mmdd (returned) + yyyy = calendar year (e.g. 1973) + mm = calendar month (e.g. 04 = april) + dd = calendar day (e.g. 15) */ +double *time; /* Time as hh.mmssxxxx (returned) + *if time<0, it is time as -(fraction of a day) + hh = hour of day (0 .le. hh .le. 23) + nn = minutes (0 .le. nn .le. 59) + ss = seconds (0 .le. ss .le. 59) + xxxx = tenths of milliseconds (0 .le. xxxx .le. 9999) */ +{ + double tsec; + + tsec = jd2ts (dj + 2400000.5); + ts2dt (tsec, date, time); + + return; +} + + +/* MJD2I-- convert Modified Julian Date to date as year, month, day and + time as hours, minutes, seconds */ + +void +mjd2i (dj, iyr, imon, iday, ihr, imn, sec, ndsec) + +double dj; /* Modified Julian Date */ +int *iyr; /* year (returned) */ +int *imon; /* month (returned) */ +int *iday; /* day (returned) */ +int *ihr; /* hours (returned) */ +int *imn; /* minutes (returned) */ +double *sec; /* seconds (returned) */ +int ndsec; /* Number of decimal places in seconds (0=int) */ + +{ + double tsec; + + tsec = jd2ts (dj + 2400000.5); + ts2i (tsec, iyr, imon, iday, ihr, imn, sec, ndsec); + return; +} + + +/* MJD2DOY-- convert Modified Julian Date to Year,Day-of-Year */ + +void +mjd2doy (dj, year, doy) + +double dj; /* Modified Julian Date */ +int *year; /* Year (returned) */ +double *doy; /* Day of year with fraction (returned) */ + +{ + jd2doy (dj + 2400000.5, year, doy); + return; +} + + +/* MJD2JD-- convert Modified Julian Date to Julian Date */ + +double +mjd2jd (dj) + +double dj; /* Modified Julian Date */ + +{ + return (dj + 2400000.5); +} + + +/* MJD2EP-- convert Modified Julian Date to fractional year */ + +double +mjd2ep (dj) + +double dj; /* Modified Julian Date */ + +{ + double date, time; + jd2dt (dj + 2400000.5, &date, &time); + return (dt2ep (date, time)); +} + + +/* MJD2EPB-- convert Modified Julian Date to Besselian epoch */ + +double +mjd2epb (dj) + +double dj; /* Modified Julian Date */ + +{ + return (1900.0 + (dj - 15019.81352) / 365.242198781); +} + + +/* MJD2EPJ-- convert Modified Julian Date to Julian epoch */ + +double +mjd2epj (dj) + +double dj; /* Modified Julian Date */ + +{ + return (2000.0 + (dj - 51544.5) / 365.25); +} + + +/* MJD2FD-- convert modified Julian date to FITS date, yyyy-mm-ddThh:mm:ss.ss */ + +char * +mjd2fd (dj) + +double dj; /* Modified Julian date */ +{ + return (jd2fd (dj + 2400000.5)); +} + + +/* MJD2TS-- convert modified Julian date to seconds since 1950.0 */ + +double +mjd2ts (dj) + +double dj; /* Modified Julian date */ +{ + return ((dj - 33282.0) * 86400.0); +} + + +/* EP2FD-- convert fractional year to FITS date, yyyy-mm-ddThh:mm:ss.ss */ + +char * +ep2fd (epoch) + +double epoch; /* Date as fractional year */ +{ + double tsec; /* seconds since 1950.0 (returned) */ + tsec = ep2ts (epoch); + return (ts2fd (tsec)); +} + + +/* EPB2FD-- convert Besselian epoch to FITS date, yyyy-mm-ddThh:mm:ss.ss */ + +char * +epb2fd (epoch) + +double epoch; /* Besselian epoch (fractional 365.242198781-day years) */ +{ + double dj; /* Julian Date */ + dj = epb2jd (epoch); + return (jd2fd (dj)); +} + + +/* EPJ2FD-- convert Julian epoch to FITS date, yyyy-mm-ddThh:mm:ss.ss */ + +char * +epj2fd (epoch) + +double epoch; /* Julian epoch (fractional 365.25-day years) */ +{ + double dj; /* Julian Date */ + dj = epj2jd (epoch); + return (jd2fd (dj)); +} + + +/* EP2TS-- convert fractional year to seconds since 1950.0 */ + +double +ep2ts (epoch) + +double epoch; /* Date as fractional year */ +{ + double dj; + dj = ep2jd (epoch); + return ((dj - 2433282.5) * 86400.0); +} + + +/* EPB2TS-- convert Besselian epoch to seconds since 1950.0 */ + +double +epb2ts (epoch) + +double epoch; /* Besselian epoch (fractional 365.242198781-day years) */ +{ + double dj; + dj = epb2jd (epoch); + return ((dj - 2433282.5) * 86400.0); +} + + +/* EPJ2TS-- convert Julian epoch to seconds since 1950.0 */ + +double +epj2ts (epoch) + +double epoch; /* Julian epoch (fractional 365.25-day years) */ +{ + double dj; + dj = epj2jd (epoch); + return ((dj - 2433282.5) * 86400.0); +} + + +/* EPB2EP-- convert Besselian epoch to fractional years */ + +double +epb2ep (epoch) + +double epoch; /* Besselian epoch (fractional 365.242198781-day years) */ +{ + double dj; + dj = epb2jd (epoch); + return (jd2ep (dj)); +} + + +/* EP2EPB-- convert fractional year to Besselian epoch */ + +double +ep2epb (epoch) + +double epoch; /* Fractional year */ +{ + double dj; + dj = ep2jd (epoch); + return (jd2epb (dj)); +} + + +/* EPJ2EP-- convert Julian epoch to fractional year */ + +double +epj2ep (epoch) + +double epoch; /* Julian epoch (fractional 365.25-day years) */ +{ + double dj; + dj = epj2jd (epoch); + return (jd2ep (dj)); +} + + +/* EP2EPJ-- convert fractional year to Julian epoch */ + +double +ep2epj (epoch) + +double epoch; /* Fractional year */ +{ + double dj; + dj = ep2jd (epoch); + return (jd2epj (dj)); +} + + +/* EP2I-- convert fractional year to year month day hours min sec */ + +void +ep2i (epoch, iyr, imon, iday, ihr, imn, sec, ndsec) + +double epoch; /* Date as fractional year */ +int *iyr; /* year (returned) */ +int *imon; /* month (returned) */ +int *iday; /* day (returned) */ +int *ihr; /* hours (returned) */ +int *imn; /* minutes (returned) */ +double *sec; /* seconds (returned) */ +int ndsec; /* Number of decimal places in seconds (0=int) */ +{ + double date, time; + + ep2dt (epoch, &date, &time); + dt2i (date, time, iyr,imon,iday,ihr,imn,sec, ndsec); + return; +} + + +/* EPB2I-- convert Besselian epoch to year month day hours min sec */ + +void +epb2i (epoch, iyr, imon, iday, ihr, imn, sec, ndsec) + +double epoch; /* Besselian epoch (fractional 365.242198781-day years) */ +int *iyr; /* year (returned) */ +int *imon; /* month (returned) */ +int *iday; /* day (returned) */ +int *ihr; /* hours (returned) */ +int *imn; /* minutes (returned) */ +double *sec; /* seconds (returned) */ +int ndsec; /* Number of decimal places in seconds (0=int) */ +{ + double date, time; + + epb2dt (epoch, &date, &time); + dt2i (date, time, iyr,imon,iday,ihr,imn,sec, ndsec); + return; +} + + +/* EPJ2I-- convert Julian epoch to year month day hours min sec */ + +void +epj2i (epoch, iyr, imon, iday, ihr, imn, sec, ndsec) + +double epoch; /* Julian epoch (fractional 365.25-day years) */ +int *iyr; /* year (returned) */ +int *imon; /* month (returned) */ +int *iday; /* day (returned) */ +int *ihr; /* hours (returned) */ +int *imn; /* minutes (returned) */ +double *sec; /* seconds (returned) */ +int ndsec; /* Number of decimal places in seconds (0=int) */ +{ + double date, time; + + epj2dt (epoch, &date, &time); + dt2i (date, time, iyr,imon,iday,ihr,imn,sec, ndsec); + return; +} + + +/* EP2JD-- convert fractional year as used in epoch to Julian date */ + +double +ep2jd (epoch) + +double epoch; /* Date as fractional year */ + +{ + double dj; /* Julian date (returned)*/ + double date, time; + + ep2dt (epoch, &date, &time); + dj = dt2jd (date, time); + return (dj); +} + + +/* EPB2JD-- convert Besselian epoch to Julian Date */ + +double +epb2jd (epoch) + +double epoch; /* Besselian epoch (fractional 365.242198781-day years) */ + +{ + return (2415020.31352 + ((epoch - 1900.0) * 365.242198781)); +} + + +/* EPJ2JD-- convert Julian epoch to Julian Date */ + +double +epj2jd (epoch) + +double epoch; /* Julian epoch (fractional 365.25-day years) */ + +{ + return (2451545.0 + ((epoch - 2000.0) * 365.25)); +} + + +/* EP2MJD-- convert fractional year as used in epoch to modified Julian date */ + +double +ep2mjd (epoch) + +double epoch; /* Date as fractional year */ + +{ + double dj; /* Julian date (returned)*/ + double date, time; + + ep2dt (epoch, &date, &time); + dj = dt2jd (date, time); + return (dj - 2400000.5); +} + + +/* EPB2MJD-- convert Besselian epoch to modified Julian Date */ + +double +epb2mjd (epoch) + +double epoch; /* Besselian epoch (fractional 365.242198781-day years) */ + +{ + return (15019.81352 + ((epoch - 1900.0) * 365.242198781)); +} + + +/* EPJ2MJD-- convert Julian epoch to modified Julian Date */ + +double +epj2mjd (epoch) + +double epoch; /* Julian epoch (fractional 365.25-day years) */ + +{ + return (51544.5 + ((epoch - 2000.0) * 365.25)); +} + + + +/* EPB2EPJ-- convert Besselian epoch to Julian epoch */ + +double +epb2epj (epoch) + +double epoch; /* Besselian epoch (fractional 365.242198781-day years) */ +{ + double dj; /* Julian date */ + dj = epb2jd (epoch); + return (jd2epj (dj)); +} + + +/* EPJ2EPB-- convert Julian epoch to Besselian epoch */ + +double +epj2epb (epoch) + +double epoch; /* Julian epoch (fractional 365.25-day years) */ +{ + double dj; /* Julian date */ + dj = epj2jd (epoch); + return (jd2epb (dj)); +} + + +/* JD2FD-- convert Julian date to FITS date, yyyy-mm-ddThh:mm:ss.ss */ + +char * +jd2fd (dj) + +double dj; /* Julian date */ +{ + double tsec; /* seconds since 1950.0 (returned) */ + tsec = (dj - 2433282.5) * 86400.0; + return (ts2fd (tsec)); +} + + +/* JD2TS-- convert Julian date to seconds since 1950.0 */ + +double +jd2ts (dj) + +double dj; /* Julian date */ +{ + return ((dj - 2433282.5) * 86400.0); +} + + +/* JD2TSI-- convert Julian date to IRAF seconds since 1980-01-01T0:00 */ + +int +jd2tsi (dj) + +double dj; /* Julian date */ +{ + double ts; + ts = (dj - 2444239.5) * 86400.0; + return ((int) ts); +} + + +/* JD2TSU-- convert Julian date to Unix seconds since 1970-01-01T0:00 */ + +time_t +jd2tsu (dj) + +double dj; /* Julian date */ +{ + return ((time_t)((dj - 2440587.5) * 86400.0)); +} + + +/* DT2DOY-- convert yyyy.mmdd hh.mmss to year and day of year */ + +void +dt2doy (date, time, year, doy) + +double date; /* Date as yyyy.mmdd */ +double time; /* Time as hh.mmssxxxx */ +int *year; /* Year (returned) */ +double *doy; /* Day of year with fraction (returned) */ +{ + double dj; /* Julian date */ + double dj0; /* Julian date on January 1 0:00 */ + double date0; /* January first of date's year */ + double dyear; + + dyear = floor (date); + date0 = dyear + 0.0101; + dj0 = dt2jd (date0, 0.0); + dj = dt2jd (date, time); + *year = (int) (dyear + 0.00000001); + *doy = dj - dj0 + 1.0; + return; +} + + +/* DOY2DT-- convert year and day of year to yyyy.mmdd hh.mmss */ + +void +doy2dt (year, doy, date, time) + +int year; /* Year */ +double doy; /* Day of year with fraction */ +double *date; /* Date as yyyy.mmdd (returned) */ +double *time; /* Time as hh.mmssxxxx (returned) */ +{ + double dj; /* Julian date */ + double dj0; /* Julian date on January 1 0:00 */ + double date0; /* January first of date's year */ + + date0 = year + 0.0101; + dj0 = dt2jd (date0, 0.0); + dj = dj0 + doy - 1.0; + jd2dt (dj, date, time); + return; +} + + +/* DOY2EP-- convert year and day of year to fractional year as used in epoch */ + +double +doy2ep (year, doy) + +int year; /* Year */ +double doy; /* Day of year with fraction */ +{ + double date, time; + doy2dt (year, doy, &date, &time); + return (dt2ep (date, time)); +} + + + +/* DOY2EPB-- convert year and day of year to Besellian epoch */ + +double +doy2epb (year, doy) + +int year; /* Year */ +double doy; /* Day of year with fraction */ +{ + double dj; + dj = doy2jd (year, doy); + return (jd2epb (dj)); +} + + +/* DOY2EPJ-- convert year and day of year to Julian epoch */ + +double +doy2epj (year, doy) + +int year; /* Year */ +double doy; /* Day of year with fraction */ +{ + double dj; + dj = doy2jd (year, doy); + return (jd2epj (dj)); +} + + +/* DOY2FD-- convert year and day of year to FITS date */ + +char * +doy2fd (year, doy) + +int year; /* Year */ +double doy; /* Day of year with fraction */ +{ + double dj; /* Julian date */ + + dj = doy2jd (year, doy); + return (jd2fd (dj)); +} + + +/* DOY2JD-- convert year and day of year to Julian date */ + +double +doy2jd (year, doy) + +int year; /* Year */ +double doy; /* Day of year with fraction */ +{ + double dj0; /* Julian date */ + double date; /* Date as yyyy.mmdd (returned) */ + double time; /* Time as hh.mmssxxxx (returned) */ + + date = (double) year + 0.0101; + time = 0.0; + dj0 = dt2jd (date, time); + return (dj0 + doy - 1.0); +} + + +/* DOY2MJD-- convert year and day of year to Julian date */ + +double +doy2mjd (year, doy) + +int year; /* Year */ +double doy; /* Day of year with fraction */ +{ + double dj0; /* Julian date */ + double date; /* Date as yyyy.mmdd (returned) */ + double time; /* Time as hh.mmssxxxx (returned) */ + + date = (double) year + 0.0101; + time = 0.0; + dj0 = dt2jd (date, time); + return (dj0 + doy - 1.0 - 2400000.5); +} + + +/* DOY2TSU-- convert from FITS date to Unix seconds since 1970-01-01T0:00 */ + +time_t +doy2tsu (year, doy) + +int year; /* Year */ +double doy; /* Day of year with fraction */ +{ + double dj; + dj = doy2jd (year, doy); + return ((time_t)jd2ts (dj)); +} + + +/* DOY2TSI-- convert from FITS date to IRAF seconds since 1980-01-01T0:00 */ + +int +doy2tsi (year, doy) + +int year; /* Year */ +double doy; /* Day of year with fraction */ +{ + double dj; + dj = doy2jd (year, doy); + return ((int)jd2tsi (dj)); +} + + +/* DOY2TS-- convert year, day of year to seconds since 1950 */ + +double +doy2ts (year, doy) + +int year; /* Year */ +double doy; /* Day of year with fraction */ +{ + double dj; + dj = doy2jd (year, doy); + return (jd2ts (dj)); +} + + +/* FD2DOY-- convert FITS date to year and day of year */ + +void +fd2doy (string, year, doy) + +char *string; /* FITS date string, which may be: + fractional year + dd/mm/yy (FITS standard before 2000) + dd-mm-yy (nonstandard use before 2000) + yyyy-mm-dd (FITS standard after 1999) + yyyy-mm-ddThh:mm:ss.ss (FITS standard after 1999) */ +int *year; /* Year (returned) */ +double *doy; /* Day of year with fraction (returned) */ +{ + double dj; /* Julian date */ + + dj = fd2jd (string); + jd2doy (dj, year, doy); + return; +} + + +/* JD2DOY-- convert Julian date to year and day of year */ + +void +jd2doy (dj, year, doy) + +double dj; /* Julian date */ +int *year; /* Year (returned) */ +double *doy; /* Day of year with fraction (returned) */ +{ + double date; /* Date as yyyy.mmdd (returned) */ + double time; /* Time as hh.mmssxxxx (returned) */ + double dj0; /* Julian date at 0:00 on 1/1 */ + double dyear; + + jd2dt (dj, &date, &time); + *year = (int) date; + dyear = (double) *year; + dj0 = dt2jd (dyear+0.0101, 0.0); + *doy = dj - dj0 + 1.0; + return; +} + + +/* TS2JD-- convert seconds since 1950.0 to Julian date */ + +double +ts2jd (tsec) + +double tsec; /* seconds since 1950.0 */ +{ + return (2433282.5 + (tsec / 86400.0)); +} + + +/* TS2MJD-- convert seconds since 1950.0 to modified Julian date */ + +double +ts2mjd (tsec) + +double tsec; /* seconds since 1950.0 */ +{ + return (33282.0 + (tsec / 86400.0)); +} + + +/* TS2EP-- convert seconds since 1950.0 to fractional year as used in epoch */ + +double +ts2ep (tsec) + +double tsec; /* Seconds since 1950.0 */ + +{ + double date, time; + ts2dt (tsec, &date, &time); + return (dt2ep (date, time)); +} + + +/* TS2EPB-- convert seconds since 1950.0 to Besselian epoch */ + +double +ts2epb (tsec) + +double tsec; /* Seconds since 1950.0 */ + +{ + double dj; /* Julian Date */ + dj = ts2jd (tsec); + return (jd2epb (dj)); +} + + +/* TS2EPB-- convert seconds since 1950.0 to Julian epoch */ + +double +ts2epj (tsec) + +double tsec; /* Seconds since 1950.0 */ + +{ + double dj; /* Julian Date */ + dj = ts2jd (tsec); + return (jd2epj (dj)); +} + + +/* DT2EP-- convert from date, time as yyyy.mmdd hh.mmsss to fractional year */ + +double +dt2ep (date, time) + +double date; /* Date as yyyy.mmdd + yyyy = calendar year (e.g. 1973) + mm = calendar month (e.g. 04 = april) + dd = calendar day (e.g. 15) */ +double time; /* Time as hh.mmssxxxx + *if time<0, it is time as -(fraction of a day) + hh = hour of day (0 .le. hh .le. 23) + nn = minutes (0 .le. nn .le. 59) + ss = seconds (0 .le. ss .le. 59) + xxxx = tenths of milliseconds (0 .le. xxxx .le. 9999) */ +{ + double epoch; /* Date as fractional year (returned) */ + double dj, dj0, dj1, date0, time0, date1; + + dj = dt2jd (date, time); + if (date == 0.0) + epoch = dj / 365.2422; + else { + time0 = 0.0; + date0 = dint (date) + 0.0101; + date1 = dint (date) + 1.0101; + dj0 = dt2jd (date0, time0); + dj1 = dt2jd (date1, time0); + epoch = dint (date) + ((dj - dj0) / (dj1 - dj0)); + } + return (epoch); +} + + +/* DT2EPB-- convert from date, time as yyyy.mmdd hh.mmsss to Besselian epoch */ + +double +dt2epb (date, time) + +double date; /* Date as yyyy.mmdd + yyyy = calendar year (e.g. 1973) + mm = calendar month (e.g. 04 = april) + dd = calendar day (e.g. 15) */ +double time; /* Time as hh.mmssxxxx + *if time<0, it is time as -(fraction of a day) + hh = hour of day (0 .le. hh .le. 23) + nn = minutes (0 .le. nn .le. 59) + ss = seconds (0 .le. ss .le. 59) + xxxx = tenths of milliseconds (0 .le. xxxx .le. 9999) */ +{ + double dj; /* Julian date */ + double epoch; /* Date as fractional year (returned) */ + dj = dt2jd (date, time); + if (date == 0.0) + epoch = dj / 365.242198781; + else + epoch = jd2epb (dj); + return (epoch); +} + + +/* DT2EPJ-- convert from date, time as yyyy.mmdd hh.mmsss to Julian epoch */ + +double +dt2epj (date, time) + +double date; /* Date as yyyy.mmdd + yyyy = calendar year (e.g. 1973) + mm = calendar month (e.g. 04 = april) + dd = calendar day (e.g. 15) */ +double time; /* Time as hh.mmssxxxx + *if time<0, it is time as -(fraction of a day) + hh = hour of day (0 .le. hh .le. 23) + nn = minutes (0 .le. nn .le. 59) + ss = seconds (0 .le. ss .le. 59) + xxxx = tenths of milliseconds (0 .le. xxxx .le. 9999) */ +{ + double dj; /* Julian date */ + double epoch; /* Date as fractional year (returned) */ + dj = dt2jd (date, time); + if (date == 0.0) + epoch = dj / 365.25; + else + epoch = jd2epj (dj); + return (epoch); +} + + +/* EP2DT-- convert from fractional year to date, time as yyyy.mmdd hh.mmsss */ + +void +ep2dt (epoch, date, time) + +double epoch; /* Date as fractional year */ +double *date; /* Date as yyyy.mmdd (returned) + yyyy = calendar year (e.g. 1973) + mm = calendar month (e.g. 04 = april) + dd = calendar day (e.g. 15) */ +double *time; /* Time as hh.mmssxxxx (returned) + *if time<0, it is time as -(fraction of a day) + hh = hour of day (0 .le. hh .le. 23) + nn = minutes (0 .le. nn .le. 59) + ss = seconds (0 .le. ss .le. 59) + xxxx = tenths of milliseconds (0 .le. xxxx .le. 9999) */ +{ + double dj, dj0, dj1, date0, time0, date1, epochi, epochf; + + time0 = 0.0; + epochi = dint (epoch); + epochf = epoch - epochi; + date0 = epochi + 0.0101; + date1 = epochi + 1.0101; + dj0 = dt2jd (date0, time0); + dj1 = dt2jd (date1, time0); + dj = dj0 + epochf * (dj1 - dj0); + jd2dt (dj, date, time); + return; +} + + +/* EPB2DT-- convert from Besselian epoch to date, time as yyyy.mmdd hh.mmsss */ + +void +epb2dt (epoch, date, time) + +double epoch; /* Besselian epoch (fractional 365.242198781-day years) */ +double *date; /* Date as yyyy.mmdd (returned) + yyyy = calendar year (e.g. 1973) + mm = calendar month (e.g. 04 = april) + dd = calendar day (e.g. 15) */ +double *time; /* Time as hh.mmssxxxx (returned) + *if time<0, it is time as -(fraction of a day) + hh = hour of day (0 .le. hh .le. 23) + nn = minutes (0 .le. nn .le. 59) + ss = seconds (0 .le. ss .le. 59) + xxxx = tenths of milliseconds (0 .le. xxxx .le. 9999) */ +{ + double dj; /* Julian date */ + dj = epb2jd (epoch); + jd2dt (dj, date, time); +} + + +/* EPJ2DT-- convert from Julian epoch to date, time as yyyy.mmdd hh.mmsss */ + +void +epj2dt (epoch, date, time) + +double epoch; /* Julian epoch (fractional 365.25-day years) */ +double *date; /* Date as yyyy.mmdd (returned) + yyyy = calendar year (e.g. 1973) + mm = calendar month (e.g. 04 = april) + dd = calendar day (e.g. 15) */ +double *time; /* Time as hh.mmssxxxx (returned) + *if time<0, it is time as -(fraction of a day) + hh = hour of day (0 .le. hh .le. 23) + nn = minutes (0 .le. nn .le. 59) + ss = seconds (0 .le. ss .le. 59) + xxxx = tenths of milliseconds (0 .le. xxxx .le. 9999) */ +{ + double dj; /* Julian date */ + dj = epj2jd (epoch); + jd2dt (dj, date, time); +} + + +/* FD2JD-- convert FITS standard date to Julian date */ + +double +fd2jd (string) + +char *string; /* FITS date string, which may be: + fractional year + dd/mm/yy (FITS standard before 2000) + dd-mm-yy (nonstandard use before 2000) + yyyy-mm-dd (FITS standard after 1999) + yyyy-mm-ddThh:mm:ss.ss (FITS standard after 1999) */ +{ + double date, time; + + fd2dt (string, &date, &time); + return (dt2jd (date, time)); +} + + +/* FD2MJD-- convert FITS standard date to modified Julian date */ + +double +fd2mjd (string) + +char *string; /* FITS date string, which may be: + fractional year + dd/mm/yy (FITS standard before 2000) + dd-mm-yy (nonstandard use before 2000) + yyyy-mm-dd (FITS standard after 1999) + yyyy-mm-ddThh:mm:ss.ss (FITS standard after 1999) */ +{ + return (fd2jd (string) - 2400000.5); +} + + +/* FD2TSU-- convert from FITS date to Unix seconds since 1970-01-01T0:00 */ + +time_t +fd2tsu (string) + +char *string; /* FITS date string, which may be: + fractional year + dd/mm/yy (FITS standard before 2000) + dd-mm-yy (nonstandard use before 2000) + yyyy-mm-dd (FITS standard after 1999) + yyyy-mm-ddThh:mm:ss.ss (FITS standard after 1999) */ +{ + double date, time; + fd2dt (string, &date, &time); + return (dt2tsu (date, time)); +} + + +/* FD2TSI-- convert from FITS date to IRAF seconds since 1980-01-01T0:00 */ + +int +fd2tsi (string) + +char *string; /* FITS date string, which may be: + fractional year + dd/mm/yy (FITS standard before 2000) + dd-mm-yy (nonstandard use before 2000) + yyyy-mm-dd (FITS standard after 1999) + yyyy-mm-ddThh:mm:ss.ss (FITS standard after 1999) */ +{ + double date, time; + fd2dt (string, &date, &time); + return (dt2tsi (date, time)); +} + + +/* FD2TS-- convert FITS standard date to seconds since 1950 */ + +double +fd2ts (string) + +char *string; /* FITS date string, which may be: + fractional year + dd/mm/yy (FITS standard before 2000) + dd-mm-yy (nonstandard use before 2000) + yyyy-mm-dd (FITS standard after 1999) + yyyy-mm-ddThh:mm:ss.ss (FITS standard after 1999) */ +{ + double date, time; + fd2dt (string, &date, &time); + return (dt2ts (date, time)); +} + + +/* FD2FD-- convert any FITS standard date to ISO FITS standard date */ + +char * +fd2fd (string) + +char *string; /* FITS date string, which may be: + fractional year + dd/mm/yy (FITS standard before 2000) + dd-mm-yy (nonstandard use before 2000) + yyyy-mm-dd (FITS standard after 1999) + yyyy-mm-ddThh:mm:ss.ss (FITS standard after 1999) */ +{ + double date, time; + fd2dt (string, &date, &time); + return (dt2fd (date, time)); +} + + +/* FD2OF-- convert any FITS standard date to old FITS standard date time */ + +char * +fd2of (string) + +char *string; /* FITS date string, which may be: + fractional year + dd/mm/yy (FITS standard before 2000) + dd-mm-yy (nonstandard use before 2000) + yyyy-mm-dd (FITS standard after 1999) + yyyy-mm-ddThh:mm:ss.ss (FITS standard after 1999) */ +{ + int iyr,imon,iday,ihr,imn; + double sec; + + fd2i (string,&iyr,&imon,&iday,&ihr,&imn,&sec, 3); + + /* Convert to old FITS date format */ + string = (char *) calloc (32, sizeof (char)); + if (iyr < 1900) + sprintf (string, "*** date out of range ***"); + else if (iyr < 2000) + sprintf (string, "%02d/%02d/%02d %02d:%02d:%06.3f", + iday, imon, iyr-1900, ihr, imn, sec); + else if (iyr < 2900.0) + sprintf (string, "%02d/%02d/%3d %02d:%02d:%6.3f", + iday, imon, iyr-1900, ihr, imn, sec); + else + sprintf (string, "*** date out of range ***"); + return (string); +} + + +/* TAI-UTC from the U.S. Naval Observatory */ +/* ftp://maia.usno.navy.mil/ser7/tai-utc.dat */ +static double taijd[26]={2441317.5, 2441499.5, 2441683.5, 2442048.5, 2442413.5, + 2442778.5, 2443144.5, 2443509.5, 2443874.5, 2444239.5, 2444786.5, + 2445151.5, 2445516.5, 2446247.5, 2447161.5, 2447892.5, 2448257.5, + 2448804.5, 2449169.5, 2449534.5, 2450083.5, 2450630.5, 2451179.5, + 2453736.5, 2454832.5, 2456293.5}; +static double taidt[26]={10.0,11.0,12.0,13.0,14.0,15.0,16.0,17.0,18.0,19.0, + 20.0,21.0,22.0,23.0,24.0,25.0,26.0,27.0,28.0,29.0,30.0,31.0,32.0, + 33.0,34.0,35.0}; +static double dttab[173]={13.7,13.4,13.1,12.9,12.7,12.6,12.5,12.5,12.5,12.5, + 12.5,12.5,12.5,12.5,12.5,12.5,12.5,12.4,12.3,12.2,12.0,11.7,11.4, + 11.1,10.6,10.2, 9.6, 9.1, 8.6, 8.0, 7.5, 7.0, 6.6, 6.3, 6.0, 5.8, + 5.7, 5.6, 5.6, 5.6, 5.7, 5.8, 5.9, 6.1, 6.2, 6.3, 6.5, 6.6, 6.8, + 6.9, 7.1, 7.2, 7.3, 7.4, 7.5, 7.6, 7.7, 7.7, 7.8, 7.8,7.88,7.82, + 7.54, 6.97, 6.40, 6.02, 5.41, 4.10, 2.92, 1.82, 1.61, 0.10,-1.02, + -1.28,-2.69,-3.24,-3.64,-4.54,-4.71,-5.11,-5.40,-5.42,-5.20,-5.46, + -5.46,-5.79,-5.63,-5.64,-5.80,-5.66,-5.87,-6.01,-6.19,-6.64,-6.44, + -6.47,-6.09,-5.76,-4.66,-3.74,-2.72,-1.54,-0.02, 1.24, 2.64, 3.86, + 5.37, 6.14, 7.75, 9.13,10.46,11.53,13.36,14.65,16.01,17.20,18.24, + 19.06,20.25,20.95,21.16,22.25,22.41,23.03,23.49,23.62,23.86,24.49, + 24.34,24.08,24.02,24.00,23.87,23.95,23.86,23.93,23.73,23.92,23.96, + 24.02,24.33,24.83,25.30,25.70,26.24,26.77,27.28,27.78,28.25,28.71, + 29.15,29.57,29.97,30.36,30.72,31.07,31.35,31.68,32.18,32.68,33.15, + 33.59,34.00,34.47,35.03,35.73,36.54,37.43,38.29,39.20,40.18,41.17, + 42.23}; + + +/* TAI2FD-- convert from TAI in FITS format to UT in FITS format */ + +char * +tai2fd (string) + +char *string; /* FITS date string, which may be: + fractional year + dd/mm/yy (FITS standard before 2000) + dd-mm-yy (nonstandard use before 2000) + yyyy-mm-dd (FITS standard after 1999) + yyyy-mm-ddThh:mm:ss.ss (FITS standard after 1999) */ +{ + double dj0, dj, tsec, dt; + + dj0 = fd2jd (string); + dt = utdt (dj0); + dj = dj0 - (dt / 86400.0); + dt = utdt (dj); + tsec = fd2ts (string); + tsec = tsec - dt + 32.184; + return (ts2fd (tsec)); +} + + +/* FD2TAI-- convert from UT in FITS format to TAI in FITS format */ + +char * +fd2tai (string) + +char *string; /* FITS date string, which may be: + fractional year + dd/mm/yy (FITS standard before 2000) + dd-mm-yy (nonstandard use before 2000) + yyyy-mm-dd (FITS standard after 1999) + yyyy-mm-ddThh:mm:ss.ss (FITS standard after 1999) */ +{ + double dj, tsec, dt; + + dj = fd2jd (string); + dt = utdt (dj); + tsec = fd2ts (string); + tsec = tsec + dt - 32.184; + return (ts2fd (tsec)); +} + + +/* DT2TAI-- convert from UT as yyyy.mmdd hh.mmssss to TAI in same format */ + +void +dt2tai (date, time) +double *date; /* Date as yyyy.mmdd */ +double *time; /* Time as hh.mmssxxxx + *if time<0, it is time as -(fraction of a day) */ +{ + double dj, dt, tsec; + + dj = dt2jd (*date, *time); + dt = utdt (dj); + tsec = dt2ts (*date, *time); + tsec = tsec + dt - 32.184; + ts2dt (tsec, date, time); + return; +} + + +/* TAI2DT-- convert from TAI as yyyy.mmdd hh.mmssss to UT in same format */ + +void +tai2dt (date, time) +double *date; /* Date as yyyy.mmdd */ +double *time; /* Time as hh.mmssxxxx + *if time<0, it is time as -(fraction of a day) */ +{ + double dj, dt, tsec, tsec0; + + dj = dt2jd (*date, *time); + dt = utdt (dj); + tsec0 = dt2ts (*date, *time); + tsec = tsec0 + dt; + dj = ts2jd (tsec); + dt = utdt (dj); + tsec = tsec0 + dt + 32.184; + ts2dt (tsec, date, time); + return; +} + + +/* ET2FD-- convert from ET (or TDT or TT) in FITS format to UT in FITS format */ + +char * +et2fd (string) + +char *string; /* FITS date string, which may be: + fractional year + dd/mm/yy (FITS standard before 2000) + dd-mm-yy (nonstandard use before 2000) + yyyy-mm-dd (FITS standard after 1999) + yyyy-mm-ddThh:mm:ss.ss (FITS standard after 1999) */ +{ + double dj0, dj, tsec, dt; + + dj0 = fd2jd (string); + dt = utdt (dj0); + dj = dj0 - (dt / 86400.0); + dt = utdt (dj); + tsec = fd2ts (string); + tsec = tsec - dt; + return (ts2fd (tsec)); +} + + +/* FD2ET-- convert from UT in FITS format to ET (or TDT or TT) in FITS format */ + +char * +fd2et (string) + +char *string; /* FITS date string, which may be: + fractional year + dd/mm/yy (FITS standard before 2000) + dd-mm-yy (nonstandard use before 2000) + yyyy-mm-dd (FITS standard after 1999) + yyyy-mm-ddThh:mm:ss.ss (FITS standard after 1999) */ +{ + double dj, tsec, dt; + + dj = fd2jd (string); + dt = utdt (dj); + tsec = fd2ts (string); + tsec = tsec + dt; + return (ts2fd (tsec)); +} + + +/* DT2ET-- convert from UT as yyyy.mmdd hh.mmssss to ET in same format */ + +void +dt2et (date, time) +double *date; /* Date as yyyy.mmdd */ +double *time; /* Time as hh.mmssxxxx + *if time<0, it is time as -(fraction of a day) */ +{ + double dj, dt, tsec; + + dj = dt2jd (*date, *time); + dt = utdt (dj); + tsec = dt2ts (*date, *time); + tsec = tsec + dt; + ts2dt (tsec, date, time); + return; +} + + +/* EDT2DT-- convert from ET as yyyy.mmdd hh.mmssss to UT in same format */ + +void +edt2dt (date, time) +double *date; /* Date as yyyy.mmdd */ +double *time; /* Time as hh.mmssxxxx + *if time<0, it is time as -(fraction of a day) */ +{ + double dj, dt, tsec, tsec0; + + dj = dt2jd (*date, *time); + dt = utdt (dj); + tsec0 = dt2ts (*date, *time); + tsec = tsec0 + dt; + dj = ts2jd (tsec); + dt = utdt (dj); + tsec = tsec0 + dt; + ts2dt (tsec, date, time); + return; +} + + +/* JD2JED-- convert from Julian Date to Julian Ephemeris Date */ + +double +jd2jed (dj) + +double dj; /* Julian Date */ +{ + double dt; + + dt = utdt (dj); + return (dj + (dt / 86400.0)); +} + + +/* JED2JD-- convert from Julian Ephemeris Date to Julian Date */ + +double +jed2jd (dj) + +double dj; /* Julian Ephemeris Date */ +{ + double dj0, dt; + + dj0 = dj; + dt = utdt (dj); + dj = dj0 - (dt / 86400.0); + dt = utdt (dj); + return (dj - (dt / 86400.0)); +} + + +/* TS2ETS-- convert from UT in seconds since 1950-01-01 to ET in same format */ + +double +ts2ets (tsec) + +double tsec; +{ + double dj, dt; + + dj = ts2jd (tsec); + dt = utdt (dj); + return (tsec + dt); +} + + +/* ETS2TS-- convert from ET in seconds since 1950-01-01 to UT in same format */ + +double +ets2ts (tsec) + +double tsec; +{ + double dj, dj0, dt; + + dj0 = ts2jd (tsec); + dt = utdt (dj0); + dj = dj0 - (dt / 86400.0); + dt = utdt (dj); + return (tsec - dt); +} + + +/* UTDT-- Compute difference between UT and dynamical time (ET-UT) */ + +double +utdt (dj) + +double dj; /* Julian Date (UT) */ +{ + double dt, date, time, ts, ts1, ts0, date0, yfrac, diff, cj; + int i, iyr, iyear; + + /* If after 1972-01-01, use tabulated TAI-UT */ + if (dj >= 2441317.5) { + dt = 0.0; + for (i = 22; i > 0; i--) { + if (dj >= taijd[i]) + dt = taidt[i]; + } + dt = dt + 32.184; + } + + /* For 1800-01-01 to 1972-01-01, use table of ET-UT from AE */ + else if (dj >= 2378496.5) { + jd2dt (dj, &date, &time); + ts = jd2ts (dj); + iyear = (int) date; + iyr = iyear - 1800; + date0 = (double) iyear + 0.0101; + ts0 = dt2ts (date0, 0.0); + date0 = (double) (iyear + 1) + 0.0101; + ts1 = dt2ts (date0, 0.0); + yfrac = (ts - ts0) / (ts1 - ts0); + diff = dttab[iyr+1] - dttab[iyr]; + dt = dttab[iyr] + (diff * yfrac); + } + + /* Compute back to 1600 using formula from McCarthy and Babcock (1986) */ + else if (dj >= 2305447.5) { + cj = (dj - 2378496.5) / 36525.0; + dt = 5.156 + 13.3066 * (cj - 0.19) * (cj - 0.19); + } + + /* Compute back to 948 using formula from Stephenson and Morrison (1984) */ + else if (dj >= 2067309.5) { + cj = (dj - 2378496.5) / 36525.0; + dt = 25.5 * cj * cj; + } + + /*Compute back to 390 BC using formula from Stephenson and Morrison (1984)*/ + else if (dj >= 0.0) { + cj = (dj = 2378496.5) / 36525.0; + dt = 1360.0 + (320.0 * cj) + (44.3 * cj * cj); + } + + else + dt = 0.0; + return (dt); +} + + +/* FD2OFD-- convert any FITS standard date to old FITS standard date */ + +char * +fd2ofd (string) + +char *string; /* FITS date string, which may be: + fractional year + dd/mm/yy (FITS standard before 2000) + dd-mm-yy (nonstandard use before 2000) + yyyy-mm-dd (FITS standard after 1999) + yyyy-mm-ddThh:mm:ss.ss (FITS standard after 1999) */ +{ + int iyr,imon,iday,ihr,imn; + double sec; + + fd2i (string,&iyr,&imon,&iday,&ihr,&imn,&sec, 3); + + /* Convert to old FITS date format */ + string = (char *) calloc (32, sizeof (char)); + if (iyr < 1900) + sprintf (string, "*** date out of range ***"); + else if (iyr < 2000) + sprintf (string, "%02d/%02d/%02d", iday, imon, iyr-1900); + else if (iyr < 2900.0) + sprintf (string, "%02d/%02d/%3d", iday, imon, iyr-1900); + else + sprintf (string, "*** date out of range ***"); + return (string); +} + + +/* FD2OFT-- convert any FITS standard date to old FITS standard time */ + +char * +fd2oft (string) + +char *string; /* FITS date string, which may be: + fractional year + dd/mm/yy (FITS standard before 2000) + dd-mm-yy (nonstandard use before 2000) + yyyy-mm-dd (FITS standard after 1999) + yyyy-mm-ddThh:mm:ss.ss (FITS standard after 1999) */ +{ + int iyr,imon,iday,ihr,imn; + double sec; + + fd2i (string,&iyr,&imon,&iday,&ihr,&imn,&sec, 3); + + /* Convert to old FITS date format */ + string = (char *) calloc (32, sizeof (char)); + sprintf (string, "%02d:%02d:%06.3f", ihr, imn, sec); + return (string); +} + + +/* FD2DT-- convert FITS standard date to date, time as yyyy.mmdd hh.mmsss */ + +void +fd2dt (string, date, time) + +char *string; /* FITS date string, which may be: + fractional year + dd/mm/yy (FITS standard before 2000) + dd-mm-yy (nonstandard use before 2000) + yyyy-mm-dd (FITS standard after 1999) + yyyy-mm-ddThh:mm:ss.ss (FITS standard after 1999) */ +double *date; /* Date as yyyy.mmdd (returned) + yyyy = calendar year (e.g. 1973) + mm = calendar month (e.g. 04 = april) + dd = calendar day (e.g. 15) */ +double *time; /* Time as hh.mmssxxxx (returned) + *if time<0, it is time as -(fraction of a day) + hh = hour of day (0 .le. hh .le. 23) + nn = minutes (0 .le. nn .le. 59) + ss = seconds (0 .le. ss .le. 59) + xxxx = tenths of milliseconds (0 .le. xxxx .le. 9999) */ +{ + int iyr,imon,iday,ihr,imn; + double sec; + + fd2i (string,&iyr,&imon,&iday,&ihr,&imn,&sec, 4); + + /* Convert date to yyyy.mmdd */ + if (iyr < 0) { + *date = (double) (-iyr) + 0.01 * (double) imon + 0.0001 * (double) iday; + *date = -(*date); + } + else + *date = (double) iyr + 0.01 * (double) imon + 0.0001 * (double) iday; + + /* Convert time to hh.mmssssss */ + *time = (double) ihr + 0.01 * (double) imn + 0.0001 * sec; + + return; +} + + +/* FD2EP-- convert from FITS standard date to fractional year */ + +double +fd2ep (string) + +char *string; /* FITS date string, which may be: + yyyy.ffff (fractional year) + dd/mm/yy (FITS standard before 2000) + dd-mm-yy (nonstandard FITS use before 2000) + yyyy-mm-dd (FITS standard after 1999) + yyyy-mm-ddThh:mm:ss.ss (FITS standard after 1999) */ + +{ + double dj; /* Julian date */ + dj = fd2jd (string); + if (dj < 1.0) + return (dj / 365.2422); + else + return (jd2ep (dj)); +} + + +/* FD2EPB-- convert from FITS standard date to Besselian epoch */ + +double +fd2epb (string) + +char *string; /* FITS date string, which may be: + yyyy.ffff (fractional year) + dd/mm/yy (FITS standard before 2000) + dd-mm-yy (nonstandard FITS use before 2000) + yyyy-mm-dd (FITS standard after 1999) + yyyy-mm-ddThh:mm:ss.ss (FITS standard after 1999) */ + +{ + double dj; /* Julian date */ + dj = fd2jd (string); + if (dj < 1.0) + return (dj / 365.242198781); + else + return (jd2epb (dj)); +} + + +/* FD2EPJ-- convert from FITS standard date to Julian epoch */ + +double +fd2epj (string) + +char *string; /* FITS date string, which may be: + yyyy.ffff (fractional year) + dd/mm/yy (FITS standard before 2000) + dd-mm-yy (nonstandard FITS use before 2000) + yyyy-mm-dd (FITS standard after 1999) + yyyy-mm-ddThh:mm:ss.ss (FITS standard after 1999) */ + +{ + double dj; /* Julian date */ + dj = fd2jd (string); + if (dj < 1.0) + return (dj / 365.25); + else + return (jd2epj (dj)); +} + + +/* DT2TSU-- convert from date and time to Unix seconds since 1970-01-01T0:00 */ + +time_t +dt2tsu (date,time) + +double date; /* Date as yyyy.mmdd */ +double time; /* Time as hh.mmssxxxx + *if time<0, it is time as -(fraction of a day) */ +{ + return ((time_t)(dt2ts (date, time) - 631152000.0)); +} + + +/* DT2TSI-- convert from date and time to IRAF seconds since 1980-01-01T0:00 */ + +int +dt2tsi (date,time) + +double date; /* Date as yyyy.mmdd */ +double time; /* Time as hh.mmssxxxx + *if time<0, it is time as -(fraction of a day) */ +{ + return ((int)(dt2ts (date, time) - 946684800.0)); +} + + + +/* DT2TS-- convert from date, time as yyyy.mmdd hh.mmsss to sec since 1950.0 */ + +double +dt2ts (date,time) + +double date; /* Date as yyyy.mmdd + yyyy = calendar year (e.g. 1973) + mm = calendar month (e.g. 04 = april) + dd = calendar day (e.g. 15) */ +double time; /* Time as hh.mmssxxxx + *if time<0, it is time as -(fraction of a day) + hh = hour of day (0 .le. hh .le. 23) + nn = minutes (0 .le. nn .le. 59) + ss = seconds (0 .le. ss .le. 59) + xxxx = tenths of milliseconds (0 .le. xxxx .le. 9999) */ +{ + double tsec; /* Seconds past 1950.0 (returned) */ + + double dh,dm,dd; + int iy,im,id; + +/* Calculate the number of full years, months, and days already + * elapsed since 0h, March 1, -1 (up to most recent midnight). */ + + /* convert time of day to elapsed seconds */ + + /* If time is < 0, it is assumed to be a fractional day */ + if (time < 0.0) + tsec = time * -86400.0; + else { + dh = (int) (time + 0.0000000001); + dm = (int) (((time - dh) * 100.0) + 0.0000000001); + tsec = (time * 10000.0) - (dh * 10000.0) - (dm * 100.0); + tsec = (int) (tsec * 100000.0 + 0.0001) / 100000.0; + tsec = tsec + (dm * 60.0) + (dh * 3600.0); + } + + + /* Calculate the number of full months elapsed since + * the current or most recent March */ + if (date >= 0.0301) { + iy = (int) (date + 0.0000000001); + im = (int) (((date - (double) (iy)) * 10000.0) + 0.00000001); + id = im % 100; + im = (im / 100) + 9; + if (im < 12) iy = iy - 1; + im = im % 12; + id = id - 1; + + /* starting with March as month 0 and ending with the following + * February as month 11, the calculation of the number of days + * per month reduces to a simple formula. the following statement + * determines the number of whole days elapsed since 3/1/-1 and then + * subtracts the 712163 days between then and 1/1/1950. it converts + * the result to seconds and adds the accumulated seconds above. */ + id = id + ((im+1+im/6+im/11)/2 * 31) + ((im-im/6-im/11)/2 * 30) + + (iy / 4) - (iy / 100) + (iy / 400); + dd = (double) id + (365.0 * (double) iy) - 712163.0; + tsec = tsec + (dd * 86400.0); + } + + return (tsec); +} + + +/* TS2DT-- convert seconds since 1950.0 to date, time as yyyy.mmdd hh.mmssss */ + +void +ts2dt (tsec,date,time) + +double tsec; /* Seconds past 1950.0 */ +double *date; /* Date as yyyy.mmdd (returned) + yyyy = calendar year (e.g. 1973) + mm = calendar month (e.g. 04 = april) + dd = calendar day (e.g. 15) */ +double *time; /* Time as hh.mmssxxxx (returned) + *if time<0, it is time as -(fraction of a day) + hh = hour of day (0 .le. hh .le. 23) + nn = minutes (0 .le. nn .le. 59) + ss = seconds (0 .le. ss .le. 59) + xxxx = tenths of milliseconds (0 .le. xxxx .le. 9999) */ +{ + int iyr,imon,iday,ihr,imn; + double sec; + + ts2i (tsec,&iyr,&imon,&iday,&ihr,&imn,&sec, 4); + + /* Convert date to yyyy.mmdd */ + if (iyr < 0) { + *date = (double) (-iyr) + 0.01 * (double) imon + 0.0001 * (double) iday; + *date = -(*date); + } + else + *date = (double) iyr + 0.01 * (double) imon + 0.0001 * (double) iday; + + /* Convert time to hh.mmssssss */ + *time = (double) ihr + 0.01 * (double) imn + 0.0001 * sec; + + return; +} + + +/* TSI2DT-- Convert seconds since 1980-01-01 to date yyyy.ddmm, time hh.mmsss */ + +void +tsi2dt (isec,date,time) + +int isec; /* Seconds past 1980-01-01 */ +double *date; /* Date as yyyy.mmdd (returned) */ +double *time; /* Time as hh.mmssxxxx (returned) */ +{ + ts2dt (tsi2ts (isec), date, time); +} + + +/* TSI2FD-- Convert seconds since 1980-01-01 to FITS standard date string */ + +char * +tsi2fd (isec) + +int isec; /* Seconds past 1980-01-01 */ +{ + return (ts2fd (tsi2ts (isec))); +} + + +/* TSI2TS-- Convert seconds since 1980-01-01 to seconds since 1950-01-01 */ + +double +tsi2ts (isec) +int isec; /* Seconds past 1980-01-01 */ +{ + return ((double) isec + 946684800.0); +} + + +/* TSU2FD-- Convert seconds since 1970-01-01 to FITS standard date string */ + +char * +tsu2fd (isec) +time_t isec; /* Seconds past 1970-01-01 */ +{ + return (ts2fd (tsu2ts (isec))); +} + + +/* TSU2DT-- Convert seconds since 1970-01-01 to date yyyy.ddmm, time hh.mmsss */ + +void +tsu2dt (isec,date,time) +time_t isec; /* Seconds past 1970-01-01 */ +double *date; /* Date as yyyy.mmdd (returned) */ +double *time; /* Time as hh.mmssxxxx (returned) */ +{ + ts2dt (tsu2ts (isec), date, time); +} + + +/* TSU2TS-- Convert seconds since 1970-01-01 to seconds since 1950-01-01 */ + +double +tsu2ts (isec) +time_t isec; /* Seconds past 1970-01-01 */ +{ + return ((double) isec + 631152000.0); +} + +/* TSU2TSI-- UT seconds since 1970-01-01 to local seconds since 1980-01-01 */ + +int +tsu2tsi (isec) +time_t isec; /* Seconds past 1970-01-01 */ +{ + double date, time; + struct tm *ts; + + /* Get local time from UT seconds */ + ts = localtime (&isec); + if (ts->tm_year < 1000) + date = (double) (ts->tm_year + 1900); + else + date = (double) ts->tm_year; + date = date + (0.01 * (double) (ts->tm_mon + 1)); + date = date + (0.0001 * (double) ts->tm_mday); + time = (double) ts->tm_hour; + time = time + (0.01 * (double) ts->tm_min); + time = time + (0.0001 * (double) ts->tm_sec); + return ((int)(dt2ts (date, time) - 631152000.0)); +} + + +/* TS2FD-- convert seconds since 1950.0 to FITS date, yyyy-mm-ddThh:mm:ss.ss */ + +char * +ts2fd (tsec) + +double tsec; /* Seconds past 1950.0 */ +{ + double date, time; + + ts2dt (tsec, &date, &time); + return (dt2fd (date, time)); +} + + +/* TSD2FD-- convert seconds since start of day to FITS time, hh:mm:ss.ss */ + +char * +tsd2fd (tsec) + +double tsec; /* Seconds since start of day */ +{ + double date, time; + char *thms, *fdate; + int lfd, nbc; + + ts2dt (tsec, &date, &time); + fdate = dt2fd (date, time); + thms = (char *) calloc (16, 1); + lfd = strlen (fdate); + nbc = lfd - 11; + strncpy (thms, fdate+11, nbc); + return (thms); +} + + +/* TSD2DT-- convert seconds since start of day to hh.mmssss */ + +double +tsd2dt (tsec) + +double tsec; /* Seconds since start of day */ +{ + double date, time; + + ts2dt (tsec, &date, &time); + return (time); +} + + + +/* DT2I-- convert vigesimal date and time to year month day hours min sec */ + +void +dt2i (date, time, iyr, imon, iday, ihr, imn, sec, ndsec) + +double date; /* Date as yyyy.mmdd (returned) + yyyy = calendar year (e.g. 1973) + mm = calendar month (e.g. 04 = april) + dd = calendar day (e.g. 15) */ +double time; /* Time as hh.mmssxxxx (returned) + *if time<0, it is time as -(fraction of a day) + hh = hour of day (0 .le. hh .le. 23) + nn = minutes (0 .le. nn .le. 59) + ss = seconds (0 .le. ss .le. 59) + xxxx = tenths of milliseconds (0 .le. xxxx .le. 9999) */ +int *iyr; /* year (returned) */ +int *imon; /* month (returned) */ +int *iday; /* day (returned) */ +int *ihr; /* hours (returned) */ +int *imn; /* minutes (returned) */ +double *sec; /* seconds (returned) */ +int ndsec; /* Number of decimal places in seconds (0=int) */ + +{ + double t,d; + + t = time; + if (date < 0.0) + d = -date; + else + d = date; + + /* Extract components of time */ + *ihr = dint (t + 0.000000001); + t = 100.0 * (t - (double) *ihr); + *imn = dint (t + 0.0000001); + *sec = 100.0 * (t - (double) *imn); + + /* Extract components of date */ + *iyr = dint (d + 0.00001); + d = 100.0 * (d - (double) *iyr); + if (date < 0.0) + *iyr = - *iyr; + *imon = dint (d + 0.001); + d = 100.0 * (d - (double) *imon); + *iday = dint (d + 0.1); + + /* Make sure date and time are legal */ + fixdate (iyr, imon, iday, ihr, imn, sec, ndsec); + + return; +} + + +/* FD2I-- convert from FITS standard date to year, mon, day, hours, min, sec */ + +void +fd2i (string, iyr, imon, iday, ihr, imn, sec, ndsec) + +char *string; /* FITS date string, which may be: + yyyy.ffff (fractional year) + dd/mm/yy (FITS standard before 2000) + dd-mm-yy (nonstandard FITS use before 2000) + yyyy-mm-dd (FITS standard after 1999) + yyyy-mm-ddThh:mm:ss.ss (FITS standard after 1999) */ +int *iyr; /* year (returned) */ +int *imon; /* month (returned) */ +int *iday; /* day (returned) */ +int *ihr; /* hours (returned) */ +int *imn; /* minutes (returned) */ +double *sec; /* seconds (returned) */ +int ndsec; /* Number of decimal places in seconds (0=int) */ + +{ + double tsec, fday, hr, mn; + int i; + char *sstr, *dstr, *tstr, *cstr, *nval, *fstr; + + /* Initialize all returned data to zero */ + *iyr = 0; + *imon = 0; + *iday = 0; + *ihr = 0; + *imn = 0; + *sec = 0.0; + + /* Return if no input string */ + if (string == NULL) + return; + + /* Check for various non-numeric characters */ + sstr = strchr (string,'/'); + dstr = strchr (string,'-'); + if (dstr == string) + dstr = strchr (string+1, '-'); + fstr = strchr (string, '.'); + tstr = strchr (string,'T'); + if (tstr == NULL) + tstr = strchr (string, 'Z'); + if (tstr == NULL) + tstr = strchr (string, 'S'); + if (fstr != NULL && tstr != NULL && fstr > tstr) + fstr = NULL; + cstr = strchr (string,':'); + + /* Original FITS date format: dd/mm/yy */ + if (sstr > string) { + *sstr = '\0'; + *iday = (int) atof (string); + if (*iday > 31) { + *iyr = *iday; + if (*iyr >= 0 && *iyr <= 49) + *iyr = *iyr + 2000; + else if (*iyr < 1000) + *iyr = *iyr + 1900; + *sstr = '/'; + nval = sstr + 1; + sstr = strchr (nval,'/'); + if (sstr > string) { + *sstr = '\0'; + *imon = (int) atof (nval); + *sstr = '/'; + nval = sstr + 1; + *iday = (int) atof (nval); + } + } + else { + *sstr = '/'; + nval = sstr + 1; + sstr = strchr (nval,'/'); + if (sstr == NULL) + sstr = strchr (nval,'-'); + if (sstr > string) { + *sstr = '\0'; + *imon = (int) atof (nval); + *sstr = '/'; + nval = sstr + 1; + *iyr = (int) atof (nval); + if (*iyr >= 0 && *iyr <= 49) + *iyr = *iyr + 2000; + else if (*iyr < 1000) + *iyr = *iyr + 1900; + } + } + tstr = strchr (string,'_'); + if (tstr == NULL) + return; + } + + /* New FITS date format: yyyy-mm-ddThh:mm:ss[.sss] */ + else if (dstr > string) { + *dstr = '\0'; + *iyr = (int) atof (string); + *dstr = '-'; + nval = dstr + 1; + dstr = strchr (nval,'-'); + *imon = 1; + *iday = 1; + + /* Decode year, month, and day */ + if (dstr > string) { + *dstr = '\0'; + *imon = (int) atof (nval); + *dstr = '-'; + nval = dstr + 1; + if (tstr > string) + *tstr = '\0'; + *iday = (int) atof (nval); + + /* If fraction of a day is present, turn it into a time */ + if (fstr != NULL) { + fday = atof (fstr); + hr = fday * 24.0; + *ihr = (int) hr; + mn = 60.0 * (hr - (double) *ihr); + *imn = (int) mn; + *sec = 60.0 * (mn - (double) *imn); + } + + if (tstr > string) + *tstr = 'T'; + } + + /* If date is > 31, it is really year in old format */ + if (*iday > 31) { + i = *iyr; + if (*iday < 100) + *iyr = *iday + 1900; + else + *iyr = *iday; + *iday = i; + } + } + + /* In rare cases, a FITS time is entered as an epoch */ + else if (tstr == NULL && cstr == NULL && isnum (string)) { + tsec = ep2ts (atof (string)); + ts2i (tsec,iyr,imon,iday,ihr,imn,sec, ndsec); + return; + } + + /* Extract time, if it is present */ + if (tstr > string || cstr > string) { + if (tstr > string) + nval = tstr + 1; + else + nval = string; + cstr = strchr (nval,':'); + if (cstr > string) { + *cstr = '\0'; + *ihr = (int) atof (nval); + *cstr = ':'; + nval = cstr + 1; + cstr = strchr (nval,':'); + if (cstr > string) { + *cstr = '\0'; + *imn = (int) atof (nval); + *cstr = ':'; + nval = cstr + 1; + *sec = atof (nval); + } + else + *imn = (int) atof (nval); + } + else + *ihr = (int) atof (nval); + } + else + ndsec = -1; + + /* Make sure date and time are legal */ + fixdate (iyr, imon, iday, ihr, imn, sec, ndsec); + + return; +} + + +/* TS2I-- convert sec since 1950.0 to year month day hours minutes seconds */ + +void +ts2i (tsec,iyr,imon,iday,ihr,imn,sec, ndsec) + +double tsec; /* seconds since 1/1/1950 0:00 */ +int *iyr; /* year (returned) */ +int *imon; /* month (returned) */ +int *iday; /* day (returned) */ +int *ihr; /* hours (returned) */ +int *imn; /* minutes (returned) */ +double *sec; /* seconds (returned) */ +int ndsec; /* Number of decimal places in seconds (0=int) */ + +{ + double t,days, ts, dts; + int nc,nc4,nly,ny,m,im; + + /* Round seconds to 0 - 4 decimal places */ + ts = tsec + 61530883200.0; + if (ts < 0.0) + dts = -0.5; + else + dts = 0.5; + if (ndsec < 1) + t = dint (ts + dts) * 10000.0; + else if (ndsec < 2) + t = dint (ts * 10.0 + dts) * 1000.0; + else if (ndsec < 3) + t = dint (ts * 100.0 + dts) * 100.0; + else if (ndsec < 4) + t = dint (ts * 1000.0 + dts) * 10.0; + else + t = dint (ts * 10000.0 + dts); + ts = t / 10000.0; + + /* Time of day (hours, minutes, seconds */ + *ihr = (int) (dmod (ts/3600.0, 24.0)); + *imn = (int) (dmod (ts/60.0, 60.0)); + *sec = dmod (ts, 60.0); + + /* Number of days since 0 hr 0/0/0000 */ + days = dint ((t / 864000000.0) + 0.000001); + + /* Number of leap centuries (400 years) */ + nc4 = (int) ((days / 146097.0) + 0.00001); + + /* Number of centuries since last /400 */ + days = days - (146097.0 * (double) (nc4)); + nc = (int) ((days / 36524.0) + 0.000001); + if (nc > 3) nc = 3; + + /* Number of leap years since last century */ + days = days - (36524.0 * nc); + nly = (int) ((days / 1461.0) + 0.0000000001); + + /* Number of years since last leap year */ + days = days - (1461.0 * (double) nly); + ny = (int) ((days / 365.0) + 0.00000001); + if (ny > 3) ny = 3; + + /* Day of month */ + days = days - (365.0 * (double) ny); + if (days < 0) { + m = 0; + *iday = 29; + } + else { + *iday = (int) (days + 0.00000001) + 1; + for (m = 1; m <= 12; m++) { + im = (m + ((m - 1) / 5)) % 2; + /* fprintf (stderr,"%d %d %d %d\n", m, im, *iday, nc); */ + if (*iday-1 < im+30) break; + *iday = *iday - im - 30; + } + } + + /* Month */ + *imon = ((m+1) % 12) + 1; + + /* Year */ + *iyr = nc4*400 + nc*100 + nly*4 + ny + m/11; + + /* Make sure date and time are legal */ + fixdate (iyr, imon, iday, ihr, imn, sec, ndsec); + + return; +} + + +/* UT2DOY-- Current Universal Time as year, day of year */ + +void +ut2doy (year, doy) + +int *year; /* Year (returned) */ +double *doy; /* Day of year (returned) */ +{ + double date, time; + ut2dt (&date, &time); + dt2doy (date, time, year, doy); + return; +} + + +/* UT2DT-- Current Universal Time as date (yyyy.mmdd) and time (hh.mmsss) */ + +void +ut2dt(date, time) + +double *date; /* Date as yyyy.mmdd (returned) */ +double *time; /* Time as hh.mmssxxxx (returned) */ +{ + time_t tsec; + struct timeval tp; + struct timezone tzp; + struct tm *ts; + + gettimeofday (&tp,&tzp); + + tsec = tp.tv_sec; + ts = gmtime (&tsec); + + if (ts->tm_year < 1000) + *date = (double) (ts->tm_year + 1900); + else + *date = (double) ts->tm_year; + *date = *date + (0.01 * (double) (ts->tm_mon + 1)); + *date = *date + (0.0001 * (double) ts->tm_mday); + *time = (double) ts->tm_hour; + *time = *time + (0.01 * (double) ts->tm_min); + *time = *time + (0.0001 * (double) ts->tm_sec); + + return; +} + + +/* UT2EP-- Return current Universal Time as fractional year */ + +double +ut2ep() +{ + return (jd2ep (ut2jd())); +} + + +/* UT2EPB-- Return current Universal Time as Besselian epoch */ + +double +ut2epb() +{ + return (jd2epb (ut2jd())); +} + + +/* UT2EPJ-- Return current Universal Time as Julian epoch */ + +double +ut2epj() +{ + return (jd2epj (ut2jd())); +} + + +/* UT2FD-- Return current Universal Time as FITS ISO date string */ + +char * +ut2fd() +{ + int year, month, day, hour, minute, second; + time_t tsec; + struct timeval tp; + struct timezone tzp; + struct tm *ts; + char *isotime; + + gettimeofday (&tp,&tzp); + tsec = tp.tv_sec; + ts = gmtime (&tsec); + + year = ts->tm_year; + if (year < 1000) + year = year + 1900; + month = ts->tm_mon + 1; + day = ts->tm_mday; + hour = ts->tm_hour; + minute = ts->tm_min; + second = ts->tm_sec; + + isotime = (char *) calloc (32, sizeof (char)); + sprintf (isotime, "%04d-%02d-%02dT%02d:%02d:%02d", + year, month, day, hour, minute, second); + return (isotime); +} + + +/* UT2JD-- Return current Universal Time as Julian Date */ + +double +ut2jd() +{ + return (fd2jd (ut2fd())); +} + + +/* UT2MJD-- convert current UT to Modified Julian Date */ + +double +ut2mjd () + +{ + return (ut2jd() - 2400000.5); +} + +/* UT2TS-- current Universal Time as IRAF seconds since 1950-01-01T00:00 */ + +double +ut2ts() +{ + double tsec; + char *datestring; + datestring = ut2fd(); + tsec = fd2ts (datestring); + free (datestring); + return (tsec); +} + + +/* UT2TSI-- current Universal Time as IRAF seconds since 1980-01-01T00:00 */ + +int +ut2tsi() +{ + return ((int)(ut2ts() - 946684800.0)); +} + + +/* UT2TSU-- current Universal Time as IRAF seconds since 1970-01-01T00:00 */ + +time_t +ut2tsu() +{ + return ((time_t)(ut2ts () - 631152000.0)); +} + + +/* FD2GST-- convert from FITS date to Greenwich Sidereal Time */ + +char * +fd2gst (string) + +char *string; /* FITS date string, which may be: + fractional year + dd/mm/yy (FITS standard before 2000) + dd-mm-yy (nonstandard use before 2000) + yyyy-mm-dd (FITS standard after 1999) + yyyy-mm-ddThh:mm:ss.ss (FITS standard after 1999) */ +{ + double dj, gsec, date, time; + + dj = fd2jd (string); + gsec = jd2gst (dj); + ts2dt (gsec, &date, &time); + date = 0.0; + return (dt2fd (date, time)); +} + + +/* DT2GST-- convert from UT as yyyy.mmdd hh.mmssss to Greenwich Sidereal Time*/ + +void +dt2gst (date, time) +double *date; /* Date as yyyy.mmdd */ +double *time; /* Time as hh.mmssxxxx + *if time<0, it is time as -(fraction of a day) */ +{ + double dj, gsec; + + dj = dt2ts (*date, *time); + gsec = jd2gst (dj); + ts2dt (gsec, date, time); + *date = 0.0; + return; +} + + +/* JD2LST - Local Sidereal Time in seconds from Julian Date */ + +double +jd2lst (dj) + +double dj; /* Julian Date */ +{ + double gst, lst; + + /* Compute Greenwich Sidereal Time at this epoch */ + gst = jd2gst (dj); + + /* Subtract longitude (degrees to seconds of time) */ + lst = gst - (240.0 * longitude); + if (lst < 0.0) + lst = lst + 86400.0; + else if (lst > 86400.0) + lst = lst - 86400.0; + return (lst); +} + + +/* FD2LST - Local Sidereal Time as hh:mm:ss.ss + from Universal Time as FITS ISO date */ + +char * +fd2lst (string) + +char *string; /* FITS date string, which may be: + fractional year + dd/mm/yy (FITS standard before 2000) + dd-mm-yy (nonstandard use before 2000) + yyyy-mm-dd (FITS standard after 1999) */ +{ + double dj, date, time, lst; + + dj = fd2jd (string); + lst = jd2lst (dj); + ts2dt (lst, &date, &time); + date = 0.0; + return (dt2fd (date, time)); +} + + +/* DT2LST - Local Sidereal Time as hh.mmssss + from Universal Time as yyyy.mmdd hh.mmssss */ + +void +dt2lst (date, time) + +double *date; /* Date as yyyy.mmdd */ +double *time; /* Time as hh.mmssxxxx + *if time<0, it is time as -(fraction of a day) */ +{ + double dj, lst, date0; + + dj = dt2jd (*date, *time); + lst = jd2lst (dj); + date0 = 0.0; + ts2dt (lst, &date0, time); + return; +} + + +/* TS2LST - Local Sidereal Time in seconds of day + * from Universal Time in seconds since 1951-01-01T0:00:00 + */ + +double +ts2lst (tsec) + +double tsec; /* time since 1950.0 in UT seconds */ +{ + double gst; /* Greenwich Sidereal Time in seconds since 0:00 */ + double lst; /* Local Sidereal Time in seconds since 0:00 */ + double gsec, date; + + /* Greenwich Sidereal Time */ + gsec = ts2gst (tsec); + date = 0.0; + ts2dt (gsec, &date, &gst); + + lst = gst - (longitude / 15.0); + if (lst < 0.0) + lst = lst + 86400.0; + else if (lst > 86400.0) + lst = lst - 86400.0; + return (lst); +} + + +/* LST2FD - calculate current UT given Local Sidereal Time + * plus date in FITS ISO format (yyyy-mm-dd) + * Return UT date and time in FITS ISO format + */ + +char * +lst2fd (string) + +char *string; /* UT Date, LST as yyyy-mm-ddShh:mm:ss.ss */ +{ + double sdj, dj; + + sdj = fd2jd (string); + + dj = lst2jd (sdj); + + return (jd2fd (dj)); +} + + +/* LST2JD - calculate current Julian Date given Local Sidereal Time + * plus current Julian Date (0.5 at 0:00 UT) + * Return UT date and time as Julian Date + */ + +double +lst2jd (sdj) + +double sdj; /* Julian Date of desired day at 0:00 UT + sidereal time */ +{ + double gst; /* Greenwich Sidereal Time in seconds since 0:00 */ + double lsd; /* Local Sidereal Time in seconds since 0:00 */ + double gst0, tsd, dj1, dj0, eqnx; + int idj; + + /* Julian date at 0:00 UT */ + idj = (int) sdj; + dj0 = (double) idj + 0.5; + if (dj0 > sdj) dj0 = dj0 - 1.0; + + /* Greenwich Sidereal Time at 0:00 UT in seconds */ + gst0 = jd2gst (dj0); + + /* Sidereal seconds since 0:00 */ + lsd = (sdj - dj0) * 86400.0; + + /* Remove longitude for current Greenwich Sidereal Time in seconds */ + /* (convert longitude from degrees to seconds of time) */ + gst = lsd + (longitude * 240.0); + + /* Time since 0:00 UT */ + tsd = (gst - gst0) / 1.0027379093; + + /* Julian Date (UT) */ + dj1 = dj0 + (tsd / 86400.0); + + /* Equation of the equinoxes converted to UT seconds */ + eqnx = eqeqnx (dj1) / 1.002739093; + + /* Remove equation of equinoxes */ + dj1 = dj1 - (eqnx / 86400.0); + if (dj1 < dj0) + dj1 = dj1 + 1.0; + + return (dj1); +} + + +/* MST2FD - calculate current UT given Greenwich Mean Sidereal Time + * plus date in FITS ISO format (yyyy-mm-ddShh:mm:ss.ss) + * Return UT date and time in FITS ISO format + */ + +char * +mst2fd (string) + +char *string; /* UT Date, MST as yyyy-mm-ddShh:mm:ss.ss */ +{ + double sdj, dj; + + sdj = fd2jd (string); + + dj = mst2jd (sdj); + + return (jd2fd (dj)); +} + + +/* MST2JD - calculate current UT given Greenwich Mean Sidereal Time + * plus date in Julian Date (0:00 UT + Mean Sidereal Time) + * Return UT date and time as Julian Date + */ + +double +mst2jd (sdj) + +double sdj; /* UT Date, MST as Julian Date */ +{ + double tsd, djd, st0, dj0, dj; + + dj0 = (double) ((int) sdj) + 0.5; + + /* Greenwich Mean Sidereal Time at 0:00 UT in seconds */ + st0 = jd2mst (dj0); + + /* Mean Sidereal Time in seconds */ + tsd = (sdj - dj0) * 86400.0; + if (tsd < 0.0) + tsd = tsd + 86400.0; + + /* Convert to fraction of a day since 0:00 UT */ + djd = ((tsd - st0) / 1.0027379093) / 86400.0; + + /* Julian Date */ + dj = dj0 + djd; + if (dj < dj0) + dj = dj + (1.0 / 1.0027379093); + + return (dj); +} + + + +/* GST2FD - calculate current UT given Greenwich Sidereal Time + * plus date in FITS ISO format (yyyy-mm-ddShh:mm:ss.ss) + * Return UT date and time in FITS ISO format + */ + +char * +gst2fd (string) + +char *string; /* UT Date, GST as yyyy-mm-ddShh:mm:ss.ss */ +{ + double sdj, dj; + + sdj = fd2jd (string); + + dj = gst2jd (sdj); + + return (jd2fd (dj)); +} + + +/* GST2JD - calculate current UT given Greenwich Sidereal Time + * plus date as Julian Date (JD at 0:00 UT + sidereal time) + * Return UT date and time as Julian Date + */ + +double +gst2jd (sdj) + +double sdj; /* UT Date, GST as Julian Date */ +{ + double dj, tsd, djd, st0, dj0, eqnx; + + dj0 = (double) ((int) sdj) + 0.5; + + /* Greenwich Mean Sidereal Time at 0:00 UT in seconds */ + st0 = jd2mst (dj0); + + /* Mean Sidereal Time in seconds */ + tsd = (sdj - dj0) * 86400.0; + if (tsd < 0.0) + tsd = tsd + 86400.0; + + /* Convert to fraction of a day since 0:00 UT */ + djd = ((tsd - st0) / 1.0027379093) / 86400.0; + + /* Julian Date */ + dj = dj0 + djd; + + /* Equation of the equinoxes (converted to UT seconds) */ + eqnx = eqeqnx (dj) / 1.002737909; + + dj = dj - eqnx / 86400.0; + if (dj < dj0) + dj = dj + 1.0; + + return (dj); +} + + +/* LST2DT - calculate current UT given Local Sidereal Time as hh.mmsss + * plus date as yyyy.mmdd + * Return UT time as hh.mmssss + */ + +double +lst2dt (date0, time0) + +double date0; /* UT date as yyyy.mmdd */ +double time0; /* LST as hh.mmssss */ +{ + double gst; /* Greenwich Sidereal Time in seconds since 0:00 */ + double lst; /* Local Sidereal Time in seconds since 0:00 */ + double date1; /* UT date as yyyy.mmdd */ + double time1; /* UT as hh.mmssss */ + double tsec0, gst0, tsd, tsec; + + /* Greenwich Sidereal Time at 0:00 UT */ + tsec0 = dt2ts (date0, 0.0); + gst0 = ts2gst (tsec0); + + /* Current Greenwich Sidereal Time in seconds */ + /* (convert longitude from degrees to seconds of time) */ + lst = dt2ts (0.0, time0); + gst = lst + (longitude * 240.0); + + /* Time since 0:00 UT */ + tsd = (gst - gst0) / 1.0027379093; + + /* UT date and time */ + tsec = tsec0 + tsd; + ts2dt (tsec, &date1, &time1); + + return (time1); +} + + +/* TS2GST - calculate Greenwich Sidereal Time given Universal Time + * in seconds since 1951-01-01T0:00:00 + * Return sidereal time of day in seconds + */ + +double +ts2gst (tsec) + +double tsec; /* time since 1950.0 in UT seconds */ +{ + double gst; /* Greenwich Sidereal Time in seconds since 0:00 */ + double tsd, eqnx, dj; + int its; + + /* Elapsed time as of 0:00 UT */ + if (tsec >= 0.0) { + its = (int) (tsec + 0.5); + tsd = (double) (its % 86400); + } + else { + its = (int) (-tsec + 0.5); + tsd = (double) (86400 - (its % 86400)); + } + + /* Mean sidereal time */ + gst = ts2mst (tsec); + + /* Equation of the equinoxes */ + dj = ts2jd (tsec); + eqnx = eqeqnx (dj); + + /* Apparent sidereal time at 0:00 ut */ + gst = gst + eqnx; + + /* Current sidereal time */ + gst = gst + (tsd * 1.0027379093); + gst = dmod (gst,86400.0); + + return (gst); +} + + +/* FD2MST-- convert from FITS date Mean Sidereal Time */ + +char * +fd2mst (string) + +char *string; /* FITS date string, which may be: + fractional year + dd/mm/yy (FITS standard before 2000) + dd-mm-yy (nonstandard use before 2000) + yyyy-mm-dd (FITS standard after 1999) + yyyy-mm-ddThh:mm:ss.ss (FITS standard after 1999) */ +{ + double gsec, date, time, dj; + + dj = fd2jd (string); + gsec = jd2mst (dj); + ts2dt (gsec, &date, &time); + date = 0.0; + return (dt2fd (date, time)); +} + + +/* DT2MST-- convert from UT as yyyy.mmdd hh.mmssss to Mean Sidereal Time + in the same format */ + +void +dt2mst (date, time) +double *date; /* Date as yyyy.mmdd */ +double *time; /* Time as hh.mmssxxxx + *if time<0, it is time as -(fraction of a day) */ +{ + double date0, gsec, dj; + date0 = *date; + dj = dt2jd (*date, *time); + gsec = jd2mst (dj); + ts2dt (gsec, date, time); + *date = date0; + return; +} + + +/* TS2MST - calculate Greenwich Mean Sidereal Time given Universal Time + * in seconds since 1951-01-01T0:00:00 + */ + +double +ts2mst (tsec) + +double tsec; /* time since 1950.0 in UT seconds */ +{ + double dj; + + dj = ts2jd (tsec); + return (jd2mst (dj)); +} + + +/* JD2MST - Julian Date to Greenwich Mean Sidereal Time using IAU 2000 + * Return sideral time in seconds of time + * (from USNO NOVAS package + * http://aa.usno.navy.mil/software/novas/novas_info.html + */ + +double +jd2mst2 (dj) + +double dj; /* Julian Date */ +{ + double dt, t, t2, t3, mst, st; + + dt = dj - 2451545.0; + t = dt / 36525.0; + t2 = t * t; + t3 = t2 * t; + + /* Compute Greenwich Mean Sidereal Time in seconds */ + st = (8640184.812866 * t) + (3155760000.0 * t) - (0.0000062 * t3) + + (0.093104 * t2) + 67310.54841; + + mst = dmod (st, 86400.0); + if (mst < 0.0) + mst = mst + 86400.0; + return (mst); +} + + +/* MJD2MST - Modified Julian Date to Greenwich Mean Sidereal Time using IAU 2000 + * Return sideral time in seconds of time + * (from USNO NOVAS package + * http://aa.usno.navy.mil/software/novas/novas_info.html + */ + +double +mjd2mst (dj) + +double dj; /* Modified Julian Date */ +{ + double dt, t, t2, t3, mst, st; + + dt = dj - 51544.5; + t = dt / 36525.0; + t2 = t * t; + t3 = t2 * t; + + /* Compute Greenwich Mean Sidereal Time in seconds */ + st = (8640184.812866 * t) + (3155760000.0 * t) - (0.0000062 * t3) + + (0.093104 * t2) + 67310.54841; + + mst = dmod (st, 86400.0); + if (mst < 0.0) + mst = mst + 86400.0; + return (mst); +} + + +/* JD2GST - Julian Date to Greenwich Sideral Time + * Return sideral time in seconds of time + * (Jean Meeus, Astronomical Algorithms, Willmann-Bell, 1991, pp 83-84) + */ + +double +jd2gst (dj) + +double dj; /* Julian Date */ +{ + double dj0, gmt, gst, tsd, eqnx, ssd, l0; + double ts2ss = 1.00273790935; + int ijd; + + /* Julian date at 0:00 UT */ + ijd = (int) dj; + dj0 = (double) ijd + 0.5; + if (dj0 > dj) dj0 = dj0 - 1.0; + + /* Greenwich mean sidereal time at 0:00 UT in seconds */ + l0 = longitude; + longitude = 0.0; + gmt = jd2mst (dj0); + longitude = l0; + + /* Equation of the equinoxes */ + eqnx = eqeqnx (dj); + + /* Apparent sidereal time at 0:00 ut */ + gst = gmt + eqnx; + + /* UT seconds since 0:00 */ + tsd = (dj - dj0) * 86400.0; + ssd = tsd * ts2ss; + + /* Current sidereal time */ + gst = gst + ssd; + gst = dmod (gst, 86400.0); + + return (gst); +} + + +/* EQEQNX - Compute equation of the equinoxes for apparent sidereal time */ + +double +eqeqnx (dj) + +double dj; /* Julian Date */ + +{ + double dt, edj, dpsi, deps, obl, eqnx; + double rad2tsec = 13750.98708; + + /* Convert UT to Ephemeris Time (TDB or TT)*/ + dt = utdt (dj); + edj = dj + dt / 86400.0; + + /* Nutation and obliquity */ + compnut (edj, &dpsi, &deps, &obl); + + /* Correct obliquity for nutation */ + obl = obl + deps; + + /* Equation of the equinoxes in seconds */ + eqnx = (dpsi * cos (obl)) * rad2tsec; + + return (eqnx); +} + + + +/* JD2MST - Julian Date to Mean Sideral Time + * Return sideral time in seconds of time + * (Jean Meeus, Astronomical Algorithms, Willmann-Bell, 1991, pp 83-84) + */ + +double +jd2mst (dj) + +double dj; /* Julian Date */ +{ + double dt, t, mst; + + dt = dj - 2451545.0; + t = dt / 36525.0; + + /* Compute Greenwich mean sidereal time in degrees (Meeus, page 84) */ + mst = 280.46061837 + (360.98564736629 * dt) + (0.000387933 * t * t) - + (t * t * t / 38710000.0); + + /* Keep degrees between 0 and 360 */ + while (mst > 360.0) + mst = mst - 360.0; + while (mst < 0.0) + mst = mst + 360.0; + + /* Convert to time in seconds (3600 / 15) */ + mst = mst * 240.0; + + /* Subtract longitude (degrees to seconds of time) */ + mst = mst - (240.0 * longitude); + if (mst < 0.0) + mst = mst + 86400.0; + else if (mst > 86400.0) + mst = mst - 86400.0; + + return (mst); +} + + +/* COMPNUT - Compute nutation using the IAU 2000b model */ +/* Translated from Pat Wallace's Fortran subroutine iau_nut00b (June 26 2007) + into C by Jessica Mink on September 5, 2008 */ + +#define NLS 77 /* number of terms in the luni-solar nutation model */ + +void +compnut (dj, dpsi, deps, eps0) + +double dj; /* Julian Date */ +double *dpsi; /* Nutation in longitude in radians (returned) */ +double *deps; /* Nutation in obliquity in radians (returned) */ +double *eps0; /* Mean obliquity in radians (returned) */ + +/* This routine is translated from the International Astronomical Union's + * Fortran SOFA (Standards Of Fundamental Astronomy) software collection. + * + * notes: + * + * 1) the nutation components in longitude and obliquity are in radians + * and with respect to the equinox and ecliptic of date. the + * obliquity at j2000 is assumed to be the lieske et al. (1977) value + * of 84381.448 arcsec. (the errors that result from using this + * routine with the iau 2006 value of 84381.406 arcsec can be + * neglected.) + * + * the nutation model consists only of luni-solar terms, but includes + * also a fixed offset which compensates for certain long-period + * planetary terms (note 7). + * + * 2) this routine is an implementation of the iau 2000b abridged + * nutation model formally adopted by the iau general assembly in + * 2000. the routine computes the mhb_2000_short luni-solar nutation + * series (luzum 2001), but without the associated corrections for + * the precession rate adjustments and the offset between the gcrs + * and j2000 mean poles. + * + * 3) the full IAU 2000a (mhb2000) nutation model contains nearly 1400 + * terms. the IAU 2000b model (mccarthy & luzum 2003) contains only + * 77 terms, plus additional simplifications, yet still delivers + * results of 1 mas accuracy at present epochs. this combination of + * accuracy and size makes the IAU 2000b abridged nutation model + * suitable for most practical applications. + * + * the routine delivers a pole accurate to 1 mas from 1900 to 2100 + * (usually better than 1 mas, very occasionally just outside 1 mas). + * the full IAU 2000a model, which is implemented in the routine + * iau_nut00a (q.v.), delivers considerably greater accuracy at + * current epochs; however, to realize this improved accuracy, + * corrections for the essentially unpredictable free-core-nutation + * (fcn) must also be included. + * + * 4) the present routine provides classical nutation. the + * mhb_2000_short algorithm, from which it is adapted, deals also + * with (i) the offsets between the gcrs and mean poles and (ii) the + * adjustments in longitude and obliquity due to the changed + * precession rates. these additional functions, namely frame bias + * and precession adjustments, are supported by the sofa routines + * iau_bi00 and iau_pr00. + * + * 6) the mhb_2000_short algorithm also provides "total" nutations, + * comprising the arithmetic sum of the frame bias, precession + * adjustments, and nutation (luni-solar + planetary). these total + * nutations can be used in combination with an existing IAU 1976 + * precession implementation, such as iau_pmat76, to deliver gcrs-to- + * true predictions of mas accuracy at current epochs. however, for + * symmetry with the iau_nut00a routine (q.v. for the reasons), the + * sofa routines do not generate the "total nutations" directly. + * should they be required, they could of course easily be generated + * by calling iau_bi00, iau_pr00 and the present routine and adding + * the results. + * + * 7) the IAU 2000b model includes "planetary bias" terms that are fixed + * in size but compensate for long-period nutations. the amplitudes + * quoted in mccarthy & luzum (2003), namely dpsi = -1.5835 mas and + * depsilon = +1.6339 mas, are optimized for the "total nutations" + * method described in note 6. the luzum (2001) values used in this + * sofa implementation, namely -0.135 mas and +0.388 mas, are + * optimized for the "rigorous" method, where frame bias, precession + * and nutation are applied separately and in that order. during the + * interval 1995-2050, the sofa implementation delivers a maximum + * error of 1.001 mas (not including fcn). + * + * References from original Fortran subroutines: + * + * Hilton, J. et al., 2006, Celest.Mech.Dyn.Astron. 94, 351 + * + * Lieske, J.H., Lederle, T., Fricke, W., Morando, B., "Expressions + * for the precession quantities based upon the IAU 1976 system of + * astronomical constants", Astron.Astrophys. 58, 1-2, 1-16. (1977) + * + * Luzum, B., private communication, 2001 (Fortran code + * mhb_2000_short) + * + * McCarthy, D.D. & Luzum, B.J., "An abridged model of the + * precession-nutation of the celestial pole", Cel.Mech.Dyn.Astron. + * 85, 37-49 (2003) + * + * Simon, J.-L., Bretagnon, P., Chapront, J., Chapront-Touze, M., + * Francou, G., Laskar, J., Astron.Astrophys. 282, 663-683 (1994) + * + */ + +{ + double as2r = 0.000004848136811095359935899141; /* arcseconds to radians */ + + double dmas2r = as2r / 1000.0; /* milliarcseconds to radians */ + + double as2pi = 1296000.0; /* arc seconds in a full circle */ + + double d2pi = 6.283185307179586476925287; /* 2pi */ + + double u2r = as2r / 10000000.0; /* units of 0.1 microarcsecond to radians */ + + double dj0 = 2451545.0; /* reference epoch (j2000), jd */ + + double djc = 36525.0; /* Days per julian century */ + + /* Miscellaneous */ + double t, el, elp, f, d, om, arg, dp, de, sarg, carg; + double dpsils, depsls, dpsipl, depspl; + int i, j; + + int nls = NLS; /* number of terms in the luni-solar nutation model */ + + /* Fixed offset in lieu of planetary terms (radians) */ + double dpplan = - 0.135 * dmas2r; + double deplan = + 0.388 * dmas2r; + +/* Tables of argument and term coefficients */ + + /* Coefficients for fundamental arguments */ + /* Luni-solar argument multipliers: */ + /* l l' f d om */ +static int nals[5*NLS]= + {0, 0, 0, 0, 1, + 0, 0, 2, -2, 2, + 0, 0, 2, 0, 2, + 0, 0, 0, 0, 2, + 0, 1, 0, 0, 0, + 0, 1, 2, -2, 2, + 1, 0, 0, 0, 0, + 0, 0, 2, 0, 1, + 1, 0, 2, 0, 2, + 0, -1, 2, -2, 2, + 0, 0, 2, -2, 1, + -1, 0, 2, 0, 2, + -1, 0, 0, 2, 0, + 1, 0, 0, 0, 1, + -1, 0, 0, 0, 1, + -1, 0, 2, 2, 2, + 1, 0, 2, 0, 1, + -2, 0, 2, 0, 1, + 0, 0, 0, 2, 0, + 0, 0, 2, 2, 2, + 0, -2, 2, -2, 2, + -2, 0, 0, 2, 0, + 2, 0, 2, 0, 2, + 1, 0, 2, -2, 2, + -1, 0, 2, 0, 1, + 2, 0, 0, 0, 0, + 0, 0, 2, 0, 0, + 0, 1, 0, 0, 1, + -1, 0, 0, 2, 1, + 0, 2, 2, -2, 2, + 0, 0, -2, 2, 0, + 1, 0, 0, -2, 1, + 0, -1, 0, 0, 1, + -1, 0, 2, 2, 1, + 0, 2, 0, 0, 0, + 1, 0, 2, 2, 2, + -2, 0, 2, 0, 0, + 0, 1, 2, 0, 2, + 0, 0, 2, 2, 1, + 0, -1, 2, 0, 2, + 0, 0, 0, 2, 1, + 1, 0, 2, -2, 1, + 2, 0, 2, -2, 2, + -2, 0, 0, 2, 1, + 2, 0, 2, 0, 1, + 0, -1, 2, -2, 1, + 0, 0, 0, -2, 1, + -1, -1, 0, 2, 0, + 2, 0, 0, -2, 1, + 1, 0, 0, 2, 0, + 0, 1, 2, -2, 1, + 1, -1, 0, 0, 0, + -2, 0, 2, 0, 2, + 3, 0, 2, 0, 2, + 0, -1, 0, 2, 0, + 1, -1, 2, 0, 2, + 0, 0, 0, 1, 0, + -1, -1, 2, 2, 2, + -1, 0, 2, 0, 0, + 0, -1, 2, 2, 2, + -2, 0, 0, 0, 1, + 1, 1, 2, 0, 2, + 2, 0, 0, 0, 1, + -1, 1, 0, 1, 0, + 1, 1, 0, 0, 0, + 1, 0, 2, 0, 0, + -1, 0, 2, -2, 1, + 1, 0, 0, 0, 2, + -1, 0, 0, 1, 0, + 0, 0, 2, 1, 2, + -1, 0, 2, 4, 2, + -1, 1, 0, 1, 1, + 0, -2, 2, -2, 1, + 1, 0, 2, 2, 1, + -2, 0, 2, 2, 2, + -1, 0, 0, 0, 2, + 1, 1, 2, -2, 2}; + + /* Luni-solar nutation coefficients, in 1e-7 arcsec */ + /* longitude (sin, t*sin, cos), obliquity (cos, t*cos, sin) */ +static double cls[6*NLS]= + {-172064161.0, -174666.0, 33386.0, 92052331.0, 9086.0, 15377.0, + -13170906.0, -1675.0, -13696.0, 5730336.0, -3015.0, -4587.0, + -2276413.0, -234.0, 2796.0, 978459.0, -485.0, 1374.0, + 2074554.0, 207.0, -698.0, -897492.0, 470.0, -291.0, + 1475877.0, -3633.0, 11817.0, 73871.0, -184.0, -1924.0, + -516821.0, 1226.0, -524.0, 224386.0, -677.0, -174.0, + 711159.0, 73.0, -872.0, -6750.0, 0.0, 358.0, + -387298.0, -367.0, 380.0, 200728.0, 18.0, 318.0, + -301461.0, -36.0, 816.0, 129025.0, -63.0, 367.0, + 215829.0, -494.0, 111.0, -95929.0, 299.0, 132.0, + 128227.0, 137.0, 181.0, -68982.0, -9.0, 39.0, + 123457.0, 11.0, 19.0, -53311.0, 32.0, -4.0, + 156994.0, 10.0, -168.0, -1235.0, 0.0, 82.0, + 63110.0, 63.0, 27.0, -33228.0, 0.0, -9.0, + -57976.0, -63.0, -189.0, 31429.0, 0.0, -75.0, + -59641.0, -11.0, 149.0, 25543.0, -11.0, 66.0, + -51613.0, -42.0, 129.0, 26366.0, 0.0, 78.0, + 45893.0, 50.0, 31.0, -24236.0, -10.0, 20.0, + 63384.0, 11.0, -150.0, -1220.0, 0.0, 29.0, + -38571.0, -1.0, 158.0, 16452.0, -11.0, 68.0, + 32481.0, 0.0, 0.0, -13870.0, 0.0, 0.0, + -47722.0, 0.0, -18.0, 477.0, 0.0, -25.0, + -31046.0, -1.0, 131.0, 13238.0, -11.0, 59.0, + 28593.0, 0.0, -1.0, -12338.0, 10.0, -3.0, + 20441.0, 21.0, 10.0, -10758.0, 0.0, -3.0, + 29243.0, 0.0, -74.0, -609.0, 0.0, 13.0, + 25887.0, 0.0, -66.0, -550.0, 0.0, 11.0, + -14053.0, -25.0, 79.0, 8551.0, -2.0, -45.0, + 15164.0, 10.0, 11.0, -8001.0, 0.0, -1.0, + -15794.0, 72.0, -16.0, 6850.0, -42.0, -5.0, + 21783.0, 0.0, 13.0, -167.0, 0.0, 13.0, + -12873.0, -10.0, -37.0, 6953.0, 0.0, -14.0, + -12654.0, 11.0, 63.0, 6415.0, 0.0, 26.0, + -10204.0, 0.0, 25.0, 5222.0, 0.0, 15.0, + 16707.0, -85.0, -10.0, 168.0, -1.0, 10.0, + -7691.0, 0.0, 44.0, 3268.0, 0.0, 19.0, + -11024.0, 0.0, -14.0, 104.0, 0.0, 2.0, + 7566.0, -21.0, -11.0, -3250.0, 0.0, -5.0, + -6637.0, -11.0, 25.0, 3353.0, 0.0, 14.0, + -7141.0, 21.0, 8.0, 3070.0, 0.0, 4.0, + -6302.0, -11.0, 2.0, 3272.0, 0.0, 4.0, + 5800.0, 10.0, 2.0, -3045.0, 0.0, -1.0, + 6443.0, 0.0, -7.0, -2768.0, 0.0, -4.0, + -5774.0, -11.0, -15.0, 3041.0, 0.0, -5.0, + -5350.0, 0.0, 21.0, 2695.0, 0.0, 12.0, + -4752.0, -11.0, -3.0, 2719.0, 0.0, -3.0, + -4940.0, -11.0, -21.0, 2720.0, 0.0, -9.0, + 7350.0, 0.0, -8.0, -51.0, 0.0, 4.0, + 4065.0, 0.0, 6.0, -2206.0, 0.0, 1.0, + 6579.0, 0.0, -24.0, -199.0, 0.0, 2.0, + 3579.0, 0.0, 5.0, -1900.0, 0.0, 1.0, + 4725.0, 0.0, -6.0, -41.0, 0.0, 3.0, + -3075.0, 0.0, -2.0, 1313.0, 0.0, -1.0, + -2904.0, 0.0, 15.0, 1233.0, 0.0, 7.0, + 4348.0, 0.0, -10.0, -81.0, 0.0, 2.0, + -2878.0, 0.0, 8.0, 1232.0, 0.0, 4.0, + -4230.0, 0.0, 5.0, -20.0, 0.0, -2.0, + -2819.0, 0.0, 7.0, 1207.0, 0.0, 3.0, + -4056.0, 0.0, 5.0, 40.0, 0.0, -2.0, + -2647.0, 0.0, 11.0, 1129.0, 0.0, 5.0, + -2294.0, 0.0, -10.0, 1266.0, 0.0, -4.0, + 2481.0, 0.0, -7.0, -1062.0, 0.0, -3.0, + 2179.0, 0.0, -2.0, -1129.0, 0.0, -2.0, + 3276.0, 0.0, 1.0, -9.0, 0.0, 0.0, + -3389.0, 0.0, 5.0, 35.0, 0.0, -2.0, + 3339.0, 0.0, -13.0, -107.0, 0.0, 1.0, + -1987.0, 0.0, -6.0, 1073.0, 0.0, -2.0, + -1981.0, 0.0, 0.0, 854.0, 0.0, 0.0, + 4026.0, 0.0, -353.0, -553.0, 0.0, -139.0, + 1660.0, 0.0, -5.0, -710.0, 0.0, -2.0, + -1521.0, 0.0, 9.0, 647.0, 0.0, 4.0, + 1314.0, 0.0, 0.0, -700.0, 0.0, 0.0, + -1283.0, 0.0, 0.0, 672.0, 0.0, 0.0, + -1331.0, 0.0, 8.0, 663.0, 0.0, 4.0, + 1383.0, 0.0, -2.0, -594.0, 0.0, -2.0, + 1405.0, 0.0, 4.0, -610.0, 0.0, 2.0, + 1290.0, 0.0, 0.0, -556.0, 0.0, 0.0}; + + /* Interval between fundamental epoch J2000.0 and given date (JC) */ + t = (dj - dj0) / djc; + +/* Luni-solar nutation */ + +/* Fundamental (delaunay) arguments from Simon et al. (1994) */ + + /* Mean anomaly of the moon */ + el = fmod (485868.249036 + (1717915923.2178 * t), as2pi) * as2r; + + /* Mean anomaly of the sun */ + elp = fmod (1287104.79305 + (129596581.0481 * t), as2pi) * as2r; + + /* Mean argument of the latitude of the moon */ + f = fmod (335779.526232 + (1739527262.8478 * t), as2pi) * as2r; + + /* Mean elongation of the moon from the sun */ + d = fmod (1072260.70369 + (1602961601.2090 * t), as2pi ) * as2r; + + /* Mean longitude of the ascending node of the moon */ + om = fmod (450160.398036 - (6962890.5431 * t), as2pi ) * as2r; + + /* Initialize the nutation values */ + dp = 0.0; + de = 0.0; + + /* Summation of luni-solar nutation series (in reverse order) */ + for (i = nls; i > 0; i=i-1) { + j = i - 1; + + /* Argument and functions */ + arg = fmod ( (double) (nals[5*j]) * el + + (double) (nals[1+5*j]) * elp + + (double) (nals[2+5*j]) * f + + (double) (nals[3+5*j]) * d + + (double) (nals[4+5*j]) * om, d2pi); + sarg = sin (arg); + carg = cos (arg); + + /* Terms */ + dp = dp + (cls[6*j] + cls[1+6*j] * t) * sarg + cls[2+6*j] * carg; + de = de + (cls[3+6*j] + cls[4+6*j] * t) * carg + cls[5+6*j] * sarg; + } + + /* Convert from 0.1 microarcsec units to radians */ + dpsils = dp * u2r; + depsls = de * u2r; + +/* In lieu of planetary nutation */ + + /* Fixed offset to correct for missing terms in truncated series */ + dpsipl = dpplan; + depspl = deplan; + +/* Results */ + + /* Add luni-solar and planetary components */ + *dpsi = dpsils + dpsipl; + *deps = depsls + depspl; + + /* Mean Obliquity in radians (IAU 2006, Hilton, et al.) */ + *eps0 = ( 84381.406 + + ( -46.836769 + + ( -0.0001831 + + ( 0.00200340 + + ( -0.000000576 + + ( -0.0000000434 ) * t ) * t ) * t ) * t ) * t ) * as2r; +} + + +/* ISDATE - Return 1 if string is an old or ISO FITS standard date */ + +int +isdate (string) + +char *string; /* Possible FITS date string, which may be: + dd/mm/yy (FITS standard before 2000) + dd-mm-yy (nonstandard FITS use before 2000) + yyyy-mm-dd (FITS standard after 1999) + yyyy-mm-ddThh:mm:ss.ss (FITS standard after 1999) */ + +{ + int iyr = 0; /* year (returned) */ + int imon = 0; /* month (returned) */ + int iday = 0; /* day (returned) */ + int i; + char *sstr, *dstr, *tstr, *nval; + + /* Translate string from ASCII to binary */ + if (string == NULL) + return (0); + + sstr = strchr (string,'/'); + dstr = strchr (string,'-'); + if (dstr == string) + dstr = strchr (string+1,'-'); + tstr = strchr (string,'T'); + + /* Original FITS date format: dd/mm/yy */ + if (sstr > string) { + *sstr = '\0'; + iday = (int) atof (string); + *sstr = '/'; + nval = sstr + 1; + sstr = strchr (nval,'/'); + if (sstr == NULL) + sstr = strchr (nval,'-'); + if (sstr > string) { + *sstr = '\0'; + imon = (int) atof (nval); + *sstr = '/'; + nval = sstr + 1; + iyr = (int) atof (nval); + if (iyr < 1000) + iyr = iyr + 1900; + } + if (imon > 0 && iday > 0) + return (1); + else + return (0); + } + + /* New FITS date format: yyyy-mm-ddThh:mm:ss[.sss] */ + else if (dstr > string) { + *dstr = '\0'; + iyr = (int) atof (string); + nval = dstr + 1; + *dstr = '-'; + dstr = strchr (nval,'-'); + imon = 0; + iday = 0; + + /* Decode year, month, and day */ + if (dstr > string) { + *dstr = '\0'; + imon = (int) atof (nval); + *dstr = '-'; + nval = dstr + 1; + if (tstr > string) + *tstr = '\0'; + iday = (int) atof (nval); + if (tstr > string) + *tstr = 'T'; + } + + /* If day is > 31, it is really year in old format */ + if (iday > 31) { + i = iyr; + if (iday < 100) + iyr = iday + 1900; + else + iyr = iday; + iday = i; + } + if (imon > 0 && iday > 0) + return (1); + else + return (0); + } + + /* If FITS date is entered as an epoch, return 0 anyway */ + else + return (0); +} + + +/* Round seconds and make sure date and time numbers are within limits */ + +static void +fixdate (iyr, imon, iday, ihr, imn, sec, ndsec) + +int *iyr; /* year (returned) */ +int *imon; /* month (returned) */ +int *iday; /* day (returned) */ +int *ihr; /* hours (returned) */ +int *imn; /* minutes (returned) */ +double *sec; /* seconds (returned) */ +int ndsec; /* Number of decimal places in seconds (0=int) */ +{ + double days; + + /* Round seconds to 0 - 4 decimal places (no rounding if <0, >4) */ + if (ndsec == 0) + *sec = dint (*sec + 0.5); + else if (ndsec < 2) + *sec = dint (*sec * 10.0 + 0.5) / 10.0; + else if (ndsec < 3) + *sec = dint (*sec * 100.0 + 0.5) / 100.0; + else if (ndsec < 4) + *sec = dint (*sec * 1000.0 + 0.5) / 1000.0; + else if (ndsec < 5) + *sec = dint (*sec * 10000.0 + 0.5) / 10000.0; + + /* Adjust minutes and hours */ + if (*sec > 60.0) { + *sec = *sec - 60.0; + *imn = *imn + 1; + } + if (*imn > 60) { + *imn = *imn - 60; + *ihr = *ihr + 1; + } + + /* Return if no date */ + if (*iyr == 0 && *imon == 0 && *iday == 0) + return; + + /* Adjust date */ + if (*ihr > 23) { + *ihr = *ihr - 24; + *iday = *iday + 1; + } + days = caldays (*iyr, *imon); + if (*iday > days) { + *iday = *iday - days; + *imon = *imon + 1; + } + if (*iday < 1) { + *imon = *imon - 1; + if (*imon < 1) { + *imon = *imon + 12; + *iyr = *iyr - 1; + } + days = caldays (*iyr, *imon); + *iday = *iday + days; + } + if (*imon < 1) { + *imon = *imon + 12; + *iyr = *iyr - 1; + days = caldays (*iyr, *imon); + if (*iday > days) { + *iday = *iday - days; + *imon = *imon + 1; + } + } + if (*imon > 12) { + *imon = *imon - 12; + *iyr = *iyr + 1; + } + return; +} + + +/* Calculate days in month 1-12 given year (Gregorian calendar only) */ + +static int +caldays (year, month) + +int year; /* 4-digit year */ +int month; /* Month (1=January, 2=February, etc.) */ +{ + if (month < 1) { + month = month + 12; + year = year + 1; + } + if (month > 12) { + month = month - 12; + year = year + 1; + } + switch (month) { + case 1: + return (31); + case 2: + if (year%400 == 0) + return (29); + else if (year%100 == 0) + return (28); + else if (year%4 == 0) + return (29); + else + return (28); + case 3: + return (31); + case 4: + return (30); + case 5: + return (31); + case 6: + return (30); + case 7: + return (31); + case 8: + return (31); + case 9: + return (30); + case 10: + return (31); + case 11: + return (30); + case 12: + return (31); + default: + return (0); + } +} + + +static double +dint (dnum) + +double dnum; +{ + double dn; + + if (dnum < 0.0) + dn = -floor (-dnum); + else + dn = floor (dnum); + return (dn); +} + + +static double +dmod (dnum, dm) + +double dnum, dm; +{ + double dnumx, dnumi, dnumf; + if (dnum < 0.0) + dnumx = -dnum; + else + dnumx = dnum; + dnumi = dint (dnumx / dm); + if (dnum < 0.0) + dnumf = dnum + (dnumi * dm); + else if (dnum > 0.0) + dnumf = dnum - (dnumi * dm); + else + dnumf = 0.0; + return (dnumf); +} + +/* Jul 1 1999 New file, based on iolib/jcon.f and iolib/vcon.f and hgetdate() + * Oct 21 1999 Fix declarations after lint + * Oct 27 1999 Fix bug to return epoch if fractional year input + * Dec 9 1999 Fix bug in ts2jd() found by Pete Ratzlaff (SAO) + * Dec 17 1999 Add all unimplemented conversions + * Dec 20 1999 Add isdate(); leave date, time strings unchanged in fd2i() + * Dec 20 1999 Make all fd2*() subroutines deal with time alone + * + * Jan 3 2000 In old FITS format, year 100 is assumed to be 2000 + * Jan 11 2000 Fix epoch to date conversion so .0 is 0:00, not 12:00 + * Jan 21 2000 Add separate Besselian and Julian epoch computations + * Jan 28 2000 Add Modified Julian Date conversions + * Mar 2 2000 Implement decimal places for FITS date string + * Mar 14 2000 Fix bug in dealing with 2000-02-29 in ts2i() + * Mar 22 2000 Add lt2* and ut2* to get current time as local and UT + * Mar 24 2000 Fix calloc() calls + * Mar 24 2000 Add tsi2* and tsu2* to convert IRAF and Unix seconds + * May 1 2000 In old FITS format, all years < 1000 get 1900 added to them + * Aug 1 2000 Make ep2jd and jd2ep consistently starting at 1/1 0:00 + * + * Jan 11 2001 Print all messages to stderr + * May 21 2001 Add day of year conversions + * May 25 2001 Allow fraction of day in FITS date instead of time + * + * Apr 8 2002 Change all long declaration to time_t + * May 13 2002 Fix bugs found by lint + * Jul 5 2002 Fix bug in fixdate() so fractional seconds come out + * Jul 8 2002 Fix rounding bug in t2i() + * Jul 8 2002 Try Fliegel and Van Flandern's algorithm for JD to UT date + * Jul 8 2002 If first character of string is -, check for other -'s in isdate + * Sep 10 2002 Add ET/TDT/TT conversion from UT subroutines + * Sep 10 2002 Add sidereal time conversions + * + * Jan 30 2003 Fix typo in ts2gst() + * Mar 7 2003 Add conversions for heliocentric julian dates + * May 20 2003 Declare nd in setdatedec() + * Jul 18 2003 Add code to parse Las Campanas dates + * + * Mar 24 2004 If ndec > 0, add UT to FITS date even if it is 0:00:00 + * + * Oct 14 2005 Add tsd2fd() and tsd2dt() + * + * May 3 2006 Drop declaration of unused variables + * Jun 20 2006 Initialized uninitialized variables + * Aug 2 2006 Add local sidereal time + * Sep 13 2006 Add more local sidereal time subroutines + * Oct 2 2006 Add UT to old FITS date conversions + * Oct 6 2006 Add eqeqnx() to compute equation of the equinoxes + * + * Jan 8 2007 Remove unused variables + * + * Sep 5 2008 Replace nutation with IAU 2006 model translated from SOFA + * Sep 9 2008 Add ang2hr(), ang2deg(), hr2ang(), deg2ang() + * Sep 10 2008 Add longitude to mean standard time (default = Greenwich) + * Oct 8 2008 Clean up sidereal time computations + * + * Sep 24 2009 Add end to comment "Coefficients for fundamental arguments" + * + * Jan 11 2012 Add TAI, TT, GPS time + * Oct 19 2012 Unused l0 dropped from jd2lst(); ts2ss from jd2mst() + */ |