!== dc_date_types#DC_DATETIME, dc_date_types#DC_DIFFTIME åž‹å¤‰æ•°ã‹ã‚‰æœˆæ—¥ç§’ã¸ã®å¤‰æ›
!
! Authors::   Yasuhiro MORIKAWA, Eizi TOYODA
! Version::   $Id: dcdatetimeeval.f90,v 1.2 2009-05-25 10:01:34 morikawa Exp $
! Tag Name::  $Name:  $
! Copyright:: Copyright (C) GFD Dennou Club, 2000-2006. All rights reserved.
! License::   See COPYRIGHT[link:../../COPYRIGHT]
!
! ã“ã®ãƒ•ã‚¡ã‚¤ãƒ«ã§æä¾›ã•ã‚Œã‚‹æ‰‹ç¶šãç¾¤ã¯ dc_date ãƒ¢ã‚¸ãƒ¥ãƒ¼ãƒ«ã«ã¦æä¾›ã•ã‚Œã¾ã™ã€‚
!

subroutine DCDateTimeEval1(time, year, mon, day, hour, min, &
  & sec, caltype, zone, sclyear, sclmon, sclday, sclsec)
  !
  ! dc_date_types#DC_DATETIME åž‹å¤‰æ•° *time* ã‚’
  ! å¹´ *year*, æœˆ *mon*, æ—¥ *day*, æ™‚é–“ *hour*, åˆ† *min*, ç§’ *sec*,
  ! æš¦æ³• *caltype*, ã‚¿ã‚¤ãƒ ã‚¾ãƒ¼ãƒ³ *zone* ã«å¤‰æ›ã—ã¦è¿”ã—ã¾ã™.
  !
  use dc_types, only: DP
  use dc_date_types, only: DC_DATETIME, &
    & CYCLIC_MDAYS, CAL_NOLEAP, CAL_JULIAN, CAL_CYCLIC, &
    & YEAR_MONTHS, YEAR_DAYS, FOUR_YEARS, FOUR_CENTURY, &
    & HOUR_SECONDS, MIN_SECONDS
  use dc_scaledsec, only:  DC_SCALED_SEC, &
    & assignment(=), DCScaledSecPutLine, &
    & operator(==), operator(>), operator(<), operator(>=), operator(<=), &
    & operator(+), operator(-), operator(*), operator(/), mod, modulo, &
    & abs, int, floor, ceiling
  use dc_trace, only: BeginSub, EndSub
  implicit none
  type(DC_DATETIME), intent(in):: time
  integer, intent(out), optional:: year ! å¹´
  integer, intent(out), optional:: mon  ! æœˆ
  integer, intent(out), optional:: day  ! æ—¥
  integer, intent(out), optional:: hour ! æ™‚
  integer, intent(out), optional:: min  ! åˆ†
  real(DP),intent(out), optional:: sec  ! ç§’
  integer, intent(out), optional:: caltype ! æš¦æ³•
  character(*), intent(out), optional:: zone ! ã‚¿ã‚¤ãƒ ã‚¾ãƒ¼ãƒ³ (UTC ã‹ã‚‰ã®æ™‚å·®)
  type(DC_SCALED_SEC), intent(out), optional:: sclyear ! å¹´ (DC_SCALED_SEC åž‹)
  type(DC_SCALED_SEC), intent(out), optional:: sclmon  ! æœˆ (DC_SCALED_SEC åž‹)
  type(DC_SCALED_SEC), intent(out), optional:: sclday  ! æ—¥ (DC_SCALED_SEC åž‹)
  type(DC_SCALED_SEC), intent(out), optional:: sclsec  ! ç§’ (DC_SCALED_SEC åž‹)

  type(DC_SCALED_SEC):: iyear, month, iday, imon, isec
  !character(*), parameter :: subname = 'DCDateTimeEval1'
