!=============================================================================== ! CVS $Id: shr_cal_mod.F90,v 1.2.4.1 2004/01/02 18:50:53 mvr Exp $ ! CVS $Source: /fs/cgd/csm/models/CVS.REPOS/shared/csm_share/shr/shr_cal_mod.F90,v $ ! CVS $Name: cam3_0_brnchT_release01 $ !=============================================================================== !BOP =========================================================================== ! ! !MODULE: shr_cal_mod -- calendar module, relates elapsed days to calendar date. ! ! !DESCRIPTION: ! These calendar routines do conversions between... ! \begin{itemize} ! \item the integer number of elapsed days ! \item the integers year, month, day (three inter-related integers) ! \item the integer coded calendar date (yyyymmdd) ! \end{itemize} ! Possible uses include: a calling routine can increment the elapsed days ! integer and use this module to determine what the corresponding calendar ! date is; this module can be used to determine how many days apart two ! arbitrary calendar dates are. ! ! !REVISION HISTORY: ! 2001-dec-28 - B. Kauffman - created initial version, taken from cpl5 ! ! !REMARKS: ! Following are some internal assumptions. These assumptions are somewhat ! arbitrary -- they were chosen because they result in the simplest code given ! the requirements of this module. These assumptions can be relaxed as ! necessary: ! o the valid range of years is [0,9999] ! o elapsed days = 0 <=> January 1st, year 0000 ! o all years have 365 days (no leap years) ! This module is hard-coded to implement a 365-day calendar, ie. there ! are no leap years. This module can be modified to implement a calendar ! with leap years if this becomes desireable. This would make the internal ! logic of this module more complex, but would not require any change to the ! module API or the calling code because the module API hides these details ! from all external routines. ! ! !INTERFACE: ------------------------------------------------------------------module shr_cal_mod 2,1 ! !USES: use shr_kind_mod
! kinds implicit none private ! except ! !PUBLIC TYPES: ! none ! !PUBLIC MEMBER FUNCTIONS: public :: shr_cal_eday2date ! converts elapsed days to coded-date public :: shr_cal_eday2ymd ! converts elapsed days to yr,month,day public :: shr_cal_date2ymd ! converts coded-date to yr,month,day public :: shr_cal_date2eday ! converts coded-date to elapsed days public :: shr_cal_ymd2date ! converts yr,month,day to coded-date public :: shr_cal_ymd2eday ! converts yr,month,day to elapsed days public :: shr_cal_validDate ! logical function: is coded-date valid? public :: shr_cal_validYMD ! logical function: are yr,month,day valid? public :: shr_cal_numDaysinMonth ! number of days in a month public :: shr_cal_elapsDaysStrtMonth ! elapsed days on start of month ! !PUBLIC DATA MEMBERS: ! none !EOP !----- local ----- integer(SHR_KIND_IN),parameter :: dsm(12) = & ! elapsed Days on Start of Month & (/ 0,31,59, 90,120,151, 181,212,243, 273,304,334/) integer(SHR_KIND_IN),parameter :: dpm(12) = & ! Days Per Month & (/31,28,31, 30, 31, 30, 31, 31, 30, 31, 30, 31/) !~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ contains !~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ !=============================================================================== !BOP =========================================================================== ! ! !IROUTINE: shr_cal_eday2date - converts elapsed days to coded-date ! ! !DESCRIPTION: ! Converts elapsed days to coded-date. ! ! !REVISION HISTORY: ! 2001-dec-28 - B. Kauffman - initial version, taken from cpl5 ! ! !INTERFACE: -----------------------------------------------------------------
subroutine shr_cal_eday2date(eday,date) 1 implicit none ! !INPUT/OUTPUT PARAMETERS: integer(SHR_KIND_IN),intent(in) :: eday ! number of elapsed days integer(SHR_KIND_IN),intent(out) :: date ! coded (yyyymmdd) calendar date !EOP !--- local --- integer(SHR_KIND_IN) :: k,year,month,day !------------------------------------------------------------------------------- ! ASSUMPTIONS: ! this calendar has a year zero (but no day or month zero) !------------------------------------------------------------------------------- year = eday/365 ! calendar year (note: Fortran truncation) day = mod(eday,365) ! elapsed days within current year do k=1,12 IF (day >= dsm(k)) month=k ! calendar month end do day = day-dsm(month) + 1 ! calendar day date = year*10000 + month*100 + day ! coded calendar date end subroutine shr_cal_eday2date !=============================================================================== !BOP =========================================================================== ! ! !IROUTINE: shr_cal_eday2ymd - converts elapsed days to year/month/day. ! ! !DESCRIPTION: ! Converts elapsed days to year/month/day. ! ! !REVISION HISTORY: ! 2001-dec-28 - B. Kauffman - initial version, taken from cpl5 ! ! !INTERFACE: -----------------------------------------------------------------
subroutine shr_cal_eday2ymd (eday,year,month,day) 2 implicit none ! !INPUT/OUTPUT PARAMETERS: integer(SHR_KIND_IN),intent(in) :: eday ! elapsed days integer(SHR_KIND_IN),intent(out) :: year,month,day ! calendar year,month,day !EOP !--- local --- integer(SHR_KIND_IN) :: k !------------------------------------------------------------------------------- ! ASSUMPTIONS: ! this calendar has a year zero (but no day or month zero) !------------------------------------------------------------------------------- year = eday/365 ! calendar year (note: Fortran truncation) day = mod(eday,365) ! elapsed days within current year do k=1,12 IF (day .ge. dsm(k)) month=k ! calendar month end do day = day-dsm(month) + 1 ! calendar day end subroutine shr_cal_eday2ymd !=============================================================================== !BOP =========================================================================== ! ! !IROUTINE: shr_cal_date2ymd - converts coded-date to year/month/day. ! ! !DESCRIPTION: ! Converts coded-date (yyyymmdd) to year/month/day. ! ! !REVISION HISTORY: ! 2001-dec-28 - B. Kauffman - initial version, taken from cpl5 ! ! !INTERFACE: -----------------------------------------------------------------
subroutine shr_cal_date2ymd (date,year,month,day) 1 implicit none ! !INPUT/OUTPUT PARAMETERS: integer(SHR_KIND_IN),intent(in) :: date ! coded-date (yyyymmdd) integer(SHR_KIND_IN),intent(out) :: year,month,day ! calendar year,month,day !EOP !------------------------------------------------------------------------------- ! !------------------------------------------------------------------------------- if (.not. shr_cal_validDate(date)) then write(6,*) "(cal_date2ymd) ERROR: invalid date = ",date endif year =int( date /10000) month=int( mod(date,10000)/ 100) day = mod(date, 100) end subroutine shr_cal_date2ymd !=============================================================================== !BOP =========================================================================== ! ! !IROUTINE: shr_cal_date2eday - converts coded-date to elapsed days ! ! !DESCRIPTION: ! Converts coded-date to elapsed days ! ! !REVISION HISTORY: ! 2001-dec-28 - B. Kauffman - initial version, taken from cpl5 ! ! !INTERFACE: -----------------------------------------------------------------
subroutine shr_cal_date2eday(date,eday) implicit none ! !INPUT/OUTPUT PARAMETERS: integer(SHR_KIND_IN),intent(in ) :: date ! coded (yyyymmdd) calendar date integer(SHR_KIND_IN),intent(out) :: eday ! number of elapsed days !EOP !--- local --- integer(SHR_KIND_IN) :: year,month,day !------------------------------------------------------------------------------- ! NOTE: ! elapsed days since yy-mm-dd = 00-01-01, with 0 elapsed seconds !------------------------------------------------------------------------------- if (.not. shr_cal_validDate(date)) stop year =int( date /10000) month=int( mod(date,10000)/ 100) day = mod(date, 100) eday = year*365 + dsm(month) + (day-1) end subroutine shr_cal_date2eday !=============================================================================== !BOP =========================================================================== ! ! !IROUTINE: shr_cal_ymd2date - converts year, month, day to coded-date ! ! !DESCRIPTION: ! Converts year, month, day to coded-date ! ! !REVISION HISTORY: ! 2001-dec-28 - B. Kauffman - initial version, taken from cpl5 ! ! !INTERFACE: -----------------------------------------------------------------
subroutine shr_cal_ymd2date(year,month,day,date) 1 implicit none ! !INPUT/OUTPUT PARAMETERS: integer(SHR_KIND_IN),intent(in ) :: year,month,day ! calendar year,month,day integer(SHR_KIND_IN),intent(out) :: date ! coded (yyyymmdd) calendar date !EOP !--- local --- !------------------------------------------------------------------------------- ! NOTE: ! this calendar has a year zero (but no day or month zero) !------------------------------------------------------------------------------- if (.not. shr_cal_validYMD(year,month,day)) stop date = year*10000 + month*100 + day ! coded calendar date end subroutine shr_cal_ymd2date !=============================================================================== !BOP =========================================================================== ! ! !IROUTINE: shr_cal_ymd2eday - converts year, month, day to elapsed days ! ! !DESCRIPTION: ! Converts year, month, day to elapsed days ! ! !REVISION HISTORY: ! 2001-dec-28 - B. Kauffman - initial version, taken from cpl5 ! ! !INTERFACE: -----------------------------------------------------------------
subroutine shr_cal_ymd2eday(year,month,day,eday) 1 implicit none ! !INPUT/OUTPUT PARAMETERS: integer(SHR_KIND_IN),intent(in ) :: year,month,day ! calendar year,month,day integer(SHR_KIND_IN),intent(out) :: eday ! number of elapsed days !EOP !--- local --- !------------------------------------------------------------------------------- ! NOTE: ! elapsed days since yy-mm-dd = 00-01-01, with 0 elapsed seconds !------------------------------------------------------------------------------- if (.not. shr_cal_validYMD(year,month,day)) stop eday = year*365 + dsm(month) + (day-1) end subroutine shr_cal_ymd2eday !=============================================================================== !BOP =========================================================================== ! ! !IROUTINE: shr_cal_validDate - determines if coded-date is a valid date ! ! !DESCRIPTION: ! Determines if the given coded-date is a valid date. ! ! !REVISION HISTORY: ! 2001-dec-28 - B. Kauffman - initial version, taken from cpl5 ! ! !INTERFACE: -----------------------------------------------------------------
logical function shr_cal_validDate(date) implicit none ! !INPUT/OUTPUT PARAMETERS: integer(SHR_KIND_IN),intent(in ) :: date ! coded (yyyymmdd) calendar date !EOP !--- local --- integer(SHR_KIND_IN) :: year,month,day !------------------------------------------------------------------------------- ! !------------------------------------------------------------------------------- year =int( date /10000) month=int( mod(date,10000)/ 100) day = mod(date, 100) shr_cal_validDate = .true. if (year < 0) shr_cal_validDate = .false. if (year > 9999) shr_cal_validDate = .false. if (month < 1) shr_cal_validDate = .false. if (month > 12) shr_cal_validDate = .false. if (day < 1) shr_cal_validDate = .false. if (shr_cal_validDate) then if (day > dpm(month)) shr_cal_validDate = .false. endif end function shr_cal_validDate !=============================================================================== !BOP =========================================================================== ! ! !IROUTINE: shr_cal_validYMD - determines if year, month, day is a valid date ! ! !DESCRIPTION: ! Determines if the given year, month, and day indicate a valid date. ! ! !REVISION HISTORY: ! 2001-dec-28 - B. Kauffman - initial version, taken from cpl5 ! ! !INTERFACE: -----------------------------------------------------------------
logical function shr_cal_validYMD(year,month,day) implicit none ! !INPUT/OUTPUT PARAMETERS: integer(SHR_KIND_IN),intent(in ) :: year,month,day ! calendar year,month,day !EOP !--- local --- !------------------------------------------------------------------------------- ! !------------------------------------------------------------------------------- shr_cal_validYMD = .true. if (year < 0) shr_cal_validYMD = .false. if (year > 9999) shr_cal_validYMD = .false. if (month < 1) shr_cal_validYMD = .false. if (month > 12) shr_cal_validYMD = .false. if (day < 1) shr_cal_validYMD = .false. if (shr_cal_validYMD) then if (day > dpm(month)) shr_cal_validYMD = .false. endif end function shr_cal_validYMD !=============================================================================== !BOP =========================================================================== ! ! !IROUTINE: shr_cal_numDaysInMonth - return the number of days in a month. ! ! !DESCRIPTION: ! Deturn the number of days in a month. ! ! !REVISION HISTORY: ! 2002-sep-18 - B. Kauffman - initial version. ! ! !INTERFACE: -----------------------------------------------------------------
integer function shr_cal_numDaysInMonth(year,month) implicit none ! !INPUT/OUTPUT PARAMETERS: integer(SHR_KIND_IN),intent(in ) :: year,month ! calendar year,month !EOP !------------------------------------------------------------------------------- ! !------------------------------------------------------------------------------- shr_cal_numDaysInMonth = dpm(month) end function shr_cal_numDaysInMonth !=============================================================================== !BOP =========================================================================== ! ! !IROUTINE: shr_cal_elapsDaysStrtMonth - return the number of elapsed days ! at start of month ! ! !DESCRIPTION: ! Return the number of elapsed days at start of a month. ! ! !REVISION HISTORY: ! 2002-Oct-29 - R. Jacob - initial version ! ! !INTERFACE: -----------------------------------------------------------------
integer function shr_cal_elapsDaysStrtMonth(year,month) 1 implicit none ! !INPUT/OUTPUT PARAMETERS: integer(SHR_KIND_IN),intent(in ) :: year,month ! calendar year,month !EOP !------------------------------------------------------------------------------- ! !------------------------------------------------------------------------------- shr_cal_elapsDaysStrtMonth = dsm(month) end function shr_cal_elapsDaysStrtMonth !=============================================================================== !=============================================================================== end module shr_cal_mod