Subversion Repositories lagranto.icon

Rev

Go to most recent revision | Blame | Last modification | View Log | Download | RSS feed

c     **************************************************************************
c     * This library provides subroutines related to time and file name        *
c     * handling                                                               *
c     *                                                                        *
c     **************************************************************************

c     ---------------------------------------------------------------------------
c     Concatenate a date string
c     ---------------------------------------------------------------------------

      subroutine datestring(datestr,yyyy,mm,dd,hh)

c     Declaration of subroutine parameters
      integer yyyy,mm,dd,hh
      character*20 datestr

c     Auxiliary parameters
      integer f1,f2,i0
      integer yy,ce

      i0=ichar('0')
      datestr=''

      yy=mod(yyyy,100)
      ce=int(yyyy/100)

      if ((ce.ne.19).and.(ce.ne.20)) then
         print*,'Invalid year... Stop'
         stop
      endif

      if (yy.ge.0) then
         f1=yy/10
         f2=mod(yy,10)
         if (ce.eq.19) then
            datestr=trim(datestr)//'19'//char(f1+i0)//char(f2+i0)
         else if (ce.eq.20) then
            datestr=trim(datestr)//'20'//char(f1+i0)//char(f2+i0)
         endif
      endif
      if (mm.gt.0) then
         f1=mm/10
         f2=mod(mm,10)
         datestr=trim(datestr)//char(f1+i0)//char(f2+i0)
      endif

      if (dd.gt.0) then
         f1=dd/10
         f2=mod(dd,10)
         datestr=trim(datestr)//char(f1+i0)//char(f2+i0)
      endif

      if (hh.ge.0) then
         f1=hh/10
         f2=mod(hh,10)
         datestr=trim(datestr)//'_'//char(f1+i0)//char(f2+i0)
      endif

      return
      end


c     ---------------------------------------------------------------------------
c     Calculates the new date when diff (in hours) is added to date1.
c     ---------------------------------------------------------------------------

      subroutine newdate(date1,diff,date2)
C
C     date1     int     input   array contains a date in the form
C                               year,month,day,hour,step
C     diff      real    input   timestep in hours to go from date1
C     date2     int     output  array contains new date in the same form

      integer   date1(5),date2(5)
      integer   idays(12)       ! array containing the days of the monthes
      real      diff
      logical   yearchange

      data idays/31,28,31,30,31,30,31,31,30,31,30,31/

      yearchange=.false.

      if ((mod(date1(1),4).eq.0).and.(date1(2).le.2)) idays(2)=29

      date2(1)=date1(1)
      date2(2)=date1(2)
      date2(3)=date1(3)
      date2(4)=date1(4)
      date2(5)=0
      date2(4)=date1(4)+int(diff)+date1(5)

      if (date2(4).ge.24) then
        date2(3)=date2(3)+int(date2(4)/24)
        date2(4)=date2(4)-int(date2(4)/24)*24
      endif
      if (date2(4).lt.0) then
        if (mod(date2(4),24).eq.0) then
          date2(3)=date2(3)-int(abs(date2(4))/24)
          date2(4)=date2(4)+int(abs(date2(4))/24)*24
        else
          date2(3)=date2(3)-(1+int(abs(date2(4))/24))
          date2(4)=date2(4)+(1+int(abs(date2(4))/24))*24
        endif
      endif

  100 if (date2(3).gt.idays(date2(2))) then
        if ((date2(2).eq.2).and.(mod(date2(1),4).eq.0)) idays(2)=29
        date2(3)=date2(3)-idays(date2(2))
        if (idays(2).eq.29) idays(2)=28
        date2(2)=date2(2)+1
        if (date2(2).gt.12) then
