C @(#)getut.for	19.1 (ES0-DMD) 02/25/03 13:29:08
C===========================================================================
C Copyright (C) 1995 European Southern Observatory (ESO)
C
C This program is free software; you can redistribute it and/or 
C modify it under the terms of the GNU General Public License as 
C published by the Free Software Foundation; either version 2 of 
C the License, or (at your option) any later version.
C
C This program is distributed in the hope that it will be useful,
C but WITHOUT ANY WARRANTY; without even the implied warranty of
C MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
C GNU General Public License for more details.
C
C You should have received a copy of the GNU General Public 
C License along with this program; if not, write to the Free 
C Software Foundation, Inc., 675 Massachusetss Ave, Cambridge, 
C MA 02139, USA.
C
C Corresponding concerning ESO-MIDAS should be addressed as follows:
C	Internet e-mail: midas@eso.org
C	Postal address: European Southern Observatory
C			Data Management Division 
C			Karl-Schwarzschild-Strasse 2
C			D 85748 Garching bei Muenchen 
C			GERMANY
C===========================================================================
C
         SUBROUTINE GETUT (NLINE, UT)
C+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
C.COPYRIGHT (c)
C.IDENT         getut.for
C.MODULE
C.AUTHOR        Andrew T. Young
C.KEYWORD
C.LANGUAGE      FORTRAN 77
C.PURPOSE       gets U.T. from a comment line LINE(NLINE), or returns -1
C.COMMENTS
C.VERSION       5.2
C.RETURNS
C.ENVIRONMENT
C.
C-----------------------------------------------------------------------------
C
C  BEGIN Declarations:
C
        IMPLICIT NONE
C
        INTEGER MXLINE
        PARAMETER(MXLINE=100)
        CHARACTER*80 LINE(MXLINE)
        COMMON /LINES/LINE
C
        INTEGER I, J, K,KMAX,KMIN,LASTCOL
        INTEGER MCOL
        INTEGER NCOL,NCOLON,NLINE,NOFF,NTIMES,NUTS,NLSTS
        REAL TIMES(5)
        REAL UT
        CHARACTER*4 TYPES(5), TSTRING*12
C
        PARAMETER (NUTS=9, NLSTS=9)
        CHARACTER*8 UTS(NUTS), LSTS(NLSTS), CARD*81, CHAR*1
        CHARACTER*12 FMT, DUM*80
C
C
        LOGICAL MATCH
        INTEGER LWORD
        REAL TIMER
C
C
C
C  END Declarations.
C
C
C  BEGIN DATA statements:
C
        DATA UTS/' UT=', ' UT =', ' U.T.=', ' U.T. =',
     1          'UT:', 'U.T.:', 'U.T.', 'UT', ' U T'/
        DATA LSTS/' LST=', ' LST =', ' L.S.T.=', 'L.S.T. =',
     1          'LST:', 'L.S.T.:', 'L.S.T.', 'LST', '.ST:'/
C
C  END DATA statements.
C
C *****************************************************************
C
C  Program begins here:
C
        CARD=' '//LINE(NLINE)
        DO 1 LASTCOL=81,2,-1
        IF (CARD(LASTCOL:LASTCOL).NE.' ') GO TO 2
    1   CONTINUE
C               empty card; quit.
        UT=-1.
        RETURN
C
    2   NTIMES=0
        TSTRING=' '
        NCOL=INDEX(CARD,' IS ')
        IF (NCOL.GT.0) CARD(NCOL:NCOL+3)='='
        DO 20 I=1,NUTS
        NCOL=INDEX(CARD,UTS(I)(:LWORD(UTS(I))))
        NOFF=1
    3   IF (NCOL.NE.0) THEN
C       key found. Look for time string:
                NCOL=NCOL+NOFF-1
C               start in col. AFTER key:
                MCOL=NCOL+LWORD(UTS(I))
                DO 8 J=MCOL,LASTCOL-3
                    CHAR=CARD(J:J)
C                   skip blanks:
                    IF (CHAR.EQ.' ') GO TO 8
                    IF (CHAR.GE.'0' .AND. CHAR.LE.'9') THEN
C                        digit found;
C                        look for reasonable string after key:
                        KMAX=MIN(J+12, LASTCOL)
                        DO 4 K=J+1,KMAX
                            CHAR=CARD(K:K)
                            IF((CHAR.GE.'0'.AND.CHAR.LE.'9') .OR.
     1                         CHAR.EQ.'H' .OR. CHAR.EQ.'M' .OR.
     2                         CHAR.EQ.'S' .OR. CHAR.EQ.':' .OR.
     3                         CHAR.EQ.' ' .OR. CHAR.EQ.'.') GO TO 4
C                           quit if unacceptable char:
                            GO TO 5
    4                   CONTINUE
                        K=KMAX+1
    5                   K=K-1
                        TSTRING=CARD(J:K)
                        NTIMES=NTIMES+1
                        TIMES(NTIMES)=TIMER(TSTRING)
                        IF (TIMES(NTIMES).EQ.-1.) THEN
                                NTIMES=NTIMES-1
                                GO TO 10
                        ELSE
                                TYPES(NTIMES)='UT'
                                GO TO 30
                        END IF
                    ELSE
C                       try next key.
                        IF (INDEX(UTS(I),'=').NE.0) GO TO 19
                        IF (INDEX(UTS(I),':').NE.0) GO TO 19
C                       digit not found; look BEFORE key if no "=" or ":".
                        GO TO 10
                    END IF
    8           CONTINUE
C
C               scan cols. BEFORE key:
   10           DO 18 J=NCOL-1,1,-1
                    CHAR=CARD(J:J)
C                   skip blanks:
                    IF (CHAR.EQ.' ') GO TO 18
C                       look for reasonable string before key:
                        KMIN=MAX(J-12, 1)
                        DO 14 K=J,KMIN,-1
                            CHAR=CARD(K:K)
                            IF((CHAR.GE.'0'.AND.CHAR.LE.'9') .OR.
     1                         CHAR.EQ.'H' .OR. CHAR.EQ.'M' .OR.
     2                         CHAR.EQ.'S' .OR. CHAR.EQ.':' .OR.
     3                         CHAR.EQ.' ' .OR. CHAR.EQ.'.') GO TO 14
C                       quit if unacceptable char:
                        GO TO 15
   14                   CONTINUE
                        K=KMIN-1
   15                   K=K+1
C                       trim leading blanks:
                        DO 16 K=K,J
                        IF (CARD(K:K).NE.' ') GO TO 17
   16                   CONTINUE
   17                   TSTRING=CARD(K:J)
                        NTIMES=NTIMES+1
                        TIMES(NTIMES)=TIMER(TSTRING)
                        IF (TIMES(NTIMES).EQ.-1.) THEN
                                NTIMES=NTIMES-1
                                GO TO 19
                        ELSE
                                TYPES(NTIMES)='UT'
                                GO TO 30
                        END IF
   18           CONTINUE
C
C               Not found; so see if key appears later:
C
   19           NOFF=NCOL+1
                NCOL=INDEX(CARD(NOFF:),UTS(I)(:LWORD(UTS(I))))
                IF (NCOL.NE.0) THEN
                        GO TO 3
                ELSE
                END IF
        END IF
   20   CONTINUE
C
C       Nothing found.  Try without keys:
C
        NCOLON=INDEX(CARD,':')
        NOFF=1
   22   IF (NCOLON.GT.0) THEN
                NCOLON=NCOLON+NOFF-1
                IF (CARD(NCOLON-1:NCOLON-1).GE.'0' .AND.
     1              CARD(NCOLON-1:NCOLON-1).LE.'9' .AND.
     2              CARD(NCOLON+2:NCOLON+2).GE.'0' .AND.
     3              CARD(NCOLON+2:NCOLON+2).LE.'9') THEN
C                       found a colon flanked by digits.
                        TSTRING=CARD(NCOLON-2:NCOLON+5)
                        NTIMES=NTIMES+1
                        TIMES(NTIMES)=TIMER(TSTRING)
C
                        IF (TIMES(NTIMES).EQ.-1.) THEN
                                NTIMES=NTIMES-1
                                GO TO 30
                        ELSE
   25                           CALL TV(LINE(NLINE))
                                WRITE(FMT,'(''('',I2,''X,A5)'')')
     1                               NCOLON-4
                                WRITE(DUM,FMT) '^^^^^'
                                CALL TVN(DUM)
                                CALL ASK('Is this UT?',CHAR)
                                IF (MATCH (CHAR,'Y')) THEN
                                        TYPES(NTIMES)='UT'
                                        GO TO 30
                                ELSE IF (CHAR.EQ.'N') THEN
                                        NTIMES=NTIMES-1
C                                       Look for another colon:
                                        NOFF=NCOLON+4
                                        NCOLON=INDEX(CARD(NOFF:),':')
                                        IF (NCOLON.NE.0) GO TO 22
                                ELSE
                                        CALL TV('Please reply Y or N.')
                                        GO TO 25
                                END IF
                        END IF
                ELSE
C                       Look for another colon:
                        NOFF=NCOLON+1
                        NCOLON=INDEX(CARD(NOFF:),':')
                        IF (NCOLON.NE.0) GO TO 22
                END IF
        END IF
   30   CONTINUE
C
C       Assess results:
C
        IF (NTIMES.EQ.1) THEN
                UT=TIMES(1)
        ELSE IF (NTIMES.EQ.0) THEN
                UT=-1.
        ELSE
C               compare times:
                UT=TIMES(1)
        END IF
C
C
C
C
        RETURN
        END
        REAL FUNCTION TIMER(TSTRING)
C
C       extracts time (hours) from tstring.
C
        IMPLICIT NONE
C
        CHARACTER TSTRING*12, FMT*9, SUBSTRING*8, FSEP*1, STR2*12
C
        INTEGER NH,NCOLON, NM,NS
C
        REAL HOURS, TMIN,SECS
C
        INTEGER LWORD
C
C
        IF (TSTRING(:1).EQ.'S' .OR. TSTRING(:1).EQ.':') THEN
C               trim leading junk:
                STR2=TSTRING(2:)
                IF (STR2(:1).EQ.' ') THEN
                        TSTRING=STR2(2:)
                ELSE
                        TSTRING=STR2
                END IF
        END IF
C       Trim trailing nulls:
        NM=INDEX(TSTRING,CHAR(0))
        IF (NM.NE.0) TSTRING(NM:)=' '
        NH=INDEX(TSTRING,'H')
        NCOLON=INDEX(TSTRING,':')
C
        IF (NCOLON.NE.0) THEN
                FSEP=':'
        ELSE
                FSEP=' '
        END IF
C
        IF (NH.EQ.0) THEN
C               delimited string (colons or blanks)
                NH=INDEX(TSTRING,FSEP)
                WRITE (FMT,'(''(BN,F'',I1,''.0)'')') NH-1
                READ (TSTRING(1:NH-1),FMT, ERR=99) HOURS
                IF (HOURS.GT.24.) GO TO 99
                IF (TSTRING(NH+1:NH+1).EQ.' ') NH=NH+1
                SUBSTRING=TSTRING(NH+1:)
                NM=INDEX(SUBSTRING,FSEP)
                IF (NM.EQ.0) NM=LWORD(SUBSTRING)+1
                WRITE (FMT,'(''(BN,F'',I1,''.0)'')') NM-1
                READ (SUBSTRING(1:NM-1),FMT, ERR=99) TMIN
                FMT=SUBSTRING(NM+1:)
                SUBSTRING=FMT
                NS=LWORD(SUBSTRING)
                IF (NS.NE.0) THEN
C                       seconds are present.
                        WRITE (FMT,'(''(BN,F'',I1,''.0)'')') NS
                        READ (SUBSTRING(1:NS),FMT, ERR=99) SECS
                ELSE
                        SECS=0.
                END IF
                TIMER=HOURS+(TMIN+SECS/60.)/60.
                RETURN
        ELSE
C               NOT a field-separator-delimited string; look for H M S
                NM=INDEX(TSTRING,'M')
                NS=INDEX(TSTRING,'S')
C               assume H M S separators
                WRITE (FMT,'(''(BN,F'',I1,''.0)'')') NH-1
                READ (TSTRING(1:NH-1),FMT, ERR=99) HOURS
                WRITE (FMT,'(''(BN,F'',I1,''.0)'')') NM-NH-1
                READ (TSTRING(NH+1:NM-1),FMT, ERR=99) TMIN
                IF (NS.NE.0) THEN
C                       seconds are present.
                        WRITE (FMT,'(''(BN,F'',I1,''.0)'')') NS-NM-1
                        READ (TSTRING(NM+1:NS-1),FMT, ERR=99) SECS
                ELSE
                        SECS=0.
                END IF
                TIMER=HOURS+(TMIN+SECS/60.)/60.
                RETURN
        END IF
C
C       Error:
C
   99   TIMER=-1.
        RETURN
        END
      SUBROUTINE GETJDC(NLINE,DJ)
C
C  GETS DP JULIAN DAY FROM EXTERNAL COMMON BLOCK
C
C       Copyright (C) Andrew T. Young, 1990
C       Copyright (C) European Southern Observatory, 1992
C
C
      IMPLICIT NONE
C
      INTEGER NLINE
      DOUBLE PRECISION DJ
C
        INTEGER MXLINE
        PARAMETER (MXLINE=100)
        CHARACTER*80 LINE(MXLINE)
        COMMON /LINES/ LINE
C
      INTEGER IDCOL,I,M,MCOL,MXBACK,NCOL,K,MEND
      REAL DDAY,Y
C
      INTEGER MON2M
      LOGICAL MATCH
C
      CHARACTER*3 MON, MONTHS(12), LMONTH(12)
      CHARACTER*20 DATSTR, CH*1
C
        DATA LMONTH/'Jan','Feb','Mar','Apr','May','Jun','Jul',
     1              'Aug','Sep','Oct','Nov','Dec'/
        DATA MONTHS/'JAN','FEB','MAR','APR','MAY','JUN','JUL',
     1              'AUG','SEP','OCT','NOV','DEC'/
C
C
C    MON is 1st 3 letters of month,  M is integer.
C    YEAR is full year,  Y is internal.
C
C
      DATSTR=' '
      IDCOL=INDEX(LINE(NLINE),'DATE')
      IF (IDCOL.EQ.0) IDCOL=INDEX(LINE(NLINE),'Date')
      IF (IDCOL.NE.0) THEN
           DO 1 I=IDCOL+4,80
C               skip over delimiters:
                IF (LINE(NLINE)(I:I).EQ.' ' .OR.
     1              LINE(NLINE)(I:I).EQ.'=' .OR.
     2              LINE(NLINE)(I:I).EQ.':') THEN
                        GO TO 1
                ELSE
C                       Date begins.
                        DATSTR=LINE(NLINE)(I:)
                        GO TO 2
                END IF
    1      CONTINUE
    2      CONTINUE
      ELSE
C       Look for month name:
        DO 5 M=1,12
                MCOL=INDEX(LINE(NLINE),MONTHS(M))
                IF (MCOL.EQ.0) MCOL=INDEX(LINE(NLINE),LMONTH(M))
                IF (MCOL.NE.0)THEN
                        NCOL=MCOL
                        MXBACK=MIN(6,MCOL-1)
C                       see if numbers precede month...
    4                   DATSTR=LINE(NLINE)(NCOL-MXBACK:)
                        IF (DATSTR(:1).GE.'0'.AND.DATSTR(:1).LE.'9')THEN
                                GO TO 6
                        ELSE
                                NCOL=NCOL+1
                                IF (NCOL-MXBACK.LE.MCOL) GO TO 4
                        END IF
                        GO TO 6
                END IF
    5   CONTINUE
C       month not found, either;quit.
        RETURN
C
    6   CONTINUE
C       Find end of month name:
        DO 8 K=6-NCOL+MCOL+4,20
        CH=DATSTR(K:K)
        IF ( (CH.GE.'A' .AND. CH.LE.'Z') .OR.
     1       (CH.GE.'a' .AND. CH.LE.'z') ) THEN
C               still in month...
                GO TO 8
        ELSE
                MEND=K
                GO TO 9
        END IF
    8   CONTINUE
        MEND=20+1
    9   CONTINUE
C       Now try to trim superfluous junk from end of string:
        IF (DATSTR(:1).GE.'0'.AND. DATSTR(:1).LE.'9') THEN
C               date string starts with digits; allow only 1 numerical field
                IF (CH.EQ.' ' .OR. CH.EQ.'.') MEND=MEND+1
                DO 10 K=MEND,20
                CH=DATSTR(K:K)
                IF ((CH.GE.'0'.AND.CH.LE.'9')) GO TO 10
                DATSTR(K:)=' '
                GO TO 11
   10           CONTINUE
        ELSE
C               date string starts with month; allow 2 fields
                IF (INDEX(DATSTR(MEND+1:),',').EQ.0) THEN
C                       no commas in date
                        MEND=INDEX(DATSTR(MEND+7:),' ')
                        IF (MEND.GT.0) DATSTR(MEND:)=' '
                ELSE
C                        commas in date
                        MEND=INDEX(DATSTR(MEND+8:),' ')
                        IF (MEND.GT.0) DATSTR(MEND:)=' '
                END IF
        END IF
   11   CONTINUE
      END IF
C
      IF(DATSTR.NE.' ')THEN
C         analyse date string to get date fields.
   17     CALL MDYC(DATSTR,MON,DDAY,Y)
C         (returns XXX in MON if it can't identify month)
          IF (MON.EQ.'XXX' .OR. DDAY.GT.32. .OR. DDAY.LT.0. .OR.
     1        Y.LT.0. .OR.
     2        (Y.LT.1800. .AND. Y.GT.99.) .OR. Y.GT.2100.) THEN
                IF (IDCOL.EQ.0) RETURN
                CALL TV ('Ambiguous date string found:')
   18           CALL TV(DATSTR)
                CALL ASK ('Does this contain a date?',MON)
                IF (MATCH(MON,'Y'))THEN
                        CALL TV ('Please enter it more clearly,')
                        CALL ASKN ('spelling month correctly:',DATSTR)
                        GO TO 17
                ELSE IF (MATCH(MON,'N'))THEN
                        RETURN
                ELSE
                        CALL TV('Please reply "y" or "n".')
                        GO TO 18
                END IF
          END IF
      ELSE
C         nothing found, so do nothing.
          RETURN
C
      END IF
C
C     Convert month name to integer:
      M=MON2M(MON)
C
C    CHECK YEAR.
      IF(Y.LT.100.) THEN
C           ...about 2048 AD you can remove the first branch, or else
C          nudge the "50" along every decade or so...
           IF (Y.GT.50.)THEN
C               assume no data before 1950:
                Y=Y+1900.
           ELSE
                Y=Y+2000.
           END IF
      END IF
C  J.D.: see SKY & TEL.61,312 (1981).
      IF(M.GT.2)GO TO 416
      M=M+12
      Y=Y-1
  416 DJ=AINT(365.25*Y) + AINT(30.6001*(M+1)) + DDAY + 1720981.5D0
C
      RETURN
      END
      SUBROUTINE MDYC(CDIN,MONTH,DAY,YEAR)
C
C       Copyright (C) Andrew T. Young, 1990
C       Copyright (C) European Southern Observatory, 1992
C
C  EXTRACTS 3-CHAR.MONTH, FLOATING DAY & YEAR FROM STRING CDIN.   3 JAN.87
C
C  (modified to handle ESO data cards, May 1992)
C
      IMPLICIT NONE
C
      CHARACTER*(*) CDIN
      CHARACTER CARD*80, MONTH*3, FIELD*5, CHAR
      INTEGER NEXT,LAST,LENCD,I,I1,J
      REAL DAY,YEAR
C
      INTEGER LWORD
C
    1 FORMAT(A4)
C    SET ILLEGAL VALUES TO FLAG ERROR RETURNS.
      MONTH='XXX'
      DAY=99.
      YEAR=-1.
      CARD=CDIN
      LENCD=LWORD(CARD)
C       skip leading blanks...
      DO 2 I=1,LENCD
      IF(CARD(I:I).NE.' ') GO TO 5
    2 CONTINUE
      RETURN
C
    4 FORMAT(BN,F4.0)
C
C  FIRST NON-BLANK...
    5 ASSIGN 25 TO NEXT
      ASSIGN 21 TO LAST
      IF(CARD(I:I).GT.'9' .OR. CARD(I:I).LT.'0') GO TO 14
C   FIRST FIELD NUMERIC, SO MONTH SECOND.
      I1=I
      DO 6 I=I,LENCD
      CHAR=CARD(I:I)
      IF(CHAR.GT.'9' .OR. CHAR.LT.'0') GO TO 10
    6 CONTINUE
      RETURN
C
C   FIRST FIELD ENDS AT (I-1), I NON-NUM.
   10 WRITE(FIELD,1) CARD(I1:I-1)
      IF(I-I1-3) 11,24,20
C    1ST FIELD IS DAY.
   11 READ(FIELD,4)DAY
      ASSIGN 18 TO LAST
C     MONTH STARTS W.LETTER.
   12 DO 13 I=I,LENCD
      CHAR=CARD(I:I)
      IF(CHAR.GE.'A' .AND. CHAR.LE.'Z') GO TO 14
   13 CONTINUE
      RETURN
C
C      GET MONTH.
   14 MONTH=CARD(I:I+2)
      I=I+3
C     FIND LAST NUMERIC FIELD.
   15 DO 16 I=I,LENCD
      CHAR=CARD(I:I)
      IF(CHAR.GE.'0' .AND. CHAR.LE.'9') GO TO LAST,(18,21)
   16 CONTINUE
      RETURN
C    YEAR LAST.
   18 J=I+3
      IF(CARD(I+2:J).EQ.'  ')J=I+1
      WRITE(FIELD,1) CARD(I:J)
      READ(FIELD,4,ERR=19)YEAR
   19 RETURN
C
C    YEAR FIRST.
   20 READ(FIELD,4,ERR=24)YEAR
      ASSIGN 24 TO NEXT
      GO TO 12
C     (TO DO MONTH.)
C
C    DAY LAST. ENDS AT NON-NUM.I1.
   21 DO 22 I1=I+1,LENCD
      CHAR=CARD(I1:I1)
      IF(CHAR.GT.'9' .OR. CHAR.LT.'0') GO TO 23
   22 CONTINUE
      RETURN
C
   23 WRITE(FIELD,1) CARD(I:I1-1)
      READ(FIELD,4,ERR=24) DAY
C     Ridiculous statement needed to fool idiot MIDAS preprocessor:
      IF(.TRUE.)GO TO NEXT,(24,25)
   24 RETURN
C
C     SKIP 2ND PART OF DOUBLE DATE.
   25 I=I1+1
      ASSIGN 18 TO LAST
      IF(CARD(I1:I1).NE.'/' .AND. CARD(I1:I1).NE.'-') GO TO 15
C     DOUBLE DATE.  SKIP TO SEPARATOR.
      I=INDEX(CARD(I1:I1+3),',')
      IF(I.EQ.0) I=INDEX(CARD(I1:I1+3),' ')
      IF(I.EQ.0) GO TO 24
      I=I+I1
      GO TO 15
      END
      REAL FUNCTION STUTZROT(DJ)
C
C  Sets STUTZ in fractional days for given Julian Date.
C
      IMPLICIT NONE
C
      DOUBLE PRECISION DJ, DSTUTZ
C
      REAL T,STUTZ
C
C
      T=(DJ-2451545.0D0)/36525.D0
      DSTUTZ=(24110.54841D0+T*(8640184.812866D0+T*(.093104-T*6.21E-6)))
     1 /86400.
      STUTZ=DSTUTZ-DINT(DSTUTZ)
      IF(STUTZ.LT.0.)STUTZ=STUTZ+1.
      STUTZROT=STUTZ
      RETURN
      END