continue
  !call BeginSub(subname)
  if (present(zone)) then
    zone = time % zone
  end if
  if (present(caltype)) then
    caltype = time % caltype
  end if
  isec = time % sec
  if (present(hour)) then
    hour = floor(isec / HOUR_SECONDS)
    isec = modulo(isec, HOUR_SECONDS)
  end if
  if (present(min)) then
    min = floor(isec / MIN_SECONDS)
    isec = modulo(isec, MIN_SECONDS)
  end if
  if (present(sec)) then
    sec = isec
  end if
  if (present(sclsec)) then
    sclsec = isec
  end if

  if (time % caltype == CAL_CYCLIC) then
    iday = time % day
    if (present(year)) year = 0
    if (present(sclyear)) sclyear = 0
    if (present(sclmon)) then
      sclmon = floor(iday / CYCLIC_MDAYS)
      iday = ceiling( modulo(iday, CYCLIC_MDAYS) )
    elseif (present(mon)) then
      mon = floor(iday / CYCLIC_MDAYS)
      iday = ceiling( modulo(iday, CYCLIC_MDAYS) )
    end if
    if (present(day)) day = iday
    if (present(sclday)) sclday = iday
    goto 999
  endif
  if (time % caltype == CAL_NOLEAP) then
    iday = int( modulo(time%day - 91, YEAR_DAYS) )
    iyear = int( (time%day - 91 - iday) / YEAR_DAYS )
  else
    if (time % caltype == CAL_JULIAN .or. time%day < 640196) then
      iday = int( modulo(time%day - 92, FOUR_YEARS) )
      iyear = int( (time%day - 92 - iday) / FOUR_YEARS ) * 4
    else
      iday = int( modulo(time%day - 94, FOUR_CENTURY) )
      iyear = int( (time%day - 94 - iday) / FOUR_CENTURY ) * 400
      if (iday == FOUR_CENTURY - 1) then
        iyear = iyear + 300
        iday = 36525
      else
        iyear = iyear + int( iday / 36524 ) * 100
        iday = int( modulo(iday, 36524) )
      endif
      iyear = iyear + int( iday / FOUR_YEARS ) * 4
      iday = int( modulo(iday, FOUR_YEARS) )
    endif
    if (iday == FOUR_YEARS - 1) then
      iyear = iyear + 3
      iday = YEAR_DAYS
    else
      iyear = iyear + int( iday / YEAR_DAYS )
      iday = int( modulo(iday, YEAR_DAYS) )
    endif
  endif

  iday = iday * 10 + 922
  month = int( iday / 306 )

  if (present(sclyear)) then
    imon = mod(month - 1, YEAR_MONTHS) + 1
    sclyear = iyear + int( (month - imon) / YEAR_MONTHS )
  elseif (present(year)) then
    imon = mod(month - 1, YEAR_MONTHS) + 1
    year = iyear + int( (month - imon) / YEAR_MONTHS )
  else
    imon = month
  end if
  if (present(sclmon)) then
    iday = int( mod(iday, 306) / 10 ) + 1
    sclmon = imon
  elseif (present(mon)) then
    iday = int( mod(iday, 306) / 10 ) + 1
    mon = imon
  else
    iday = int( iday / 10 )  + 1
  end if

  if (present(day)) day = iday
  if (present(sclday)) sclday = iday

999 continue
  !call EndSub(subname)
end subroutine DCDateTimeEval1

subroutine DCDiffTimeEval1(diff, &
  & year, mon, day, hour, min, sec, nondim, &
  & sclyear, sclmon, sclday, sclsec, sclnondim, err)
  !
  ! dc_date_types#DC_DIFFTIME åž‹å¤‰æ•° *diff* ã‚’
  ! å¹´ *year*, æœˆ *mon*, æ—¥ *day*, æ™‚é–“ *hour*, åˆ† *min*, ç§’ *sec*,
  ! ç„¡æ¬¡å…ƒæ™‚é–“ *nondim* ã«å¤‰æ›ã—ã¦è¿”ã—ã¾ã™.
  !
  use dc_types, only: DP
  use dc_trace, only: BeginSub, EndSub
  use dc_error, only: StoreError, DC_NOERR, DC_ENODIMTIME, DC_EDIMTIME
  use dc_date_types, only: DC_DIFFTIME, &
    & MIN_SECONDS, HOUR_SECONDS, YEAR_MONTHS
  use dc_scaledsec, only:  DC_SCALED_SEC, &
    & assignment(=), DCScaledSecPutLine, &
    & operator(==), operator(>), operator(<), operator(>=), operator(<=), &
    & operator(+), operator(-), operator(*), operator(/), mod, modulo, &
    & abs, int, floor, ceiling
  implicit none
  type(DC_DIFFTIME), intent(in):: diff
  integer, intent(out), optional:: year ! å¹´
  integer, intent(out), optional:: mon  ! æœˆ
  integer, intent(out), optional:: day  ! æ—¥
  integer, intent(out), optional:: hour ! æ™‚
  integer, intent(out), optional:: min  ! åˆ†
  real(DP),intent(out), optional:: sec  ! ç§’
  real(DP),intent(out), optional:: nondim  ! ç„¡æ¬¡å…ƒæ™‚é–“. Nondimensional time
  type(DC_SCALED_SEC), intent(out), optional:: sclyear ! å¹´ (DC_SCALED_SEC åž‹)
  type(DC_SCALED_SEC), intent(out), optional:: sclmon  ! æœˆ (DC_SCALED_SEC åž‹)
  type(DC_SCALED_SEC), intent(out), optional:: sclday  ! æ—¥ (DC_SCALED_SEC åž‹)
  type(DC_SCALED_SEC), intent(out), optional:: sclsec  ! ç§’ (DC_SCALED_SEC åž‹)
  type(DC_SCALED_SEC), intent(out), optional:: sclnondim  ! ç„¡æ¬¡å…ƒæ™‚é–“ (DC_SCALED_SEC åž‹)
  logical, intent(out), optional :: err
  type(DC_SCALED_SEC):: imon, isec
  integer:: stat
  character(*), parameter :: subname = 'DCDiffTimeEval1'