*         date2(1)=date2(1)+int(date2(2)/12)
*         date2(2)=date2(2)-int(date2(2)/12)*12
          date2(1)=date2(1)+1
          date2(2)=date2(2)-12
        endif
        if (date2(2).lt.1) then
          date2(1)=date2(1)-(1+int(abs(date2(2)/12)))
          date2(2)=date2(2)+(1+int(abs(date2(2)/12)))*12
        endif
        goto 100
      endif     
  200 if (date2(3).lt.1) then
        date2(2)=date2(2)-1
        if (date2(2).gt.12) then
          date2(1)=date2(1)+int(date2(2)/12)
          date2(2)=date2(2)-int(date2(2)/12)*12
        endif
        if (date2(2).lt.1) then
          date2(1)=date2(1)-(1+int(abs(date2(2)/12)))
          date2(2)=date2(2)+(1+int(abs(date2(2)/12)))*12
        endif
        if ((date2(2).eq.2).and.(mod(date2(1),4).eq.0)) idays(2)=29
        date2(3)=date2(3)+idays(date2(2))
        if (idays(2).eq.29) idays(2)=28
        goto 200
      endif

      if (date2(2).gt.12) then
        date2(1)=date2(1)+int(date2(2)/12)
        date2(2)=date2(2)-int(date2(2)/12)*12
      endif
      if (date2(2).lt.1) then
        date2(1)=date2(1)-(1+int(abs(date2(2)/12)))
        date2(2)=date2(2)+(1+int(abs(date2(2)/12)))*12
      endif

      if (date2(1).lt.1000) then
      if (date2(1).ge.100) date2(1)=date2(1)-100
      endif

      return
      end

c     ---------------------------------------------------------------------------
c     Convert <hh.mm> -> <frac> and <frac> -> <hhmm>
c     ---------------------------------------------------------------------------

      subroutine hhmm2frac (hhmm,frac)

      real hhmm
      real frac
      
      frac=real(int(hhmm))+
     >     100.*(hhmm-real(int(hhmm)))/60.

      end


      subroutine frac2hhmm (frac,hhmm)

      real hhmm
      real frac

      real hh,mm
      
      hh =  real(int(frac))
      mm =  60. * (frac-real(int(frac)))

      hhmm = hh + 0.01 * mm

      end

c     ---------------------------------------------------------------------------
c     Time difference between two dates
c     ---------------------------------------------------------------------------

      subroutine timediff(date1,date2,diff)
 
C     New version with hour and minutes! (for hour and step [in hours]
C     use the routine oldtimediff!)
C
C     Calculates the time difference in hours (and minutes) for the two
C     dates specified by the two arrays date1 and date2.
C     They are expected to contain the following date information:
C     year      month   day     hour    minute.
C
C     date1     array specifying the first date
C     date2     array specifying the second date
C     diff      time differenc between date1 and date2 in hours
C
 
      integer   date1(5),date2(5)
      integer   idays(12)       ! array containing the days of the monthes
      real      diff
      integer   ixday,imdiff,ihdiff,iddiff,j
      integer   yy,yy1,yy2
 
      idays(1)=31
      idays(2)=28
      idays(3)=31
      idays(4)=30
      idays(5)=31
      idays(6)=30
      idays(7)=31
      idays(8)=31
      idays(9)=30
      idays(10)=31
      idays(11)=30
      idays(12)=31
 
C     Check format of year (YYYY or YY - in case of YY assume 19YY)

      if (date1(1).lt.100) date1(1)=1900+date1(1)
      if (date2(1).lt.100) date2(1)=1900+date2(1)

C     Determine if the period between date1 and date2 contains a Feb.29
 
      ixday=0   ! extra day flag
 
      yy1=min(date1(1),date2(1))
      yy2=max(date1(1),date2(1))
      if (yy1.eq.yy2) then
        if (mod(yy1,4).eq.0) then
          idays(2)=29
        endif
      else
        if (mod(yy1,4).eq.0) then
          if (((yy1.eq.date1(1)).and.(date1(2).le.2)).or.
     >        ((yy1.eq.date2(1)).and.(date2(2).le.2))) then
            ixday=ixday+1
          endif
        endif
        if (mod(yy2,4).eq.0) then
          if (((yy2.eq.date1(1)).and.(date1(2).gt.2)).or.
     >        ((yy2.eq.date2(1)).and.(date2(2).gt.2))) then
            ixday=ixday+1
          endif
        endif
        if (yy2-yy1.gt.1) then
          do yy=yy1+1,yy2-1
            if (mod(yy,4).eq.0) then
              ixday=ixday+1
            endif
          enddo
        endif
      endif
 
      ihdiff=0  ! diff. in hours between date1/date2
      iddiff=0  ! diff. in days  between date1/date2
 
      if (date1(1).gt.date2(1)) then            ! compare years
        do j=date2(1),date1(1)-1
          iddiff=iddiff+365
        enddo
        iddiff=iddiff+ixday
      else if (date1(1).lt.date2(1)) then
        do j=date1(1),date2(1)-1
          iddiff=iddiff-365
        enddo
        iddiff=iddiff-ixday
      endif
 
      if (date1(2).gt.date2(2)) then            ! compare monthes
        do j=date2(2),date1(2)-1
          iddiff=iddiff+idays(j)
        enddo
      else if (date1(2).lt.date2(2)) then
        do j=date1(2),date2(2)-1
          iddiff=iddiff-idays(j)
        enddo
      endif
 
      iddiff=iddiff+date1(3)-date2(3)
      ihdiff=iddiff*24+date1(4)-date2(4)
      imdiff=ihdiff*60+date1(5)-date2(5)
 
      ihdiff=imdiff/60
      imdiff=mod(imdiff,60)
 
      diff=real(ihdiff)+real(imdiff)/100.
 
      return
      end


