/* tparse.f -- translated by f2c (version 19980913).
   You must link the resulting object file with the libraries:
	-lf2c -lm   (in that order)
*/

#include "f2c.h"

/* Table of constant values */

static integer c__400 = 400;

/* $Procedure       TPARSE ( Parse a UTC time string ) */
/* Subroutine */ int tparse_(char *string, doublereal *sp2000, char *error, 
	ftnlen string_len, ftnlen error_len)
{
    /* Builtin functions */
    /* Subroutine */ int s_copy(char *, char *, ftnlen, ftnlen);
    integer s_cmp(char *, char *, ftnlen, ftnlen), i_dnnt(doublereal *);

    /* Local variables */
    integer year;
    doublereal tvec[10];
    logical mods;
    integer temp;
    char type__[5];
    integer q;
    extern /* Subroutine */ int repmc_(char *, char *, char *, char *, ftnlen,
	     ftnlen, ftnlen, ftnlen);
    integer ntvec, month;
    logical ok;
    extern /* Subroutine */ int tcheck_(doublereal *, char *, logical *, char 
	    *, logical *, char *, ftnlen, ftnlen, ftnlen), rmaini_(integer *, 
	    integer *, integer *, integer *);
    logical succes, yabbrv;
    char modify[8*5];
    logical adjust;
    char pictur[80];
    extern /* Subroutine */ int tpartv_(char *, doublereal *, integer *, char 
	    *, char *, logical *, logical *, logical *, char *, char *, 
	    ftnlen, ftnlen, ftnlen, ftnlen, ftnlen), texpyr_(integer *);
    extern doublereal j2000_(void);
    integer day;
    extern doublereal spd_(void);

/* $ Abstract */

/*      Parse a time string and return seconds past the J2000 epoch */
/*      on a formal calendar. */

/* $ Disclaimer */

/*     THIS SOFTWARE AND ANY RELATED MATERIALS WERE CREATED BY THE */
/*     CALIFORNIA INSTITUTE OF TECHNOLOGY (CALTECH) UNDER A U.S. */
/*     GOVERNMENT CONTRACT WITH THE NATIONAL AERONAUTICS AND SPACE */
/*     ADMINISTRATION (NASA). THE SOFTWARE IS TECHNOLOGY AND SOFTWARE */
/*     PUBLICLY AVAILABLE UNDER U.S. EXPORT LAWS AND IS PROVIDED "AS-IS" */
/*     TO THE RECIPIENT WITHOUT WARRANTY OF ANY KIND, INCLUDING ANY */
/*     WARRANTIES OF PERFORMANCE OR MERCHANTABILITY OR FITNESS FOR A */
/*     PARTICULAR USE OR PURPOSE (AS SET FORTH IN UNITED STATES UCC */
/*     SECTIONS 2312-2313) OR FOR ANY PURPOSE WHATSOEVER, FOR THE */
/*     SOFTWARE AND RELATED MATERIALS, HOWEVER USED. */

/*     IN NO EVENT SHALL CALTECH, ITS JET PROPULSION LABORATORY, OR NASA */
/*     BE LIABLE FOR ANY DAMAGES AND/OR COSTS, INCLUDING, BUT NOT */
/*     LIMITED TO, INCIDENTAL OR CONSEQUENTIAL DAMAGES OF ANY KIND, */
/*     INCLUDING ECONOMIC DAMAGE OR INJURY TO PROPERTY AND LOST PROFITS, */
/*     REGARDLESS OF WHETHER CALTECH, JPL, OR NASA BE ADVISED, HAVE */
/*     REASON TO KNOW, OR, IN FACT, SHALL KNOW OF THE POSSIBILITY. */

/*     RECIPIENT BEARS ALL RISK RELATING TO QUALITY AND PERFORMANCE OF */
/*     THE SOFTWARE AND ANY RELATED MATERIALS, AND AGREES TO INDEMNIFY */
/*     CALTECH AND NASA FOR ALL THIRD-PARTY CLAIMS RESULTING FROM THE */
/*     ACTIONS OF RECIPIENT IN THE USE OF THE SOFTWARE. */

/* $ Required_Reading */

/*     None. */

/* $ Keywords */

/*      PARSING, TIME */

/* $ Declarations */
/* $ Brief_I/O */

/*      VARIABLE  I/O  DESCRIPTION */
/*      --------  ---  -------------------------------------------------- */
/*      STRING     I   Input time string, UTC. */
/*      SP2000     O   Equivalent UTC seconds past J2000. */
/*      ERROR      O   Descriptive error message. */

/* $ Detailed_Input */

/*      STRING      is an input time string, containing a Calendar or */
/*                  Julian Date.  It may be in several different */
/*                  formats and can make use of abbreviations. */
/*                  Several example strings and */
/*                  the times that they translate to are listed below */
/*                  in the C$ Examples section. */

/* $ Detailed_Output */

/*      SP2000      is the equivalent of UTC, expressed in UTC */
/*                  seconds past J2000. If an error occurs, or if */
/*                  UTC is ambiguous, SP2000 is not changed. */

/*      ERROR       is a descriptive error message, which is blank when */
/*                  no error occurs. */

/* $ Parameters */

/*      None. */

/* $ Exceptions */

/*      Error free. */

/* $ Files */

/*      None. */

/* $ Particulars */

/*      The input string is examined and the various components of */
/*      a date are identified: julian date, year, month, day of year, */
/*      day of month, hour, minutes, seconds.  These items are */
/*      assumed to be components on a calendar that contains no */
/*      leapseconds (i.e. every day is assumed to have exactly 86400 */
/*      seconds). */

/*      TPARSE recognizes a wide range of standard time formats. */
/*      The examples section contains a list of several common */
/*      strings that are recognized and their interpretation. */
/*      TPARSE relies on the lower lever routine TPARTV to */
/*      interpret the input string. */

/*      Here is a brief summary of some of the basic rules used */
/*      in the interpretation of strings. */

/*      1)  Unless the substring JD or jd is present the string is */
/*          assumed to be a calendar format (day-month-year or year and */
/*          day of year).  If the substring JD or jd is present, the */
/*          string is assumed to represent a julian date. */

/*      2)  If the julian date specifier is not present, any integer */
/*          greater than 999 is regarded as being a year specification. */

/*      3)  A dash '-' can represent a minus sign only if it is precedes */
/*          the first digit in the string and the string contains */
/*          the julian date specifier (JD).  (No negative years, */
/*          months, days, etc are allowed). */

/*      4)  Numeric components of a time string must be separated */
/*          by a character that is not a digit or decimal point. */
/*          Only one decimal component is allowed.  For example */
/*          1994219.12819 is sometimes interpreted as the */
/*          219th day of 1994 + 0.12819 days.  TPARSE does not */
/*          support such strings. */

/*          No exponential components are allowed.  For example you */
/*          can't input 1993 Jun 23 23:00:01.202E-4 you have */
/*          to explicitly list all zeros that follow the decimal */
/*          point: i.e.  1993 Jun 23 23:00:00.0001202 */

/*      5)  The single colon (:) when used to separate numeric */
/*          components of a string is interpreted as separating */
/*          Hours, Minutes, and Seconds of time. */

/*      6)  If a double slash (//) or double colon (::) follows */
/*          a pair of integers, those integers are assumed  to */
/*          represent the year and day of year. */

/*      7)  A quote followed by an integer less than 100 is regarded */
/*          as an abbreviated year.  For example: '93 would be regarded */
/*          as the 93rd year of the reference century.  See TEXPYR */
/*          for further discussion of abbreviated years. */

/*       8) An integer followed by 'B.C.' or 'A.D.' is regarded as */
/*          a year in the era associated with that abbreviation. */

/*       9) All dates are regarded as belonging to the extended */
/*          Gregorian Calendar (the Gregorian calendar is the calendar */
/*          currently used by western society).  See the routine JUL2GR */
/*          for  converting from Julian Calendar to the */
/*          Gregorian Calendar. */
/*          western society). */

/*      10) When the size of the integer components does not clearly */
/*          specify a year the following patterns are assumed */

/*          Calendar Format */

/*              Year Month Day */
/*              Month Day Year */
/*              Year Day Month */

/*              Where Month is the name of a month, not its numeric */
/*              value. */

/*              When integer components are separated by slashes (/) */
/*              as in 3/4/5.  Month, Day, Year is assumed (2005 March 4) */

/*           Day of Year Format. */

/*              If a day of year marker is present (// or ::) the */
/*              pattern */

/*              I-I// or I-I:: (where I stands for and integer) */
/*              is interpreted as Year Day-of-Year. However, I-I/ is */
/*              regarded as ambiguous. */

/*      To understand the complete list of strings that can be understood */
/*      by TPARSE you need to examine TPARTV and read the appendix to */
/*      the TIME required reading entitled "Parsing Time Strings" */

/*      TPARSE does not support the specification of time system */
/*      such as TDT or TDB; AM/PM specifications of time; or time */
/*      zones (such as PDT, UTC+7:20, etc.). */

/*      If some part of the time string is not recognized or if */
/*      the meaning of the components are not clear, an error string */
/*      is constructed that explains the problem with the string. */

/*      Since the routine is works by breaking the input string into */
/*      a sequence of tokens whose meanings are determined by position */
/*      and magnitude, you can supply strings such as 1993 FEB 35 and */
/*      have this correctly interpreted as March 7, 1993.  However, */
/*      this default action can be modified so that only "proper" */
/*      calendar dates and times are recognized.  To do this call */
/*      the routine TPARCH as shown below: */

/*         CALL TPARCH ( 'YES' ) */

/*      This will cause the routine to treat dates and times with */
/*      components outside the normal range as errors. */

/*      To return to the default behavior */

/*         CALL TPARCH ( 'NO' ) */

/* $ Examples */

/*      The following are examples of valid inputs to TPARSE: */



/*      ISO (T) Formats. */

/*      String                        Year Mon  DOY DOM  HR Min Sec */
/*      ----------------------------  ---- ---  --- ---  -- --- ------ */
/*      1996-12-18T12:28:28           1996 Dec   na  18  12  28 28 */
/*      1986-01-18T12                 1986 Jan   na  18  12  00 00 */
/*      1986-01-18T12:19              1986 Jan   na  18  12  19 00 */
/*      1986-01-18T12:19:52.18        1986 Jan   na  18  12  19 52.18 */
/*      1995-08T18:28:12              1995  na  008  na  18  28 12 */
/*      1995-18T                      1995  na  018  na  00  00 00 */


/*      Calendar Formats. */

/*      String                        Year   Mon DOM  HR Min  Sec */
/*      ----------------------------  ----   --- ---  -- ---  ------ */
/*      Tue Aug  6 11:10:57  1996     1996   Aug  06  11  10  57 */
/*      1 DEC 1997 12:28:29.192       1997   Dec  01  12  28  29.192 */
/*      2/3/1996 17:18:12.002         1996   Feb  03  17  18  12.002 */
/*      Mar 2 12:18:17.287 1993       1993   Mar  02  12  18  17.287 */
/*      1992 11:18:28  3 Jul          1992   Jul  03  11  18  28 */
/*      June 12, 1989 01:21           1989   Jun  12  01  21  00 */
/*      1978/3/12 23:28:59.29         1978   Mar  12  23  28  59.29 */
/*      17JUN1982 18:28:28            1982   Jun  17  18  28  28 */
/*      13:28:28.128 1992 27 Jun      1992   Jun  27  13  28  28.128 */
/*      1972 27 jun 12:29             1972   Jun  27  12  29  00 */
/*      '93 Jan 23 12:29:47.289       1993*  Jan  23  12  29  47.289 */
/*      27 Jan 3, 19:12:28.182        2027*  Jan  03  19  12  28.182 */
/*      23 A.D. APR 4, 18:28:29.29    0023** Apr  04  18  28  29.29 */
/*      18 B.C. Jun 3, 12:29:28.291   -017** Jun  03  12  29  28.291 */
/*      29 Jun  30 12:29:29.298       2029+  Jun  30  12  29  29.298 */
/*      29 Jun '30 12:29:29.298       2030*  Jun  29  12  29  29.298 */

/*      Day of Year Formats */

/*      String                        Year  DOY HR Min Sec */
/*      ----------------------------  ----  --- -- --- ------ */
/*      1997-162::12:18:28.827        1997  162 12  18 28.827 */
/*      162-1996/12:28:28.287         1996  162 12  28 28.287 */
/*      1993-321/12:28:28.287         1993  231 12  28 28.287 */
/*      1992 183// 12 18 19           1992  183 12  18 19 */
/*      17:28:01.287 1992-272//       1992  272 17  28 01.287 */
/*      17:28:01.282 272-1994//       1994  272 17  28 01.282 */
/*      '92-271/ 12:28:30.291         1992* 271 12  28 30.291 */
/*      92-182/ 18:28:28.281          1992* 182 18  28 28.281 */
/*      182-92/ 12:29:29.192          0182+ 092 12  29 29.192 */
/*      182-'92/ 12:28:29.182         1992  182 12  28 29.182 */


/*      Julian Date Strings */

/*      jd 28272.291                  Julian Date   28272.291 */
/*      2451515.2981 (JD)             Julian Date 2451515.2981 */
/*      2451515.2981 JD               Julian Date 2451515.2981 */

/*                                   Abbreviations Used in Tables */

/*                                      na    --- Not Applicable */
/*                                      Mon   --- Month */
/*                                      DOY   --- Day of Year */
/*                                      DOM   --- Day of Month */
/*                                      Wkday --- Weekday */
/*                                      Hr    --- Hour */
/*                                      Min   --- Minutes */
/*                                      Sec   --- Sec */

/*      * The default interpretation of a year that has been abbreviated */
/*      with a leading quote as in 'xy (such as '92) is to treat */
/*      the year as 19xy if xy > 68 and to treat it is 20xy otherwise. */
/*      Thus '70 is interpreted as 1970 and '67 is treated as 2067. */
/*      However, you may change the "split point" and centuries through */
/*      use of the SPICE routine TSETYR which is an entry point in */
/*      the SPICE module TEXPYR.  See that routine for a discussion of */
/*      how you may reset the split point. */

/*      ** All epochs are regarded as belonging to the Gregorian */
/*      calendar.  We formally extend the Gregorian calendar backward */
/*      and forward in time for all epochs.  If you have epochs belonging */
/*      to the Julian Calendar, consult the routines TPARTV and JUL2GR */
/*      for a discussion concerning conversions to the Gregorian */
/*      calendar and ET. */

/*      +  When a day of year format or calendar format string is */
/*      input and neither of integer components of the date */
/*      is greater than 1000, the first integer */
/*      is regarded as being the year. */

/*      Any integer greater than 1000 */
/*      is regarded as a year specification. Thus 1001-1821//12:28:28 */
/*      is interpreted as specifying two years and will be rejected */
/*      as ambiguous. */

/* $ Restrictions */

/*      None. */

/* $ Literature_References */

/*      None. */

/* $ Author_and_Institution */

/*      J.M. Lynch      (JPL) */
/*      W.M. Owen       (JPL) */
/*      M.J. Spencer    (JPL) */
/*      I.M. Underwood  (JPL) */
/*      W.L. Taber      (JPL) */

/* $ Version */

/* -    SPICELIB Version 5.0.0, 30-DEC-1997 (WLT) */

/*        The routine was modified to compensate for the inability */
/*        of the Muller-Wimberly formula to handle negative years */
/*        (that is years prior to 1 AD. */

/*        Comments concerning the default century used for two */
/*        digit years were upgraded. */

/* -    SPICELIB Version 4.0.0, 8-APR-1996 (WLT) */

/*        All of the token recognition and parsing was moved */
/*        into the routine TPARTV.  The entry point TPARCH */
/*        was moved to the routine TCHECK. */

/*        This routine now merely assembles the */
/*        parsed components to produce SP2000. */

/*        The number of strings now recognized has been greatly */
/*        increased.  However, the interpretation given to */
/*        strings such as  31 Jan 32 has been changed. */

/* -    SPICELIB Version 3.0.0, 30-JUL-1993 (WLT) */

/*        The entry point TPARCH was added so that users may */
/*        restrict the set of input calendar strings to those */
/*        that are in proper form. */

/* -    SPICELIB Version 2.0.1, 10-MAR-1992 (WLT) */

/*        Comment section for permuted index source lines was added */
/*        following the header. */

/* -    SPICELIB Version 2.0.0, 18-NOV-1991 (MJS) */

/*        TPARSE no longer accepts a blank time string. */

/* -    SPICELIB Version 1.0.1, 26-MAR-1991 (JML) */

/*        In the Detailed_Input section of the header, the */
/*        description of how default values are assigned to */
/*        tokens in STRING was clarified. */

/* -    SPICELIB Version 1.0.0, 31-JAN-1990 (WMO) (IMU) */

/* -& */
/* $ Index_Entries */

/*     parse a utc time string */

/* -& */
/* $ Revisions */

/* -    SPICELIB Version 5.0.0, 30-DEC-1997 (WLT) */

/*        The routine was modified to compensate for the inability */
/*        of the Muller-Wimberly formula to handle negative years */
/*        (that is years prior to 1 AD. */

/*        Comments concerning the default century used for two */
/*        digit years were upgraded. */

/* -    SPICELIB Version 4.0.0, 8-APR-1996 (WLT) */

/*        All of the token recognition and parsing was moved */
/*        into the routine TPARTV.  The entry point TPARCH */
/*        was moved to the routine TCHECK. */

/*        This routine now merely assembles the */
/*        the parsed components to produce SP2000. */

/* -    SPICELIB Version 3.0.0, 30-JUL-1993 (WLT) */

/*        The entry point TPARCH was added so that users may */
/*        restrict the set of input calendar strings to those */
/*        that are in proper form. */

/* -    SPICELIB Version 2.0.0, 18-NOV-1991 (MJS) */

/*        TPARSE no longer accepts a blank time string. Prior to */
/*        this fix, TPARSE interpreted a blank time string to be */
/*        -1577880000.000 UTC seconds (1 JAN 1950 00:00:00). */

/* -    SPICELIB Version 1.0.1, 26-MAR-1991 (JML) */

/*        In the Detailed_Input section of the header, the */
/*        description of how default values are assigned to */
/*        tokens in STRING was clarified. */

/*        NAIFers are accustomed to specifying day of year */
/*        formats of UTC strings in the following form: */

/*           1986-247 // 12:00:00 */

/*        This revision to the header states explicitly that */
/*        the // is a blank token which results in the default */
/*        value being assigned to the month token.  The previous */
/*        version of the header implied that tokens could be left */
/*        out or "missing" from the string, and that default values */
/*        would automatically be assigned.  This works only for */
/*        tokens missing from the right end of the string.  For */
/*        default values to be assigned to tokens missing from the */
/*        middle of a UTC string, consecutive delimiters such as */
/*        // or :: must be included. */


/* -& */

/*     SPICELIB functions */


/*     Parameters */


/*     Local variables */


/*     All the work of taking apart the string is handled */
/*     by TPARTV. */

    s_copy(error, " ", error_len, (ftnlen)1);
    succes = TRUE_;
    tpartv_(string, tvec, &ntvec, type__, modify, &mods, &yabbrv, &succes, 
	    pictur, error, string_len, (ftnlen)5, (ftnlen)8, (ftnlen)80, 
	    error_len);
    if (! succes) {
	return 0;
    }

/*     We are not going to support all of the various */
/*     time string modifiers that can be parsed. */

    if (mods) {
	if (s_cmp(modify + 32, " ", (ftnlen)8, (ftnlen)1) != 0) {
	    s_copy(error, "TPARSE does not support the specification of a ti"
		    "me system in a string.  The time system # was specified. "
		    , error_len, (ftnlen)106);
	    repmc_(error, "#", modify + 32, error, error_len, (ftnlen)1, (
		    ftnlen)8, error_len);
	    return 0;
	} else if (s_cmp(modify + 16, " ", (ftnlen)8, (ftnlen)1) != 0) {
	    s_copy(error, "TPARSE does not support the specification of a ti"
		    "me zone in a time string.  The time zone '#' was specifi"
		    "ed. ", error_len, (ftnlen)109);
	    repmc_(error, "#", modify + 16, error, error_len, (ftnlen)1, (
		    ftnlen)8, error_len);
	    return 0;
	} else if (s_cmp(modify + 24, " ", (ftnlen)8, (ftnlen)1) != 0) {
	    s_copy(error, "TPARSE does not support the AM/PM conventions for"
		    " time strings. ", error_len, (ftnlen)64);
	    return 0;
	}
    }
    if (s_cmp(type__, "JD", (ftnlen)5, (ftnlen)2) == 0) {

/*        Nothing to do but convert TVEC(1). */

	*sp2000 = (tvec[0] - j2000_()) * spd_();
    } else if (s_cmp(type__, "YMD", (ftnlen)5, (ftnlen)3) == 0 || s_cmp(
	    type__, "YD", (ftnlen)5, (ftnlen)2) == 0) {
	tcheck_(tvec, type__, &mods, modify, &ok, error, (ftnlen)5, (ftnlen)8,
		 error_len);
	if (! ok) {
	    return 0;
	}

/*        If we have day of year format, we move it into the */
/*        month-day of month format. */

	if (s_cmp(type__, "YD", (ftnlen)5, (ftnlen)2) == 0) {
	    tvec[5] = tvec[4];
	    tvec[4] = tvec[3];
	    tvec[3] = tvec[2];
	    tvec[2] = tvec[1];
	    tvec[1] = 1.;
	}

/*        Get the year month and day as integers. */

	year = i_dnnt(tvec);
	month = i_dnnt(&tvec[1]);
	day = i_dnnt(&tvec[2]);

/*        Fix up the year as needed. */

	if (s_cmp(modify, "B.C.", (ftnlen)8, (ftnlen)4) == 0) {
	    year = 1 - year;
	} else if (s_cmp(modify, "A.D.", (ftnlen)8, (ftnlen)4) == 0) {

/*           Do nothing. */

	} else if (year < 100) {
	    texpyr_(&year);
	}

/*        Apply the Muller-Wimberly formula and then tack on */
/*        the seconds. */

	if (year < 1) {

/*           The Muller-Wimberly formula doesn't work for years */
/*           less than 0.  So we boost the year by an appropriate */
/*           multiple of 400 and then subtract the appropriate */
/*           number of days later. */

	    adjust = TRUE_;
	    temp = year;
	    rmaini_(&temp, &c__400, &q, &year);
	    year += 400;
	    --q;
	} else {
	    adjust = FALSE_;
	}
	day = year * 367 - (year + (month + 9) / 12) * 7 / 4 - ((year + (
		month - 9) / 7) / 100 + 1) * 3 / 4 + month * 275 / 9 + day - 
		730516;
	if (adjust) {

/*           Adjust DAY by the appropriate multiple of 400 years. */

	    day += q * 146097;
	}
	*sp2000 = ((doublereal) day - .5) * spd_() + tvec[3] * 3600. + tvec[4]
		 * 60. + tvec[5];
    } else {

/*        We've already covered all the bases we are planning to */
/*        cover in this routine.  Any other case is regarded as an */
/*        error. */

	s_copy(error, "The only type of time strings that are handled by TPA"
		"RSE are 'JD', 'YMD' and 'YD' (year day-of-year).  You've ent"
		"ered a string of the type #. ", error_len, (ftnlen)142);
	repmc_(error, "#", type__, error, error_len, (ftnlen)1, (ftnlen)5, 
		error_len);
    }
    return 0;
} /* tparse_ */