continue
  !call BeginSub(subname)
  stat = DC_NOERR
  if ( present(sclnondim) ) then
    if ( .not. diff % nondim_flag ) then
      stat = DC_EDIMTIME
      goto 999
    end if
    sclnondim = diff % sec
  elseif ( present(nondim) ) then
    if ( .not. diff % nondim_flag ) then
      stat = DC_EDIMTIME
      goto 999
    end if
    nondim = diff % sec
  else
    if ( diff % nondim_flag ) then
      stat = DC_ENODIMTIME
      goto 999
    end if
  end if

  imon = diff % mon
  isec = diff % sec
  if (present(sclyear)) then
    sclyear = int( imon / YEAR_MONTHS )
    imon = mod(imon, YEAR_MONTHS)
  elseif (present(year)) then
    year = int( imon / YEAR_MONTHS )
    imon = mod(imon, YEAR_MONTHS)
  endif

  if (present(sclmon)) then
    sclmon = imon
  elseif (present(mon)) then
    mon = imon
  endif

  if (present(sclday)) then
    sclday = diff % day
  elseif (present(day)) then
    day = diff % day
  else
    isec = isec + diff % day * diff % day_seconds
  endif

  if (present(hour)) then
    hour = int(isec / HOUR_SECONDS)
    isec = mod(isec, HOUR_SECONDS)
  endif
  if (present(min)) then
    min = int(isec / MIN_SECONDS)
    isec = mod(isec, MIN_SECONDS)
  endif

  if (present(sec)) then
    sec = isec
  endif
  if (present(sclsec)) then
    sclsec = isec
  endif
999 continue
  call StoreError(stat, subname, err)
  !call EndSub(subname)
end subroutine DCDiffTimeEval1

function DCDateTimeEvalDay(time) result(result)
  !
  ! dc_date_types#DC_DATETIME åž‹å¤‰æ•°ã®æ—¥æ™‚ã‚’æ—¥æ•°ã«æ›ç®—ã—ã¦
  ! å€ç²¾åº¦å®Ÿæ•°åž‹å¤‰æ•°ã§è¿”ã—ã¾ã™. (ä¾‹ãˆã° 12 æ™‚é–“ã¯ 0.5 æ—¥ã¨æ›ç®—ã•ã‚Œã¾ã™).
  !
  use dc_types, only: DP
  use dc_date_generic, only: Eval
  use dc_date_types, only: DC_DATETIME
  use dc_scaledsec, only: DC_SCALED_SEC, assignment(=), operator(/), operator(+)
  implicit none
  real(DP):: result
  type(DC_DATETIME), intent(in):: time
  type(DC_SCALED_SEC):: day, sec
continue
  call Eval(time, sclday = day, sclsec = sec)
  result = day + sec / time % day_seconds
end function DCDateTimeEvalDay

function DCDiffTimeEvalDay(diff) result(result)
  !
  ! dc_date_types#DC_DIFFTIME åž‹å¤‰æ•°ã®æ—¥æ™‚ã‚’æ—¥æ•°ã«æ›ç®—ã—ã¦
  ! å€ç²¾åº¦å®Ÿæ•°åž‹å¤‰æ•°ã§è¿”ã—ã¾ã™. (ä¾‹ãˆã° 12 æ™‚é–“ã¯ 0.5 æ—¥ã¨æ›ç®—ã•ã‚Œã¾ã™).
  !
  ! 1 ãƒ¶æœˆã¯ dc_date_types#CYCLIC_MDAYS ã¨æ›ç®—ã—ã¾ã™.
  !
  use dc_types, only: DP
  use dc_date_generic, only: Eval
  use dc_date_types, only: DC_DIFFTIME, CYCLIC_MDAYS
  use dc_scaledsec, only: DC_SCALED_SEC, assignment(=), operator(/), &
    & operator(+), operator(*), int
  implicit none
  real(DP):: result
  type(DC_DIFFTIME), intent(in):: diff
  type(DC_SCALED_SEC):: day, mon, sec