c     ---------------------------------------------------------------------------
c     Time check based on date strings from input files
c     ---------------------------------------------------------------------------

      subroutine do_timecheck (datestr,numdat,timeinc,fbflag,refdate)

c     Perform a simple timecheck based on the names of the input files;
c     the following tests have to be passed:
c        (1) the order of <datestr> must match with <fbflag>
c        (2) the step between <datestr> must match with <timeinc>
c        (3) <refdate> must match with <datestr(1)>

          implicit none

c         Declaration of subroutine parameters
      integer      numdat
      character*13 datestr(numdat)
      real         timeinc
      integer      fbflag
      integer      refdate(6)

c         Numerical epsilon
          real        eps
          parameter   (eps=0.0001)


c     Auxilary variables
      integer      yyyy(numdat)
      integer      mm  (numdat)
      integer      dd  (numdat)
      integer      hh  (numdat)
      integer      mi  (numdat)
      integer      i
      character*13 str
      integer      date1(5),date2(5)
      real         diff,ok
      integer      hires

c     Get date mode (including or without minutes)
      if ( len_trim(datestr(1)).eq.11 ) then
        hires = 0
      elseif ( len_trim(datestr(1)).eq.13 )   then
        hires = 1
      else
        hires = -1
      endif
      do i=2,numdat
         if ((len_trim(datestr(i)).eq.11).and.(hires.eq.1)) hires = -1
         if ((len_trim(datestr(i)).eq.13).and.(hires.eq.0)) hires = -1
      enddo
      if ( hires.eq.-1 ) then
         print*,' ERROR: string format is wrong:'
         print*,'     either {YYYYMMDD_HH} or {YYYYMMDD_HHMM}'
         stop
      endif

c         Convert date strings into integers
      do i=1,numdat
        if (hires.eq.0) then
           read(datestr(i),'(i4,i2,i2,1x,i2)')
     >                  yyyy(i),mm(i),dd(i),hh(i)
           mi(i) = 0
        else
           read(datestr(i),'(i4,i2,i2,1x,i2,i2)')
     >              yyyy(i),mm(i),dd(i),hh(i),mi(i)
        endif

      enddo


c         Check time increment and consistence with time increment
      do i=1,numdat-1

          date1(1) = yyyy(i)
          date1(2) = mm  (i)
          date1(3) = dd  (i)
          date1(4) = hh  (i)
          date1(5) = mi  (i)
          date2(1) = yyyy(i+1)
          date2(2) = mm  (i+1)
          date2(3) = dd  (i+1)
          date2(4) = hh  (i+1)
          date2(5) = mi  (i+1)

          call timediff (date2,date1,diff)

          if (abs(diff).lt.(1.-eps)) diff = 100. * diff/60

          if (fbflag.eq.1) then
                ok = diff - timeinc
          elseif (fbflag.eq.-1) then
                ok = -diff - timeinc
          endif

              if ( abs(ok).gt.eps ) then
                print*,' ERROR: timecheck failed !!!! Stop'
                print*,'   date 1  : ',date1
                print*,'   date 2  : ',date2
                print*,'   diff,timeinc : ',diff,timeinc
                stop
              endif

      enddo

c         Check the reference date
      if ( ( refdate(1).ne.yyyy(1) ).or.
     >     ( refdate(2).ne.mm  (1) ).or.
     >     ( refdate(3).ne.dd  (1) ).or.
     >     ( refdate(4).ne.hh  (1) ) )
     >then
         print*,' ERROR: timecheck failed (refdate) !!!! Stop'
         print*,'ref : ',refdate
         print*,'P   : ',yyyy(1),mm(1),dd(1),hh(1),mi(1)
         stop
      endif

      end