C******************************************************************************* C C Copyright (C) 1993, California Institute of Technology. U.S. C Government Sponsorhip under NASA Contract NAS7-918 is C acknowledged. C C******************************************************************************* C Procedure CAL2CH C CHARACTER*(*) FUNCTION CAL2CH( YEAR, MONTH, DAY, * HOUR, MINUTE, SECOND, FRAC ) C C C Purpose C C This subroutine (CALendar date 2 CHaracter string) takes the various C components of an input calendar date and returns as its functional va C the equivalent time in the character*25 format 'DD-MMM-YYYY HH:MM:SS. C C If the user wishes to display only some initial segment of the calend C date, he may do so with his declaration of CAL2CH. For example, if he C wants to display 'DD-MMM-YYYY HH:MM:SS' then he may declare the funct C CAL2CH to be character*20. C C C Input_Arguments C C YEAR is the year. C MONTH is the month number. C DAY is the day. C HOUR is the hour. C MINUTE is the minute. C SECOND is the second. C FRAC is the fractional seconds. C C C Declarations_of_External_Functions C CHARACTER*5 INT2CH C C C Declarations_of_Input_and_Output_Arguments C INTEGER YEAR INTEGER MONTH INTEGER DAY INTEGER HOUR INTEGER MINUTE INTEGER SECOND DOUBLE PRECISION FRAC C C C Declarations_of_Local_Variables C CHARACTER*3 MONTHS(12) C CHARACTER*3 STR CHARACTER*31 NEWTIM DOUBLE PRECISION TEMP INTEGER NDIGIT INTEGER IDIGIT C C SAVE MONTHS C C Data_Statements C DATA MONTHS( 1) /'JAN'/ DATA MONTHS( 2) /'FEB'/ DATA MONTHS( 3) /'MAR'/ DATA MONTHS( 4) /'APR'/ DATA MONTHS( 5) /'MAY'/ DATA MONTHS( 6) /'JUN'/ DATA MONTHS( 7) /'JUL'/ DATA MONTHS( 8) /'AUG'/ DATA MONTHS( 9) /'SEP'/ DATA MONTHS(10) /'OCT'/ DATA MONTHS(11) /'NOV'/ DATA MONTHS(12) /'DEC'/ C C C Method C-& C*********************************************************************** C C1 Check to see if the input calendar date is out of bounds. IF( YEAR .LT. 0 )THEN CAL2CH = 'DISTANT-PAST' RETURN ELSEIF( YEAR .GT. 9999 )THEN CAL2CH = 'DISTANT-FUTURE' RETURN END IF C C------------------------------ C C1 Convert the time from integers to characters. C C2 Fractional seconds NDIGIT = MIN( LEN(CAL2CH), LEN(NEWTIM) ) - 21 TEMP = FRAC DO 20005 I = 1,NDIGIT TEMP = 10.0D0 * MOD( TEMP, 1.0D0 ) IDIGIT = INT( TEMP ) NEWTIM(21+I:21+I) = INT2CH( IDIGIT ) 20005 CONTINUE NEWTIM(21:21) = '.' C C2 Second NEWTIM(18:20) = INT2CH( SECOND + 100 ) NEWTIM(18:18) = ':' C C2 Minute NEWTIM(15:17) = INT2CH( MINUTE + 100 ) NEWTIM(15:15) = ':' C C2 Hour NEWTIM(12:14) = INT2CH( HOUR + 100 ) NEWTIM(12:12) = ' ' C C2 Year NEWTIM(8:11) = INT2CH( YEAR ) NEWTIM(7:7) = '-' C C2 Month NEWTIM(4:6) = MONTHS( MONTH ) NEWTIM(3:3) = '-' C C2 Day STR = INT2CH( DAY + 100 ) IF ( STR(2:2) .EQ. '0' ) STR(2:2) = ' ' NEWTIM(1:2) = STR(2:3) C C C1 Return the converted time string. CAL2CH = NEWTIM C RETURN END C Procedure CAL2JD C DOUBLE PRECISION FUNCTION CAL2JD * ( YEAR, MONTH, DAY, HOUR, MINUTE, SECOND, FRAC ) C C C Purpose C C This double precision function (CALendar date to Julian Date) takes t C components of a calendar date and time C C Year / Month / Day , Hour : Minute : Second.Frac C C and returns the corresponding Julian date. C C The values for MONTH, DAY, HOUR, MINUTE, SECOND, and FRACtional secon C not have to lie within the usual range, i.e., MONTH=13 and DAY=212 ar C legitimate. C C C Input_Arguments C C YEAR is the year. C MONTH is the month number. C DAY is the day. C HOUR is the hour. C MINUTE is the minute. C SECOND is the second. C FRAC is the fractional seconds. C C C Output_Arguments C C Declarations_of_External_Functions C INTEGER DATE2J C C C Declarations_of_Input_and_Output_Arguments C INTEGER YEAR INTEGER MONTH INTEGER DAY INTEGER HOUR INTEGER MINUTE INTEGER SECOND DOUBLE PRECISION FRAC C C C Declarations_of_Local_Variables C C Method C-& C*********************************************************************** C C1 Call DATE2J to convert the date (year, month, day) to the integer C1 Julian date at noon of that day. CAL2JD = DATE2J( YEAR, MONTH, DAY ) - 0.5D0 + * (3600.D0*HOUR + 60.D0*MINUTE + SECOND + FRAC) / 86400.D0 C RETURN END C Procedure CALSEC C DOUBLE PRECISION FUNCTION CALSEC * ( YEAR, MONTH, DAY, HOUR, MINUTE, SECOND, FRAC ) C C C Purpose C C This double precision function (CALendar date to SEConds) takes the C components of a calendar date and time C C Year / Month / Day , Hour : Minute : Second.Frac C C and returns the corresponding seconds past the reference date (JDREF) C this library. C C C Input_Arguments C C YEAR is the year. C MONTH is the month number. C DAY is the day. C HOUR is the hour. C MINUTE is the minute. C SECOND is the second. C FRAC is the fractional seconds. C C C Output_Arguments C C Declarations_of_External_Functions C INTEGER DATE2J DOUBLE PRECISION JD2SEC C C C Declarations_of_Input_and_Output_Arguments C INTEGER YEAR INTEGER MONTH INTEGER DAY INTEGER HOUR INTEGER MINUTE INTEGER SECOND DOUBLE PRECISION FRAC C C C Declarations_of_Local_Variables C DOUBLE PRECISION JD C C C Method C-& C*********************************************************************** C C1 Call DATE2J to compute the double precision Julian date at the start C1 the current day. JD = DATE2J( YEAR, MONTH, DAY ) - 0.5D0 C C1 Call JD2SEC to compute the seconds past the reference date at the st C1 of the current day and then add in the seconds in the remaining frac C1 day. CALSEC = JD2SEC( JD ) * + HOUR * 3600.0D0 * + MINUTE * 60.0D0 * + SECOND * + FRAC C RETURN END C Procedure CASCHG C SUBROUTINE CASCHG( INSTR, OUTSTR ) C C C Purpose C C This subroutine (CASe CHanGe) will take an input character string and C all occurances of lowercase letters with the corresponding uppercase C C C Input_Arguments C C INSTR is the input character string. C C C Output_Arguments C C OUTSTR is the output character string. This string may the same as C input string. C C C Declarations_of_External_Functions C C Declarations_of_Input_and_Output_Arguments C CHARACTER*(*) INSTR CHARACTER*(*) OUTSTR C C C Declarations_of_Local_Variables C CHARACTER*26 LOWER CHARACTER*26 UPPER C C C Data_Statements C DATA LOWER /'abcdefghijklmnopqrstuvwxyz'/ DATA UPPER /'ABCDEFGHIJKLMNOPQRSTUVWXYZ'/ C C C Method C-& C*********************************************************************** C OUTSTR = INSTR C DO 20002 I = 1,MIN( LEN(INSTR), LEN(OUTSTR) ) N = INDEX( LOWER, OUTSTR(I:I) ) IF ( N .GT. 0 ) OUTSTR(I:I) = UPPER(N:N) 20002 CONTINUE C RETURN END C Procedure CH2CAL C SUBROUTINE CH2CAL( STRING, MSG, * YEAR, MONTH, DAY, HOUR, MINUTE, SECOND, FRAC, * ERROR ) C C C Purpose C C This subroutine (CHaracter string 2 CALendar date) will parse an inpu C character string containing the date and time in the format C 'DD-MMM-YYYY HH:MM:SS.FFFF' and return the seven components of this d C and time converted to numbers. C C The user may input only an initial segment of the date/time string, b C the input string must include at least the day, month, and year. C C C Input_Arguments C C STRING is the input date and time in the format C 'DD-MMM-YYYY HH:MM:SS.FFFF'. The fractional seconds, seconds C minutes, and/or hours may be omitted if their intended value C zero. C MSG controls the response to an input error. C If MSG=true and the input STRING contains a string which can C be parsed, then an error message is written to the standa C system output file and the program is terminated with a C walkback. C If MSG=false and the input STRING contains a string which ca C be parsed, no message is written but ERROR=true is return C C C C C Output_Arguments C C YEAR is the year. C MONTH is the month number. C DAY is the day. C HOUR is the hour. C MINUTE is the minute. C SECOND is the second. C FRAC is the fractional seconds. C ERROR = true if the input string cannot be parsed; otherwise, C ERROR=false is returned. C C C Declarations_of_External_Functions C INTEGER CH2INT DOUBLE PRECISION CH2DP C C C Declarations_of_Input_and_Output_Arguments C CHARACTER*(*) STRING LOGICAL MSG INTEGER YEAR INTEGER MONTH INTEGER DAY INTEGER HOUR INTEGER MINUTE INTEGER SECOND DOUBLE PRECISION FRAC LOGICAL ERROR C C C Declarations_of_Local_Variables C CHARACTER*80 BUFFER C INTEGER S INTEGER E INTEGER NDIGIT C INTEGER INT C LOGICAL FIND C INTEGER IERROR CHARACTER*40 ERRMSG(5) C CHARACTER*3 MONTHS(12) C C SAVE MONTHS SAVE ERRMSG C C Data_Statements C DATA MONTHS( 1) /'JAN'/ DATA MONTHS( 2) /'FEB'/ DATA MONTHS( 3) /'MAR'/ DATA MONTHS( 4) /'APR'/ DATA MONTHS( 5) /'MAY'/ DATA MONTHS( 6) /'JUN'/ DATA MONTHS( 7) /'JUL'/ DATA MONTHS( 8) /'AUG'/ DATA MONTHS( 9) /'SEP'/ DATA MONTHS(10) /'OCT'/ DATA MONTHS(11) /'NOV'/ DATA MONTHS(12) /'DEC'/ C DATA ERRMSG(1) /'Name of month not found'/ DATA ERRMSG(2) /'Year not found'/ DATA ERRMSG(3) /'Too many digits in fractional seconds'/ DATA ERRMSG(4) /'No decimal before fractional seconds'/ DATA ERRMSG(5) /'Too many digits in integer'/ C C C Method C-& C*********************************************************************** C1 Main Routine C*********************************************************************** C ERROR = .FALSE. C CALL CASCHG( STRING, BUFFER ) C GO TO 30001 C 20002 GO TO 30002 C 20003 GO TO 30003 C 20004 GO TO 30004 C 20005 GO TO 30005 C 20006 GO TO 30006 C 20007 GO TO 30007 C 20008 RETURN C C*********************************************************************** C1 Procedures C*********************************************************************** C C PROCEDURE (GET DAY NUMBER) C 30001 S = 1 ASSIGN 20009 TO NPR008 GO TO 30008 20009 DAY = INT C GO TO 20002 C C*********************************************************************** C C PROCEDURE (GET MONTH NUMBER) C 30002 S = E + 1 C DO 20011 I = 1,12 N = INDEX( BUFFER(S:), MONTHS(I) ) IF( N .GT. 0 )THEN MONTH = I E = S + N GO TO 20010 END IF 20011 CONTINUE IERROR = 1 ASSIGN 20016 TO NPR009 GO TO 30009 C 20016 CONTINUE 20010 GO TO 20003 C C*********************************************************************** C C PROCEDURE (GET YEAR) C 30003 S = E + 1 ASSIGN 20017 TO NPR008 GO TO 30008 20017 YEAR = INT IF (.NOT.( YEAR .LE. 0 )) GO TO 20019 IERROR = 2 ASSIGN 20020 TO NPR009 GO TO 30009 C 20020 CONTINUE 20019 GO TO 20004 C C*********************************************************************** C C PROCEDURE (GET HOURS) C 30004 S = E + 1 ASSIGN 20021 TO NPR008 GO TO 30008 20021 HOUR = INT C GO TO 20005 C C*********************************************************************** C C PROCEDURE (GET MINUTES) C 30005 S = E + 1 ASSIGN 20022 TO NPR008 GO TO 30008 20022 MINUTE = INT C GO TO 20006 C C*********************************************************************** C C PROCEDURE (GET INTEGRAL SECONDS) C 30006 S = E + 1 ASSIGN 20023 TO NPR008 GO TO 30008 20023 SECOND = INT C GO TO 20007 C C*********************************************************************** C C PROCEDURE (GET FRACTIONAL SECONDS) C 30007 S = E + 1 C ASSIGN 20024 TO NPR010 GO TO 30010 C 20024 NDIGIT = E - S + 1 IF (.NOT.( .NOT. FIND )) GO TO 20026 FRAC = 0.0 GO TO 20025 20026 IF (.NOT.( NDIGIT .GT. 10 )) GO TO 20027 IERROR = 3 ASSIGN 20028 TO NPR009 GO TO 30009 20028 GO TO 20025 20027 IF (.NOT.( BUFFER(S-1:S-1) .NE. '.' )) GO TO 20029 IERROR = 4 ASSIGN 20030 TO NPR009 GO TO 30009 20030 GO TO 20025 20029 FRAC = CH2DP( BUFFER(S-1:E) ) C 20025 GO TO 20008 C C*********************************************************************** C C PROCEDURE (GET NEXT INTEGER INT) C 30008 ASSIGN 20031 TO NPR010 GO TO 30010 C 20031 NDIGIT = E - S + 1 IF (.NOT.( .NOT. FIND )) GO TO 20033 INT = 0 GO TO 20032 20033 IF (.NOT.( NDIGIT .GT. 10 )) GO TO 20034 IERROR = 5 ASSIGN 20035 TO NPR009 GO TO 30009 20035 GO TO 20032 20034 INT = CH2INT( BUFFER(S:E) ) C 20032 GO TO NPR008,(20009,20017,20021,20022,20023) C C*********************************************************************** C C PROCEDURE (FIND START S AND END E OF NEXT DIGIT STRING) C 30010 N = S DO 20037 S = N,LEN(STRING) IF ( INDEX( '1234567890', BUFFER(S:S) ) .GT. 0 ) GO TO 20036 20037 CONTINUE E = S FIND = .FALSE. GO TO 31010 C 20036 DO 20040 E = S+1,LEN(STRING) IF ( INDEX( '1234567890', BUFFER(E:E) ) .LE. 0 ) GO TO 20041 20040 CONTINUE 20041 E = E - 1 FIND = .TRUE. C 31010 GO TO NPR010,(20024,20031) C C*********************************************************************** C C PROCEDURE (PROCESS INPUT ERROR) C 30009 IF(MSG)THEN WRITE(*,110) STRING, ERRMSG( IERROR ) 110 FORMAT(' ','Error - ''',A,'''', * /' ',' is not a legitimate date/time string', * /' ',' ',A) C CALL HALT ELSE ERROR = .TRUE. RETURN END IF C GO TO NPR009,(20016,20020,20028,20030,20035) C C*********************************************************************** C END C Procedure CH2DP C DOUBLE PRECISION FUNCTION CH2DP( STRING ) C C C Purpose C C This double precision function (CHaracter 2 Double Precision) takes t C character string STRING and returns the double precision equivalent. C string STRING must contain a legitimate number, either floating point C integer. Any blanks in the input STRING are ignored. C C C Input_Arguments C C STRING is a character string. C C C Declarations_of_External_Functions C C Declarations_of_Input_and_Output_Arguments C CHARACTER*(*) STRING C C C Declarations_of_Local_Variables C DOUBLE PRECISION DP INTEGER ISTAT C C C Data_Statements C C Method C-& C*********************************************************************** C1 Main Routine C*********************************************************************** C CALL CH2DPX( STRING, .TRUE., DP, ISTAT ) C CH2DP = DP C RETURN END C Use MAXEXP = INT( LOG10( D1MACH(2) ) ) C to check if input numbers are out of range??? C C C Procedure CH2DPX C SUBROUTINE CH2DPX( CH, MSG, DP, ISTAT ) C C C Purpose C C This subroutine (CHaracter 2 Double Precision X) takes the input char C string CH and returns the double precision numeric equivalent DP. The C CH must contain a legitimate number, either floating point or integer C Leading and trailing blanks are ignored but any other character in CH C is not a digit or an exponent delimiter ('D' or 'E') will cause a fat C error. In particular, embedded blanks are not allowed. C C C Input_Arguments C C CH is the character string to be converted to a double precision C MSG is a logical flag which controls the response to an error con C If MSG=.TRUE. and an error is encountered, then an error mess C written to the standard system output file and the program C terminated with a walkback. C If MSG=.FALSE. and an error is encountered, then no error mes C written but ISTAT<0 is returned. C C C Output_Arguments C C DP is the double precision equivalent of the number in the chara C string CH. C ISTAT is the error status flag: C ISTAT=0 if the request was successful. The other output C arguments are defined. C ISTAT>0 if the request was successful but some warning co C prevails that the user may wish to be aware of. T C other output arguments are defined. C ISTAT<0 if the request was unsuccessful. The other output C arguments are undefined and should not be used. C C C Declarations_of_External_Functions C DOUBLE PRECISION D1MACH C C C Declarations_of_Input_and_Output_Arguments C DOUBLE PRECISION DP LOGICAL MSG CHARACTER*(*) CH INTEGER ISTAT C C C Declarations_of_Local_Variables C PARAMETER ( MAXLEN = 30 ) C INTEGER N1 INTEGER N2 INTEGER LENGTH C CHARACTER*(MAXLEN) CTEMP1 CHARACTER*(MAXLEN) CTEMP2 C INTEGER MSGNUM C C SAVE C C C Data_Statements C C Method C-& C*********************************************************************** C1 Main Routine C*********************************************************************** C C2 Trim leading and trailing blanks. DO 20002 N1 = 1,LEN(CH) IF ( CH(N1:N1) .NE. ' ' ) GO TO 20003 20002 CONTINUE 20003 DO 20005 N2 = LEN(CH),1,-1 IF ( CH(N2:N2) .NE. ' ' ) GO TO 20006 20005 CONTINUE C C2 Verify that the trimmed string is not empty. 20006 IF (.NOT.( N1 .GT. N2 )) GO TO 20009 MSGNUM = 1 ASSIGN 20010 TO NPR001 GO TO 30001 C 20010 CONTINUE 20009 LENGTH = N2 - N1 + 1 IF (.NOT.( LENGTH .GT. MAXLEN )) GO TO 20012 MSGNUM = 2 ASSIGN 20013 TO NPR001 GO TO 30001 C C2 If the input number is an integer, add a decimal point. 20013 CONTINUE 20012 CTEMP1 = CH( N1:N2 ) IF( INDEX( CTEMP1, '.' ) .EQ. 0 )THEN CTEMP1 = CTEMP1(:LENGTH) // '.' LENGTH = LENGTH + 1 END IF C C2 Convert the input string to a double precision using a FORTRAN inter C2 file. CTEMP2 = ' ' CTEMP2( MAXLEN-LENGTH+1: ) = CTEMP1 READ ( UNIT=CTEMP2, FMT='(D30.22)', IOSTAT=IOS ) DP IF (.NOT.( IOS .GT. 0 )) GO TO 20017 MSGNUM = 3 ASSIGN 20018 TO NPR001 GO TO 30001 C 20018 CONTINUE 20017 RETURN C C*********************************************************************** C1 Procedures C*********************************************************************** C C PROCEDURE (WRITE ERROR MESSAGE NUMBER MSGNUM) C 30001 IF ( .NOT. MSG) RETURN C WRITE(*,*) 'ERROR - Unable to convert string to ', * 'double precision number' WRITE(*,*) ' Input string = ', CH GO TO (20021,20022,20023), MSGNUM GO TO 20020 20021 WRITE(*,*) ' String is empty' GO TO 20020 20022 WRITE(*,*) ' String is too long' GO TO 20020 20023 READ ( UNIT=CTEMP2, FMT='(D30.22)' ) DP C C20020 CALL HALT 20020 CONTINUE C GO TO NPR001,(20010,20013,20018) C C*********************************************************************** C END C Procedure CH2INT C INTEGER FUNCTION CH2INT( STRING ) C C C Purpose C C This integer function takes the input character string STRING and ret C integer equivalent. The string STRING must contain a legitimate integ C Any blanks in the input STRING are ignored. C C C Input_Arguments C C STRING is a character string. C C C Declarations_of_Input_and_Output_Arguments C CHARACTER*(*) STRING C C C Declarations_of_Local_Variables C INTEGER ICHR INTEGER LENGTH C CHARACTER*1 CHR C INTEGER INT C LOGICAL MINUS C C C Data_Statements C C Method C-& C*********************************************************************** C1 Main Routine C*********************************************************************** C GO TO 30001 C 20002 ASSIGN 20003 TO NPR002 GO TO 30002 20003 IF (.NOT.( CHR .EQ. '+' )) GO TO 20005 ASSIGN 20006 TO NPR002 GO TO 30002 20006 GO TO 20004 20005 IF (.NOT.( CHR .EQ. '-' )) GO TO 20007 MINUS = .TRUE. ASSIGN 20008 TO NPR002 GO TO 30002 20008 CONTINUE 20007 CONTINUE C 20004 IF (.NOT.( CHR .EQ. ' ' )) GO TO 20009 ASSIGN 20009 TO NPR003 GO TO 30003 C 20009 CONTINUE 20010 IF (.NOT.( CHR .NE. ' ' )) GO TO 20011 N = INDEX( '0123456789', CHR ) - 1 IF (.NOT.( N .LT. 0 )) GO TO 20012 ASSIGN 20012 TO NPR003 GO TO 30003 20012 INT = 10*INT + N ASSIGN 20013 TO NPR002 GO TO 30002 20013 GO TO 20010 C 20011 IF(MINUS)THEN CH2INT = -INT ELSE CH2INT = INT END IF C RETURN C C*********************************************************************** C1 Procedures C*********************************************************************** C C PROCEDURE (INITIALIZE) C 30001 LENGTH = LEN( STRING ) ICHR = 0 MINUS = .FALSE. INT = 0 C GO TO 20002 C C*********************************************************************** C C PROCEDURE (GET CHR: THE NEXT NONBLANK CHARACTER IN STRING) C 30002 CONTINUE 20016 ICHR = ICHR + 1 IF( ICHR .GT. LENGTH )THEN CHR = ' ' GO TO 20017 ELSE CHR = STRING(ICHR:ICHR) IF ( CHR .NE. ' ' ) GO TO 20017 END IF GO TO 20016 C 20017 GO TO NPR002,(20003,20006,20008,20013) C C*********************************************************************** C C PROCEDURE (WRITE ERROR MESSAGE) C 30003 WRITE(*,*) 'ERROR - Unable to convert string to integer: ', * 'String = ''', STRING, '''' C CALL HALT C GO TO NPR003,(20009,20012) C C*********************************************************************** C END C Procedure CH2JD C DOUBLE PRECISION FUNCTION CH2JD( STRING, MSG, ERROR ) C C C Purpose C C This double precision function (CHaracter string 2 Julian Date) will C an input character string containing the date and time in the format C 'DD-MMM-YYYY HH:MM:SS.FFFF' and return as its functional value the C corresponding Julian date. C C The user may input only an initial segment of the date/time string, b C the input string must include at least the day, month, and year. C C C Input_Arguments C C STRING is the input data and time in the format C 'DD-MMM-YYYY HH:MM:SS.FFFF'. The fractional seconds, seconds C minutes, and/or hours may be omitted if their intended value C zero. C MSG controls the response to an input error. C If MSG=true and the input STRING contains a string which can C be parsed, then an error message is written to the standa C system output file and the program is terminated with a C walkback. C If MSG=false and the input STRING contains a string which ca C be parsed, no message is written but ERROR=true is return C C C Output_Arguments C C ERROR = true if and only if MSG=false and the input string cannot C parsed; otherwise ERROR=false is returned. C C C Declarations_of_External_Functions C DOUBLE PRECISION CAL2JD C C C Declarations_of_Input_and_Output_Arguments C CHARACTER*(*) STRING LOGICAL MSG LOGICAL ERROR C C C Declarations_of_Local_Variables C INTEGER YEAR INTEGER MONTH INTEGER DAY INTEGER HOUR INTEGER MINUTE INTEGER SECOND DOUBLE PRECISION FRAC C C C Method C-& C*********************************************************************** C C1 Call CH2CAL to convert the character string to a calendar date. CALL CH2CAL( STRING, MSG, * YEAR, MONTH, DAY, HOUR, MINUTE, SECOND, FRAC, * ERROR ) IF (ERROR) THEN ch2jd = 0 RETURN end IF C C1 Call CAL2JD to convert the calendar date to the Julian date. CH2JD = CAL2JD( YEAR, MONTH, DAY, HOUR, MINUTE, SECOND, FRAC ) C RETURN END C Procedure CH2SEC C DOUBLE PRECISION FUNCTION CH2SEC( STRING, MSG, ERROR ) C C C Purpose C C This double precision function (CHaracter string 2 SEConds) will pars C an input character string containing the date and time in the format C 'DD-MMM-YYYY HH:MM:SS.FFFF' and return as its functional value the C corresponding seconds past the reference date (JDREF) for this librar C C The user may input only an initial segment of the date/time string, b C the input string must include at least the day, month, and year. C C C Input_Arguments C C STRING is the input data and time in the format C 'DD-MMM-YYYY HH:MM:SS.FFFF'. The fractional seconds, seconds C minutes, and/or hours may be omitted if their intended value C zero. C MSG controls the response to an input error. C If MSG=true and the input STRING contains a string which can C be parsed, then an error message is written to the standa C system output file and the program is terminated with a C walkback. C If MSG=false and the input STRING contains a string which ca C be parsed, no message is written but ERROR=true is return C C C Output_Arguments C C ERROR = true if and only if MSG=false and the input string cannot C parsed; otherwise ERROR=false is returned. C C C Declarations_of_External_Functions C DOUBLE PRECISION CALSEC C C C Declarations_of_Input_and_Output_Arguments C CHARACTER*(*) STRING LOGICAL MSG LOGICAL ERROR C C C Declarations_of_Local_Variables C INTEGER YEAR INTEGER MONTH INTEGER DAY INTEGER HOUR INTEGER MINUTE INTEGER SECOND DOUBLE PRECISION FRAC C C C Method C-& C*********************************************************************** C C1 Call CH2CAL to convert the input string to the components of the c C1 date and time. CALL CH2CAL( STRING, MSG, * YEAR, MONTH, DAY, HOUR, MINUTE, SECOND, FRAC, * ERROR ) C C1 Call CALSEC to convert the components of the calendar date to seco C1 past the reference date. IF ( .NOT. ERROR ) * CH2SEC = CALSEC( YEAR, MONTH, DAY, HOUR, MINUTE, SECOND, FRAC ) C RETURN END C Procedure DATE2J C INTEGER FUNCTION DATE2J( YEAR, MONTH, DAY ) C C C Purpose C C This integer function (calendar DATE 2 Julian date) takes the input C Gregorian calendar date and returns as its functional value the C corresponding integer Julian date. Since the Julian date is an intege C this correspondence is exact for noon of the output calendar date. C C The algorithm for this conversion is taken from the following article C Tantzen,R.T., "Communications of the ACM", Volume 6, Number 8, August C Algorithm 199, page 444. C C C Input_Arguments C C YEAR is the year number. C MONTH is the month number. C DAY is the day number. C C C Output_Arguments C C Declarations_of_External_Functions C C Declarations_of_Input_and_Output_Arguments C INTEGER YEAR INTEGER MONTH INTEGER DAY C C C Declarations_of_Local_Variables C INTEGER Y INTEGER M INTEGER D C INTEGER C INTEGER YA C C C Method C-& C*********************************************************************** C Y = YEAR M = MONTH D = DAY C IF( M .GT. 2 )THEN M = M - 3 ELSE M = M + 9 Y = Y - 1 END IF C C = Y/100 YA = Y - 100*C DATE2J = (146097*C)/4 + (1461*YA)/4 + (153*M+2)/5 + D + 1721119 C RETURN END C Procedure INT2CH C CHARACTER*(*) FUNCTION INT2CH( INT ) C C C Purpose C C This character*(*) function (INTeger 2 CHaracter) takes the input int C INT and returns the equivalent character string representation left C justified and padded with blanks on the the right. For example, if IN C is declared as CHARACTER*5 in the calling routine then INT2CH(23) wil C return the five character string '23 '. C C C Input_Arguments C C INT is an integer. C C C Declarations_of_Input_and_Output_Arguments C INTEGER INT C C C Declarations_of_Local_Variables C PARAMETER ( MAXLEN = 15 ) C LOGICAL MINUS INTEGER ITEMP CHARACTER*(MAXLEN) STRING C CHARACTER*1 DIGIT(0:9) C C C Data_Statements C DATA DIGIT(0) / '0' / DATA DIGIT(1) / '1' / DATA DIGIT(2) / '2' / DATA DIGIT(3) / '3' / DATA DIGIT(4) / '4' / DATA DIGIT(5) / '5' / DATA DIGIT(6) / '6' / DATA DIGIT(7) / '7' / DATA DIGIT(8) / '8' / DATA DIGIT(9) / '9' / C C C Method C-& C*********************************************************************** C IF( INT .LT. 0 )THEN MINUS = .TRUE. ELSE MINUS = .FALSE. END IF C ITEMP = ABS( INT ) ICHR = MAXLEN + 1 STRING = ' ' C GO TO 20006 20004 IF ( ITEMP .EQ. 0 ) GO TO 20005 20006 JTEMP = ITEMP/10 N = ITEMP - 10*JTEMP ICHR = ICHR - 1 STRING(ICHR:ICHR) = DIGIT(N) ITEMP = JTEMP GO TO 20004 C 20005 IF(MINUS)THEN ICHR = ICHR - 1 STRING(ICHR:ICHR) = '-' END IF C INT2CH = STRING( ICHR:MAXLEN ) C RETURN END C Procedure J2DATE C SUBROUTINE J2DATE( JD, YEAR, MONTH, DAY ) C C C Purpose C C This subroutine (Julian date 2 calendar DATE) converts the input inte C Julian date to the corresponding Gregorian calendar date. Since the J C date is an integer, this correspondence is exact for noon of the cale C date. C C The algorithm for this conversion is taken from the following article C Tantzen,R.T., "Communications of the ACM", Volume 6, Number 8, August C Algorithm 199, page 444. C C C Input_Arguments C C JD is the integer Julian date. C C C Output_Arguments C C YEAR is the year number. C MONTH is the month number. C DAY is the day number. C C C Output_Arguments C C Declarations_of_External_Functions C C Declarations_of_Input_and_Output_Arguments C INTEGER JD INTEGER YEAR INTEGER MONTH INTEGER DAY C C C Declarations_of_Local_Variables C INTEGER J INTEGER Y INTEGER M INTEGER D C C C Method C-& C*********************************************************************** C J = JD C C J = J - 1721119 Y = (4*J-1)/146097 J = 4*J - 1 - 146097*Y D = J/4 J = (4*D+3)/1461 D = 4*D + 3 -1461*J D = (D+4)/4 M = (5*D-3)/153 D = 5*D - 3 - 153*M D = (D+5)/5 Y = 100*Y + J IF( M .LT. 10 )THEN M = M + 3 ELSE M = M - 9 Y = Y + 1 END IF C C YEAR = Y MONTH = M DAY = D C RETURN END C Procedure JD2CAL C SUBROUTINE JD2CAL( JD, YEAR, MONTH, DAY, * HOUR, MINUTE, SECOND, FRAC ) C C C Purpose C C This subroutine (Julian Date 2 CALendar date) takes an input Julian d C and returns the various components of the corresponding calendar date C The components of the calendar date are all returned as numbers to al C for use in computation. For instance, the month is returned as the C integer month number rather than as a character string. C C C Input_Arguments C C JD is the Julian date. C C C Output_Arguments C C YEAR is the year. C MONTH is the month number. C DAY is the day. C HOUR is the hour. C MINUTE is the minute. C SECOND is the second. C FRAC is the fractional seconds. C C C Declarations_of_Input_and_Output_Arguments C DOUBLE PRECISION JD INTEGER YEAR INTEGER MONTH INTEGER DAY INTEGER HOUR INTEGER MINUTE INTEGER SECOND DOUBLE PRECISION FRAC C C C Declarations_of_Local_Variables C DOUBLE PRECISION SECDAY PARAMETER ( SECDAY = 86400.0D0 ) C DOUBLE PRECISION JDPLUS INTEGER JDINT DOUBLE PRECISION DSEC INTEGER ISEC C C C Method C-& C*********************************************************************** C C1 Compute JDINT, the integer Julian date at noon of the current day C1 compute DSEC, the number of seconds elapsed since the start of the C1 current day. JDPLUS = JD + 0.5D0 JDINT = INT( JDPLUS ) DSEC = SECDAY * MOD( JDPLUS, 1.0D0 ) IF( DSEC .GE. SECDAY )THEN JDINT = JDINT + 1 DSEC = DSEC - SECDAY END IF ISEC = INT( DSEC ) C C1 Call J2DATE with JDINT to compute the year, month, and day of the C1 calendar date. CALL J2DATE( JDINT, YEAR, MONTH, DAY ) C C1 Compute HOUR. HOUR = ISEC/3600 ISEC = ISEC - 3600*HOUR C C1 Compute MINUTE. MINUTE = ISEC/60 ISEC = ISEC - 60*MINUTE C C1 Compute SECOND. SECOND = ISEC C C1 Compute FRAC. FRAC = MOD( DSEC, 1.0D0 ) C RETURN END C Procedure JD2SEC C DOUBLE PRECISION FUNCTION JD2SEC( JD ) C C C Purpose C C This subroutine (Julian Date 2 SEConds) takes an input Julian date an C returns the corresponding time in seconds past the reference date (JD C for this library as its functional value. C C C Input_Arguments C C JD is the Julian date to convert. C C C Declarations_of_External_Functions C DOUBLE PRECISION JDREF C C C Declarations_of_Input_and_Output_Arguments C DOUBLE PRECISION JD C C C Declarations_of_Local_Variables C DOUBLE PRECISION SECDAY PARAMETER ( SECDAY = 86400.0D0 ) C C C Method C-& C*********************************************************************** C C1 Subtract the Julian reference date from the input Julian date and C1 multiply by the number of seconds in a day (86400). JD2SEC = ( JD - JDREF() ) * SECDAY C RETURN END C Procedure JDREF C DOUBLE PRECISION FUNCTION JDREF( ) C C C Purpose C C This double precision function (Julian Date REFerence) will return th C the current Julian reference epoch for this library. Any time convers C routine in this library which outputs double precision seconds will o C seconds past this reference epoch. Note that this function must be ca C with an empty argument list: JDREF(). C C> Subroutine JDSET may be called to change this reference epoch from th C default value of 2451545.0 which is J2000.0 (January 1, 2000, 12 hour C C The alternate entry point, JDNEW, is reserved for use by other routin C this library and should never be called by the user. C C C Input_Arguments C C Output_Arguments C C Declarations_of_External_Functions C C Declarations_of_Input_and_Output_Arguments C C Declarations_of_Local_Variables C C Declare the alternate entry point: DOUBLE PRECISION JDNEW C DOUBLE PRECISION REFDAT C DOUBLE PRECISION JDSAVE C C SAVE C C Data_Statements C DATA JDSAVE /2451545.0D0/ C C C Method C*********************************************************************** C C1 Entry point JDREF. C JDREF = JDSAVE C RETURN C C*********************************************************************** C C1 Entry point JDNEW. C1 This entry point will change the Julian reference epoch to the val C the input argument REFDAT. C ENTRY JDNEW( REFDAT ) C JDSAVE = REFDAT JDNEW = JDSAVE C RETURN END C Procedure SEC2CH C CHARACTER*(*) FUNCTION SEC2CH( SEC ) C C C Purpose C C This subroutine (SEConds 2 CHaracter string) takes the input seconds C the Julian reference date (JDREF) for this library and returns as its C functional value the equivalent time in the character*25 format C 'DD-MMM-YYYY HH:MM:SS.FFFF'. C C If the user wishes to display only some initial segment of the calend C date, he may do so with his declaration of SEC2CH. For example, if he C wants to display 'DD-MMM-YYYY HH:MM:SS' then he may declare the funct C SEC2CH to be character*20. C C Note that this function will round rather than truncate to the neares C fractional second. The output accuracy is computed using the length o C declared in the calling routine. For example, if the calling routine C SEC2CH to be character*24, then this routine will round to the neares C millisecond. If the calling routine declares SEC2CH to be character*2 C this routine will round to the nearest second. C C C Input_Arguments C C SEC is the time in seconds past the reference date for this library. C C C Declarations_of_External_Functions C CHARACTER*31 CAL2CH C C C Declarations_of_Input_and_Output_Arguments C DOUBLE PRECISION SEC C C C Declarations_of_Local_Variables C INTEGER YEAR INTEGER MONTH INTEGER DAY INTEGER HOUR INTEGER MINUTE INTEGER SECOND DOUBLE PRECISION FRAC C INTEGER NDIGIT DOUBLE PRECISION EPS DOUBLE PRECISION SECTMP C C NDIGIT is the number of fractional digits to be output. C EPS is the fraction needed to be added to SEC to round to NDIGIT digi C SECTMP is the 'rounded' number of seconds. C C C Method C-& C*********************************************************************** C C1 Check to see if the date is out of bounds. IF( SEC .LT. -1.0D12 )THEN SEC2CH = 'DISTANT-PAST' RETURN ELSEIF( SEC .GT. 1.0D12 )THEN SEC2CH = 'DISTANT-FUTURE' RETURN END IF C C1 Round the number of seconds based on the output character string l NDIGIT = MIN( MAX( LEN(SEC2CH)-21, 0 ), 20 ) EPS = 0.5D0 / ( 10.D0**NDIGIT ) SECTMP = SEC + EPS C C1 Call SECCAL to convert seconds to calendar date. CALL SECCAL( SECTMP, YEAR, MONTH, DAY, HOUR, MINUTE, SECOND, FRAC) C C1 Call CAL2CH to convert calendar date to a character string. SEC2CH = CAL2CH( YEAR, MONTH, DAY, HOUR, MINUTE, SECOND, FRAC ) C RETURN END C Procedure SEC2JD C DOUBLE PRECISION FUNCTION SEC2JD( SEC ) C C C Purpose C C This double precision function subroutine (SEConds 2 Julian Date) tak C input time in seconds past the Julian reference date (JDREF) for this C and returns the corresponding Julian date as its functional value. C C C Input_Arguments C C SEC is the seconds past the reference date for this library. C C C Declarations_of_External_Functions C DOUBLE PRECISION JDREF C C C Declarations_of_Input_and_Output_Arguments C DOUBLE PRECISION SEC C C C Declarations_of_Local_Variables C DOUBLE PRECISION SECDAY PARAMETER ( SECDAY = 86400.0D0 ) C C C Method C-& C*********************************************************************** C C1 Divide the input seconds past the Julian reference date by the num C1 of seconds in a day and add the Julian reference date. SEC2JD = SEC/SECDAY + JDREF() C RETURN END C Procedure SECCAL C SUBROUTINE SECCAL( SEC, YEAR, MONTH, DAY, * HOUR, MINUTE, SECOND, FRAC ) C C C Purpose C C This subroutine (SEConds to CALendar date) takes an input seconds pas C the Julian reference date (JDREF) for this library and returns the va C components of the corresponding calendar date. The components of the C calendar date are all returned as numbers to allow for use in computa C For instance, the month is returned as the integer month number rathe C as a character string. C C C Input_Arguments C C SEC is the seconds past the reference date for this library. C C C Output_Arguments C C YEAR is the year. C MONTH is the month number. C DAY is the day. C HOUR is the hour. C MINUTE is the minute. C SECOND is the second. C FRAC is the fractional seconds. C C C Declarations_of_External_Functions C DOUBLE PRECISION SEC2JD C C C Declarations_of_Input_and_Output_Arguments C DOUBLE PRECISION SEC INTEGER YEAR INTEGER MONTH INTEGER DAY INTEGER HOUR INTEGER MINUTE INTEGER SECOND DOUBLE PRECISION FRAC C C C Declarations_of_Local_Variables C DOUBLE PRECISION JD DOUBLE PRECISION TEMP C C C Method C-& C*********************************************************************** C C1 Extract the fraction seconds (FRAC) from SEC. Note that care must C1 taken if SEC<0 since FRAC must be a non-negative number < 1. The o C1 fraction seconds of the calendar representation is simply the frac C1 part of the input seconds and can be computed immediately. The rem C1 integral seconds is converted to the rest of the calendar date. Th C1 done to avoid round off error that could be introduced by the C1 intermediate conversion to Julian date. FRAC = MOD( SEC, 1.0D0 ) IF ( FRAC .LT. 0.0D0 ) FRAC = 1.0D0 + FRAC C C1 Call SEC2JD to convert the integral seconds to the Julian date. JD = SEC2JD( SEC - FRAC + 0.5D0 ) C C1 Call JD2CAL to convert the Julian date to calandar date. CALL JD2CAL( JD, YEAR, MONTH, DAY, * HOUR, MINUTE, SECOND, TEMP ) C RETURN END