continue
  call Eval(diff, sclmon = mon, sclday = day, sclsec = sec)
  result = int(mon * CYCLIC_MDAYS) + day + sec / diff % day_seconds
end function DCDiffTimeEvalDay

function DCDateTimeEvalHour(time) result(result)
  !
  ! dc_date_types#DC_DATETIME åž‹å¤‰æ•°ã®æ—¥æ™‚ã‚’æ™‚é–“ã«æ›ç®—ã—ã¦
  ! å€ç²¾åº¦å®Ÿæ•°åž‹å¤‰æ•°ã§è¿”ã—ã¾ã™.
  ! (ä¾‹ãˆã° 2 æ—¥ã¯ 48 æ™‚é–“ã«, 30 åˆ† ã¯ 0.5 æ™‚é–“ã¨æ›ç®—ã•ã‚Œã¾ã™).
  !
  use dc_types, only: DP
  use dc_date_generic, only: Eval
  use dc_date_types, only: DC_DATETIME, HOUR_SECONDS
  use dc_scaledsec, only: DC_SCALED_SEC, assignment(=), operator(/), &
    & operator(+), operator(*), int
  implicit none
  real(DP):: result
  type(DC_DATETIME), intent(in):: time
  type(DC_SCALED_SEC):: day, sec
continue
  call Eval(time, sclday = day, sclsec = sec)
  result = (day * time % day_seconds + sec) / HOUR_SECONDS
end function DCDateTimeEvalHour

function DCDiffTimeEvalHour(diff) result(result)
  !
  ! dc_date_types#DC_DIFFTIME åž‹å¤‰æ•°ã®æ—¥æ™‚ã‚’æ™‚é–“ã«æ›ç®—ã—ã¦
  ! å€ç²¾åº¦å®Ÿæ•°åž‹å¤‰æ•°ã§è¿”ã—ã¾ã™.
  ! (ä¾‹ãˆã° 2 æ—¥ã¯ 48 æ™‚é–“ã«, 30 åˆ† ã¯ 0.5 æ™‚é–“ã¨æ›ç®—ã•ã‚Œã¾ã™).
  !
  ! 1 ãƒ¶æœˆã¯ dc_date_types#CYCLIC_MDAYS ã¨æ›ç®—ã—ã¾ã™.
  !
  use dc_types, only: DP
  use dc_date_generic, only: Eval
  use dc_date_types, only: DC_DIFFTIME, HOUR_SECONDS, CYCLIC_MDAYS
  use dc_scaledsec, only: DC_SCALED_SEC, assignment(=), operator(/), &
    & operator(+), operator(*), int
  implicit none
  real(DP):: result
  type(DC_DIFFTIME), intent(in):: diff
  type(DC_SCALED_SEC):: mon, day, sec
continue
  call Eval(diff, sclmon = mon, sclday = day, sclsec = sec)
  result = ( int(mon * CYCLIC_MDAYS) + day &
    &         * diff % day_seconds + sec) / HOUR_SECONDS
end function DCDiffTimeEvalHour

function DCDateTimeEvalMin(time) result(result)
  !
  ! dc_date_types#DC_DATETIME åž‹å¤‰æ•°ã®æ—¥æ™‚ã‚’åˆ†ã«æ›ç®—ã—ã¦
  ! å€ç²¾åº¦å®Ÿæ•°åž‹å¤‰æ•°ã§è¿”ã—ã¾ã™.
  ! (ä¾‹ãˆã° 1 æ—¥ã¯ 3600 åˆ†ã«, 30 ç§’ ã¯ 0.5 åˆ†ã¨æ›ç®—ã•ã‚Œã¾ã™).
  !
  use dc_types, only: DP
  use dc_date_generic, only: Eval
  use dc_date_types, only: DC_DATETIME, MIN_SECONDS
  use dc_scaledsec, only: DC_SCALED_SEC, assignment(=), operator(/), &
    & operator(+), operator(*), int
  implicit none
  real(DP):: result
  type(DC_DATETIME), intent(in):: time
  type(DC_SCALED_SEC):: day, sec
continue
  call Eval(time, sclday = day, sclsec = sec)
  result = (day * time % day_seconds + sec) / MIN_SECONDS
end function DCDateTimeEvalMin

