!== dcdatetime.f90 - dc_date_types#DC_DATETIME 型変数の生成
!
! Authors::   Yasuhiro MORIKAWA, Eizi TOYODA
! Version::   $Id: dcdatetime.f90,v 1.4 2006/01/09 22:47:05 morikawa Exp $
! Tag Name::  $Name: gt4f90io-20060117 $
! Copyright:: Copyright (C) GFD Dennou Club, 2000-2005. All rights reserved.
! License::   See COPYRIGHT[link:../../COPYRIGHT]
!
! このファイルで提供される手続き群は dc_date モジュールにて提供されます。
!

type(DC_DATETIME) function DCDateTime(mon, day, sec) result(result) !:nodoc:
  !
  ! dc_date_types#DC_DATETIME の生成を行う関数です (constructor)。
  !
  ! dc_date#Eval の逆操作を行います。
  !
  !--
  ! このサブルーチンは暦法 (1 年が何日か？ 1 日は何秒か？) を知っています。
  ! ですが、もしかすると、dc_data_types 内の変数を用いるべきかもしれません。
  !++
  !
  use dc_types,      only: DP
  use dc_date_types, only: DC_DATETIME, caltype, cyclic_mdays, &
    &                      CAL_NOLEAP, CAL_JULIAN, CAL_CYCLIC
  implicit none
  integer, intent(in):: mon, day
  real(DP),     intent(in):: sec

  integer           :: iday, month, year, century
  integer, parameter:: four_years = 365 * 4 + 1
continue
  iday = day + floor(sec / 86400.0_DP)
  result % sec = modulo(sec, 86400.0_DP)
  if (caltype == CAL_CYCLIC) then
    result % day = iday + mon * cyclic_mdays
    return
  endif
  month = modulo(mon - 3, 12) + 3
  year = (mon - month) / 12
  iday = iday + (month * 306 - 914) / 10
  if (caltype == CAL_NOLEAP) then
    result % day = iday + year * 365 + month + 90
  else
    iday = iday + (year * four_years - modulo(year * four_years, 4)) / 4
    if (caltype == CAL_JULIAN .or. iday < 640116) then
      result % day = iday + 91
    else
      century = (year - modulo(year, 100)) / 100 + 1
      result % day = iday - (century * 3 - modulo(century * 3, 4)) / 4 + 93
    endif
  endif
end function DCDateTime
