module datetime_module

!***********************************************************************
!* module contains all routines that deal with date/time calculation   *
!***********************************************************************
!
integer                 :: icalendo,iyear0,julday0
integer,parameter       :: kmain=6              ! main control output

contains

  integer function julday(mm,id,iy)
!-----------------------------------------------------------------------
!
!     calculate julian day from given date
!
!     on input : mm, id, iy contain month, day and year
!     on output: julday contains the julian day
!
!     julday0 is the reference julian day for the calculation
!
!     J. Meeuws, "Astronomical formulea for calculators" 19xx
!
!-----------------------------------------------------------------------
    implicit none
!
    integer,intent(in) :: mm, id, iy
!
    integer :: jul, jy, jm, ja, iyyy
    integer,parameter :: igreg=15+31*(10+12*1582)
!
! handle dates before 0 AD
!
    iyyy=iy
    if (iy.eq.0) then
       stop ' ERROR invalid year 0 AD'
    end if
    if (iy.lt.0) then
       iyyy=iy+1
    end if
!
! calculate julian day from date in gregorian calendar
!
    if (mm.gt.2) then
       jy=iyyy
       jm=mm+1
    else
       jy=iyyy-1
       jm=mm+13
    endif
    jul=int(365.25*jy)+int(30.6001*jm)+id+1720995
!
! handle julian calender
!
    if (id+31*(mm+12*iyyy).ge.igreg) then
       ja=int(0.01*jy)
       jul=jul+2-ja+int(0.25*ja)
    endif
    julday=jul
!
  end function julday

  subroutine tau2date(itaux,idatex)
!-----------------------------------------------------------------------
!
!     calculate date from given time in seconds
!
!     on input : itaux contains date/time in seconds
!     on output: idatex contains date in year,month,day,hour,min,sec
!
!     icalendo determines the type calendar used for the conversion
!     iyear0 is the reference year for the calculation
!     julday0 is the reference julian day for the calculation
!
!-----------------------------------------------------------------------
!    use global_data, only : kmain,icalendo,iyear0,julday0
    implicit none
    integer,intent(in) :: itaux
    integer,dimension(6),intent(out) :: idatex
!
    integer :: julian,idayy,iyeary,idummy
!
! compute time (hour,min,sec) and number of days
!
    idatex(6)=mod(itaux,60)
    idatex(5)=mod(itaux/60,60)
    idatex(4)=mod(itaux/3600,24)
    idayy=itaux/86400
!
! permanent 360 year calendar with 30 days in each month
!
    if (icalendo.eq.1) then
       idatex(3)=mod(idayy,30)+1
       idatex(2)=mod(idayy/30,12)+1
       idatex(1)=iyear0+idayy/360
!
! real calendar
!
    else if (icalendo.eq.2) then
       julian=julday0+idayy
       call caldat(julian,idatex(2),idatex(3),idatex(1))
!
! permanent 365 day year calendar
!
    elseif (icalendo.eq.3) then
       iyeary=idayy/365
       idatex(1)=iyear0+iyeary
! use Jan 1, 1981 as a year containing 365 days and add doy
       julian=julday(1,1,1981)+idayy-iyeary*365
       call caldat(julian,idatex(2),idatex(3),idummy)
!
! permanent leap year calendar
!
    elseif (icalendo.eq.4) then
       iyeary=idayy/366
       idatex(1)=iyear0+iyeary
! use Jan 1, 1980 as a year containing 366 days and add doy
       julian=julday(1,1,1980)+idayy-iyeary*366
       call caldat(julian,idatex(2),idatex(3),idummy)
!
! illegal option icalendo
!
    else
       write(kmain,*) ' Illegal calendar type'
       write(kmain,*) ' icalendo=',icalendo
       stop ' ERROR while computing date'
    endif
!
  end subroutine tau2date



  subroutine date2tau(idatex,itaux)
!-----------------------------------------------------------------------
!
!     calculate time in seconds from given date
!
!     on input : idatex contains date in year,month,day,hour,min,sec
!     on output: itaux contains date/time in seconds
!
!     icalendo determines the type calendar used for the conversion
!     iyear0 is the reference year for the calculation
!     julday0 is the reference julian day for the calculation
!
!-----------------------------------------------------------------------
!    use global_data, only : icalendo,iyear0,julday0,kmain
    implicit none
    integer,dimension(6),intent(in) :: idatex
    integer,intent(out) :: itaux
!
    integer :: idaysec
!
! compute the seconds the day is old
! 
    idaysec=idatex(6)+idatex(5)*60+idatex(4)*3600
!
! permanent 360 year calendar with 30 days in each month
!
    if (icalendo.eq.1) then
       itaux=idaysec+(idatex(3)-1)*86400+(idatex(2)-1)*2592000 &
            +(idatex(1)-iyear0)*31104000
!
! real calendar
!
    elseif (icalendo.eq.2) then
       itaux=86400*(julday(idatex(2),idatex(3),idatex(1))-julday0)+idaysec
!
! permanent 365 day year calendar
!
    elseif (icalendo.eq.3) then
       itaux=86400*(julday(idatex(2),idatex(3),1981)-julday(1,1,1981)) &
            +(idatex(1)-iyear0)*365*86400+idaysec
!
! permanent leap year calendar
!
    elseif (icalendo.eq.4) then
       itaux=86400*(julday(idatex(2),idatex(3),1980)-julday(1,1,1980)) &
            +(idatex(1)-iyear0)*366*86400+idaysec
!
! illegal option icalendo
!
    else
       write(kmain,*) ' Illegal calendar type'
       write(kmain,*) ' icalendo=',icalendo
       stop ' ERROR while computing time'
    endif
!
  end subroutine date2tau

 
  subroutine caldat(julian,mm,id,iyyy)
!-----------------------------------------------------------------------
!
!     calculate date from given julian day
!
!     on input : julday contains the julian day
!     on output: mm, id, iyyy contain month, day and year
!
!     julday0 is the reference julian day for the calculation
!
!     J. Meeuws, "Astronomical formulea for calculators" 19xx
!
!-----------------------------------------------------------------------
    implicit none
!
    integer,intent(in)  :: julian
    integer,intent(out) :: mm, id, iyyy
!
    integer :: jalpha, ja, jb, jc, jd, je
    integer,parameter :: igreg=2299161
!
! handle gregorian and julian date
!
    if (julian.ge.igreg)then
       jalpha=int(((julian-1867216)-0.25)/36524.25)
       ja=julian+1+jalpha-int(0.25*jalpha)
    else
       ja=julian
    endif
    jb=ja+1524
    jc=int(6680.+((jb-2439870)-122.1)/365.25)
    jd=365*jc+int(0.25*jc)
    je=int((jb-jd)/30.6001)
    id=jb-jd-int(30.6001*je)
    mm=je-1
    if (mm.gt.12) mm=mm-12
    iyyy=jc-4715
    if (mm.gt.2) iyyy=iyyy-1
!
! handle dates before 0 AD
!
    if (iyyy.le.0) iyyy=iyyy-1
!
  end subroutine caldat

  subroutine getTMTimeOffset ( itau_offset_TM_OMI )
    ! 
    ! Determines the number of seconds offset between
    ! the OMI time and TM time
    !
    ! out
      use  constants_module, only : int32
      implicit none
    
    integer(int32),intent(out)  :: itau_offset_TM_OMI
    !
    integer,dimension(6) :: daterefOMI

    ! OMI reference date
    daterefOMI = (/ 2004, 1, 1, 0, 0, 0 /)
    call date2tau( daterefOMI, itau_offset_TM_OMI )

  end subroutine getTMTimeOffset


end module datetime_module