function DCDiffTimeEvalMin(diff) result(result)
  !
  ! dc_date_types#DC_DIFFTIME åž‹å¤‰æ•°ã®æ—¥æ™‚ã‚’åˆ†ã«æ›ç®—ã—ã¦
  ! å€ç²¾åº¦å®Ÿæ•°åž‹å¤‰æ•°ã§è¿”ã—ã¾ã™.
  ! (ä¾‹ãˆã° 1 æ—¥ã¯ 3600 åˆ†ã«, 30 ç§’ ã¯ 0.5 åˆ†ã¨æ›ç®—ã•ã‚Œã¾ã™).
  !
  ! 1 ãƒ¶æœˆã¯ dc_date_types#CYCLIC_MDAYS ã¨æ›ç®—ã—ã¾ã™.
  !
  use dc_types, only: DP
  use dc_date_generic, only: Eval
  use dc_date_types, only: DC_DIFFTIME, MIN_SECONDS, CYCLIC_MDAYS
  use dc_scaledsec, only: DC_SCALED_SEC, assignment(=), operator(/), &
    & operator(+), operator(*), int
  implicit none
  real(DP):: result
  type(DC_DIFFTIME), intent(in):: diff
  type(DC_SCALED_SEC):: mon, day, sec
continue
  call Eval(diff, sclmon = mon, sclday = day, sclsec = sec)
  result = ( int(mon * CYCLIC_MDAYS) + day &
    &         * diff % day_seconds + sec) / MIN_SECONDS
end function DCDiffTimeEvalMin

function DCDateTimeEvalSec(time) result(result)
  !
  ! dc_date_types#DC_DATETIME åž‹å¤‰æ•°ã®æ—¥æ™‚ã‚’ç§’ã«æ›ç®—ã—ã¦
  ! å€ç²¾åº¦å®Ÿæ•°åž‹å¤‰æ•°ã§è¿”ã—ã¾ã™.
  !
  ! å¹´ã®è¦ç´ ã¯ç„¡è¦–ã•ã‚Œã¾ã™. ã™ãªã‚ã¡, 1999-01-01 ãŒæ ¼ç´ã•ã‚ŒãŸ time ã¨
  ! 2007-01-01 ãŒæ ¼ç´ã•ã‚ŒãŸ time ã‹ã‚‰ã¯åŒã˜å€¤ãŒè¿”ã‚Šã¾ã™.
  ! (ã“ã‚Œã¯ã‚‚ã—ã‹ã™ã‚‹ã¨æœ›ã¾ã—ãç„¡ã„å‹•ä½œã‹ã‚‚ã—ã‚Œã¾ã›ã‚“).
  !
  use dc_types, only: DP
  use dc_date_generic, only: Eval
  use dc_date_types, only: DC_DATETIME
  use dc_scaledsec, only: assignment(=)
  implicit none
  real(DP):: result
  type(DC_DATETIME), intent(in):: time
  integer:: day
  real(DP):: sec, day_seconds
continue
  call Eval(time, day = day, sec = sec)
  day_seconds = time % day_seconds
  result = day * day_seconds + sec
end function DCDateTimeEvalSec

function DCDiffTimeEvalSec(diff) result(result)
  !
  ! dc_date_types#DC_DIFFTIME åž‹å¤‰æ•°ã®æ—¥æ™‚ã‚’ç§’ã«æ›ç®—ã—ã¦
  ! å€ç²¾åº¦å®Ÿæ•°åž‹å¤‰æ•°ã§è¿”ã—ã¾ã™.
  !
  ! 1 ãƒ¶æœˆã¯ dc_date_types#CYCLIC_MDAYS ã¨æ›ç®—ã—ã¾ã™.
  !
  use dc_types, only: DP
  use dc_date_generic, only: Eval
  use dc_date_types, only: DC_DIFFTIME, CYCLIC_MDAYS
  use dc_scaledsec, only: assignment(=)
  implicit none
  real(DP):: result
  type(DC_DIFFTIME), intent(in):: diff
  integer:: mon, day
  real(DP):: sec, day_seconds
continue
  if ( .not. diff % nondim_flag ) then
    call Eval(diff, mon = mon, day = day, sec = sec)
    day_seconds = diff % day_seconds
    result = int(mon * CYCLIC_MDAYS) + day * day_seconds + sec
  else
    call Eval(diff, nondim = result)
  end if
end function DCDiffTimeEvalSec

