C+ C NAME: C DATE_DOY C PURPOSE: C Converts dates (iYr,Month,iDay) to daynumber iDoy and v.v. C CATEGORY: C Time keeping C CALLING SEQUENCE: subroutine DATE_DOY(ID,iYr,cMon,iMon,iDay,iDoy) C INPUTS: C ID integer ID=0 date (yr,month,day) ----> doy of year C ID=1 doy of year ----> date (yr,month,day) C iYr integer year; the year xxxBC should be entered as -xxx+1. C C ID = 0: C cMon character*3 month (either cMon or iMon must be specified) C iMon integer value 1-12 (see PROCEDURE) C iDay integer day of month C C ID = 1: C iDoy integer day of year C OUTPUTS: C ID = 0: C iDoy integer day of year C C ID = 1: C cMon character*3 month C iMon integer 1-12 C iDay integer day of month C CALLS: C uppercase C RESTRICTIONS: C >>> For ID=0 (date --> doy) the input for the month may be given in the form C of a char-string cMon or as an integer iMon. cMon takes precedence C over iMon: first cMon is checked for valid input; if cMon is not valid C iMon is used (if iMon is invalid too, the program is aborted). C >>> ADVICE: ALWAYS use cMon for input. C Upon output the values of cMon and iMon are always consistent. C The returned value for cMon is always in uppercase. C PROCEDURE: C Dates before 5 october 1582 are interpreted as Julian dates; after 15 C october as Gregorian dates. C >>> 5 october 1582 (Julian) = 15 october 1582 (Gregorian). C MODIFICATION HISTORY: C 1989-1990, Paul Hick (MPAE,UCSD/CASS; pphick@ucsd.edu) C- integer ID integer iYr character cMon*3 integer iMon integer iDay integer iDoy character*3 MONTHS(12) &/'JAN','FEB','MAR','APR','MAY','JUN','JUL','AUG','SEP','OCT','NOV','DEC'/ integer iDays(12) &/ 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 / if (ID .ne. 0 .and. ID .ne. 1) stop 'DATE_DOY: invalid ID' Leap = 2 if (iYr/4*4 .eq. iYr .and. (iYr .lt. 1582 .or. iYr/100*100 .ne. iYr & .or. iYr/400*400 .eq. iYr)) Leap = 1 !It's a leap year iDays(2) = 30-Leap !Days in february if (ID .eq. 0) then !Date ---> daynumber call uppercase(cMon) !Change to upper case I = 1 do while (I .le. 12 .and. cMon .ne. MONTHS(I)) I = I+1 end do if (I .le. 12) then iMon = I else !If cMon does not make sense, try iMon if (iMon .lt. 1 .or. iMon .gt. 12) stop 'DATE_DOY: invalid month' cMon = MONTHS(iMon) end if if(iDay .lt. 1 .or. iDay .gt. iDays(iMon))stop'DATE_DOY: invalid iDay' I = iMon-1 !Number of months already past iDoy = I*31-min(I/2,3)-max(0,(I-7)/2)+iDay !Day number if (I .ge. 2) iDoy = iDoy-Leap !Correction for February if (iYr .eq. 1582 .and. iDoy .gt. 278) then !278=15 oct (Greg.) if (iDoy .lt. 288) stop 'DATE_DOY: date in gap between calendars' iDoy = iDoy-10 !Substract 10 day gap end if else !Daynumber ---> date if (iDoy .lt. 1 .or. iDoy .gt. 367-Leap)stop 'DATE_DOY: invalid iDoy' if (iYr .eq. 1582) then if (iDoy .gt. 355) stop 'DATE_DOY: invalid iDoy for 1582' iDays(10) = 21 !Substract 10 day gap for october end if iDay = iDoy iMon = 1 !Suppose it's in january do while ((iDay-1)/iDays(iMon) .ge. 1) iDay = iDay-iDays(iMon) !Month iMon already past iMon = iMon+1 !Try next month end do cMon = MONTHS(iMon) if (iYr .eq. 1582 .and. iMon .eq. 10 .and. iDay.ge.5) iDay = iDay+10 end if !Add 10 day gap return end