function DCDiffTimeEvalNondim(diff) result(result)
  !
  ! dc_date_types#DC_DIFFTIME åž‹å¤‰æ•°ã®æ—¥æ™‚ã‚’ç„¡æ™‚é™æ™‚é–“ã«æ›ç®—ã—ã¦
  ! å€ç²¾åº¦å®Ÿæ•°åž‹å¤‰æ•°ã§è¿”ã—ã¾ã™.
  !
  ! 1 ãƒ¶æœˆã¯ dc_date_types#CYCLIC_MDAYS ã¨æ›ç®—ã—ã¾ã™.
  !
  use dc_types, only: DP
  use dc_date_generic, only: Eval
  use dc_date_types, only: DC_DIFFTIME, CYCLIC_MDAYS
  implicit none
  real(DP):: result
  type(DC_DIFFTIME), intent(in):: diff
  real(DP):: nondim
continue
  call Eval(diff, nondim=nondim)
  result = nondim
end function DCDiffTimeEvalNondim

function DCDateTimeEvalSclSec(time) result(result)
  !
  ! dc_date_types#DC_DATETIME åž‹å¤‰æ•°ã®æ—¥æ™‚ã‚’ç§’ã«æ›ç®—ã—ã¦
  ! DC_SCALED_SEC åž‹ã§è¿”ã—ã¾ã™.
  !
  ! å¹´ã®è¦ç´ ã¯ç„¡è¦–ã•ã‚Œã¾ã™. ã™ãªã‚ã¡, 1999-01-01 ãŒæ ¼ç´ã•ã‚ŒãŸ time ã¨
  ! 2007-01-01 ãŒæ ¼ç´ã•ã‚ŒãŸ time ã‹ã‚‰ã¯åŒã˜å€¤ãŒè¿”ã‚Šã¾ã™.
  ! (ã“ã‚Œã¯ã‚‚ã—ã‹ã™ã‚‹ã¨æœ›ã¾ã—ãç„¡ã„å‹•ä½œã‹ã‚‚ã—ã‚Œã¾ã›ã‚“).
  !
  use dc_types, only: DP
  use dc_date_generic, only: Eval
  use dc_date_types, only: DC_DATETIME
  use dc_scaledsec, only: DC_SCALED_SEC, operator(/), &
    & operator(+), operator(*), int
  implicit none
  type(DC_SCALED_SEC):: result
  type(DC_DATETIME), intent(in):: time
  type(DC_SCALED_SEC):: day, sec
continue
  call Eval(time, sclday = day, sclsec = sec)
  result = day * time % day_seconds + sec
end function DCDateTimeEvalSclSec

function DCDiffTimeEvalSclSec(diff) result(result)
  !
  ! dc_date_types#DC_DIFFTIME åž‹å¤‰æ•°ã®æ—¥æ™‚ã‚’ç§’ã«æ›ç®—ã—ã¦
  ! DC_SCALED_SEC åž‹ã§è¿”ã—ã¾ã™.
  !
  ! 1 ãƒ¶æœˆã¯ dc_date_types#CYCLIC_MDAYS ã¨æ›ç®—ã—ã¾ã™.
  !
  use dc_types, only: DP
  use dc_date_generic, only: Eval
  use dc_date_types, only: DC_DIFFTIME, CYCLIC_MDAYS
  use dc_scaledsec, only: DC_SCALED_SEC, operator(/), &
    & operator(==), operator(+), operator(*), int
  implicit none
  type(DC_SCALED_SEC):: result
  type(DC_DIFFTIME), intent(in):: diff
  type(DC_SCALED_SEC):: mon, day, sec
  type(DC_SCALED_SEC):: zero_sec
continue
  if ( .not. diff % nondim_flag ) then
    call Eval(diff, sclmon = mon, sclday = day, sclsec = sec)
    if ( mon == zero_sec ) then
      result = day * diff % day_seconds + sec
    else
      result = ( int(mon * CYCLIC_MDAYS) + day ) * diff % day_seconds + sec
    end if
  else
    call Eval(diff, sclnondim = sec)
    result = sec
  end if
end function DCDiffTimeEvalSclSec

function DCDateTimeEvalByUnit(time, unit, unit_symbol) result(result)
  !
  ! dc_date_types#DC_DATETIME åž‹å¤‰æ•°ã®æ—¥æ™‚ã‚’ *unit* ã¾ãŸã¯
  ! *unit_symbol* ã®å˜ä½
  ! ã«æ›ç®—ã—ã¦å€ç²¾åº¦å®Ÿæ•°åž‹å¤‰æ•°ã§è¿”ã—ã¾ã™.
  !
  ! *unit* ã«ã¯
  ! æ—¥ dc_date_types#UNIT_DAY, æ™‚ dc_date_types#UNIT_HOUR,
  ! åˆ† dc_date_types#UNIT_MIN, ç§’ dc_date_types#UNIT_SEC
  ! ã‚’ä¸Žãˆã‚‹ã“ã¨ãŒå¯èƒ½ã§ã™.
  !
  ! *unit_symbol* ã«ã¯
  ! æ—¥ dc_date_types#UNIT_SYMBOL_DAY, æ™‚ dc_date_types#UNIT_SYMBOL_HOUR,
  ! åˆ† dc_date_types#UNIT_SYMBOL_MIN, ç§’ dc_date_types#UNIT_SYMBOL_SEC
  ! ã‚’ä¸Žãˆã‚‹ã“ã¨ãŒå¯èƒ½ã§ã™.
  !
  ! ã“ã‚Œã‚‰ã«è©²å½“ã—ãªã„ã‚‚ã®ã‚’ *unit* ã¾ãŸã¯ *unit_symbol*
  ! ã«ä¸ŽãˆãŸå ´åˆ, ã‚‚ã—ãã¯å¼•æ•°ã‚’ä¸¡æ–¹ã¨ã‚‚ä¸Žãˆãªã„å ´åˆ, 0.0 ãŒè¿”ã‚Šã¾ã™.
  !
  use dc_types, only: DP, TOKEN
  use dc_date_generic, only: EvalSec, EvalMin, EvalHour, EvalDay, ParseTimeUnits
  use dc_date_types, only: DC_DATETIME, &
    & UNIT_SYMBOL_DAY, UNIT_SYMBOL_HOUR, UNIT_SYMBOL_MIN, UNIT_SYMBOL_SEC, &
    & UNIT_SYMBOL_ERR
  implicit none
  real(DP):: result
  type(DC_DATETIME), intent(in):: time
  character(*), intent(in):: unit
  integer, intent(in), optional:: unit_symbol
  integer:: symbol
continue
  symbol = UNIT_SYMBOL_ERR
  if ( present(unit_symbol) ) then
    symbol = unit_symbol
  else
    symbol = ParseTimeUnits(unit)
  end if

  if ( symbol == UNIT_SYMBOL_SEC ) then
    result = EvalSec(time)
  elseif ( symbol == UNIT_SYMBOL_MIN ) then
    result = EvalMin(time)
  elseif ( symbol == UNIT_SYMBOL_HOUR ) then
    result = EvalHour(time)
  elseif ( symbol == UNIT_SYMBOL_DAY ) then
    result = EvalDay(time)
  else
    result = 0.0_DP
  end if
end function DCDateTimeEvalByUnit

function DCDiffTimeEvalByUnit(diff, unit, unit_symbol) result(result)
  !
  ! dc_date_types#DC_DIFFTIME åž‹å¤‰æ•°ã®æ—¥æ™‚ã‚’ *unit* ã®å˜ä½
  ! ã«æ›ç®—ã—ã¦å€ç²¾åº¦å®Ÿæ•°åž‹å¤‰æ•°ã§è¿”ã—ã¾ã™.
  !
  ! *unit* ã«ã¯
  ! æ—¥ dc_date_types#UNIT_DAY, æ™‚ dc_date_types#UNIT_HOUR,
  ! åˆ† dc_date_types#UNIT_MIN, ç§’ dc_date_types#UNIT_SEC,
  ! ç„¡æ¬¡å…ƒæ™‚é–“ dc_date_types#UNIT_NONDIM
  ! ã‚’ä¸Žãˆã‚‹ã“ã¨ãŒå¯èƒ½ã§ã™.
  !
  ! *unit_symbol* ã«ã¯
  ! æ—¥ dc_date_types#UNIT_SYMBOL_DAY, æ™‚ dc_date_types#UNIT_SYMBOL_HOUR,
  ! åˆ† dc_date_types#UNIT_SYMBOL_MIN, ç§’ dc_date_types#UNIT_SYMBOL_SEC
  ! ç„¡æ¬¡å…ƒæ™‚é–“ dc_date_types#UNIT_SYMBOL_NONDIM
  ! ã‚’ä¸Žãˆã‚‹ã“ã¨ãŒå¯èƒ½ã§ã™.
  !
  ! ã“ã‚Œã‚‰ã«è©²å½“ã—ãªã„ã‚‚ã®ã‚’ *unit* ã¾ãŸã¯ *unit_symbol*
  ! ã«ä¸ŽãˆãŸå ´åˆ, ã‚‚ã—ãã¯å¼•æ•°ã‚’ä¸¡æ–¹ã¨ã‚‚ä¸Žãˆãªã„å ´åˆ, 0.0 ãŒè¿”ã‚Šã¾ã™.
  !
  use dc_types, only: DP, TOKEN
  use dc_date_generic, only: EvalNondim, EvalSec, EvalMin, EvalHour, EvalDay, &
    & ParseTimeUnits
  use dc_date_types, only: DC_DIFFTIME, &
    & UNIT_SYMBOL_DAY, UNIT_SYMBOL_HOUR, UNIT_SYMBOL_MIN, &
    & UNIT_SYMBOL_SEC, UNIT_SYMBOL_NONDIM, UNIT_SYMBOL_ERR
  implicit none
  real(DP):: result
  type(DC_DIFFTIME), intent(in):: diff
  character(*), intent(in):: unit
  integer, intent(in), optional:: unit_symbol
  integer:: symbol
continue
  symbol = UNIT_SYMBOL_ERR
  if ( present(unit_symbol) ) then
    symbol = unit_symbol
  else
    symbol = ParseTimeUnits(unit)
  end if

  if ( symbol == UNIT_SYMBOL_NONDIM ) then
    result = EvalNondim(diff)
  elseif ( symbol == UNIT_SYMBOL_SEC ) then
    result = EvalSec(diff)
  elseif ( symbol == UNIT_SYMBOL_MIN ) then
    result = EvalMin(diff)
  elseif ( symbol == UNIT_SYMBOL_HOUR ) then
    result = EvalHour(diff)
  elseif ( symbol == UNIT_SYMBOL_DAY ) then
    result = EvalDay(diff)
  else
    result = 0.0_DP
  end if
end function DCDiffTimeEvalByUnit

!!$subroutine DCDateTimeEval0(time, mon, day, sec)
!!$  !
!!$  ! dc_date_types#DC_DATETIME åž‹å¤‰æ•°ã® *time* ã‚’
!!$  ! æœˆ *mon*, æ—¥ *day*, ç§’ *sec* ã«å¤‰æ›ã—ã¦è¿”ã™.
!!$  !
!!$  use dc_types, only: DP
!!$  use dc_date_types, only: DC_DATETIME, &
!!$    & CYCLIC_MDAYS, CAL_NOLEAP, CAL_JULIAN, CAL_CYCLIC, &
!!$    & FOUR_YEARS, FOUR_CENTURY
!!$  use dc_trace, only: BeginSub, EndSub
!!$  implicit none
!!$  type(DC_DATETIME), intent(in):: time
!!$  integer, intent(out):: mon, day
!!$  real(DP), intent(out):: sec
!!$  integer:: year, month
!!$  character(*), parameter :: subname = 'DCDateTimeEval0'
!!$continue
!!$  call BeginSub(subname)
!!$  sec = time%sec
!!$  if (time % caltype == CAL_CYCLIC) then
!!$    day = modulo(dble(time%day - 1), CYCLIC_MDAYS) + 1
!!$    mon = (time%day - 1) / CYCLIC_MDAYS
!!$    goto 999
!!$  endif
!!$  if (time % caltype == CAL_NOLEAP) then
!!$    day = modulo(time%day - 91, 365)
!!$    year = (time%day - 91 - day) / 365
!!$  else
!!$    if (time % caltype == CAL_JULIAN .or. time%day < 640196) then
!!$      day = modulo(time%day - 92, FOUR_YEARS)
!!$      year = (time%day - 92 - day) / FOUR_YEARS * 4
!!$    else
!!$      day = modulo(time%day - 94, FOUR_CENTURY)
!!$      year = (time%day - 94 - day) / FOUR_CENTURY * 400
!!$      if (day == FOUR_CENTURY - 1) then
!!$        year = year + 300
!!$        day = 36525
!!$      else
!!$        year = year + day / 36524 * 100
!!$        day = modulo(day, 36524)
!!$      endif
!!$      year = year + day / FOUR_YEARS * 4
!!$      day = modulo(day, FOUR_YEARS)
!!$    endif
!!$    if (day == FOUR_YEARS - 1) then
!!$      year = year + 3
!!$      day = 365
!!$    else
!!$      year = year + day / 365
!!$      day = modulo(day, 365)
!!$    endif
!!$  endif
!!$  day = day * 10 + 922
!!$  month = day / 306
!!$  mon = mod(month - 1, 12) + 1
!!$  year = year + (month - mon) / 12
!!$  day = mod(day, 306) / 10  + 1
!!$999 continue
!!$  call EndSub(subname, 'mon=<%d>, day=<%d>, sec=<%f>',&
!!$    & i=(/mon, day/), d=(/sec/))
!!$end subroutine DCDateTimeEval0