!= æ—¥æ™‚ã®è¨å®š
!= Setting of date
!
! Authors::   Yasuhiro MORIKAWA
! Version::   $Id: dccaldatecreate.f90,v 1.3 2010-09-24 07:07:31 morikawa Exp $
! Tag Name::  $Name:  $
! Copyright:: Copyright (C) GFD Dennou Club, 2009-. All rights reserved.
! License::   See COPYRIGHT[link:../../COPYRIGHT]
!
! ã“ã®ãƒ•ã‚¡ã‚¤ãƒ«ã«è¨˜è¼‰ã•ã‚Œã‚‹æ‰‹ç¶šãç¾¤ã¯ dc_calendar ãƒ¢ã‚¸ãƒ¥ãƒ¼ãƒ«ã‹ã‚‰æä¾›ã•ã‚Œã¾ã™.
!
! Procedures described in this file are provided from "dc_calendar" module.
!

subroutine DCCalDateCreate1( year, month, day, hour, min, sec, date, zone, err )
  !
  ! æ—¥æ™‚ã®è¨å®šã‚’è¡Œã„ã¾ã™.
  !
  ! YYYY-MM-DDThh:mm:ss.sTZD ã®ã‚ˆã†ãªæ–‡å—åˆ—
  ! (YYYY ã¯å¹´, MM ã¯æœˆ, DD ã¯æ—¥, hh ã¯æ™‚, mm ã¯åˆ†, ss.s ã¯ç§’,
  ! TZD ã¯ã‚¿ã‚¤ãƒ ã‚¾ãƒ¼ãƒ³) ã§æŒ‡å®šã™ã‚‹å ´åˆã«ã¯
  ! ä¸‹è¨˜ã®åŒåã®ã‚µãƒ–ãƒ«ãƒ¼ãƒãƒ³ã‚’ä½¿ç”¨ã—ã¦ä¸‹ã•ã„.
  !
  ! çœç•¥å¯èƒ½å¼•æ•° *date* ãŒçœç•¥ã•ã‚ŒãŸå ´åˆã«ã¯, dc_calendar å†…éƒ¨ã§
  ! ä¿æŒã•ã‚Œã‚‹ "dc_calendar_types#DC_CAL_DATE" åž‹ã®å¤‰æ•°ã«æ—¥æ™‚ãŒ
  ! è¨å®šã•ã‚Œã¾ã™. ãã®å¾Œã®æ‰‹ç¶šãã§ *date* ã‚’çœç•¥ã—ãŸå ´åˆã«ã¯
  ! ã“ã®æ—¥æ™‚ãŒä½¿ç”¨ã•ã‚Œã¾ã™.
  ! *date* ãŒçœç•¥ã•ã‚Œãªã„å ´åˆã«ã¯ãã®å¤‰æ•°ã«æ—¥æ™‚ãŒè¨å®šã•ã‚Œã¾ã™.
  ! ãã®æ—¥æ™‚ã‚’ä½¿ç”¨ã™ã‚‹å ´åˆ, æ‰‹ç¶šãã«ãã® "dc_calendar_types#DC_CAL_DATE" åž‹ã®å¤‰æ•°
  ! ã‚’ä¸Žãˆã¦ãã ã•ã„.
  !
  ! Set date.
  !
  ! If a string like as "YYYY-MM-DDThh:mm:ss.sTZD"
  ! (YYYY is year, MM is month, DD is day, hh is hour, mm is minute,
  ! ss.s is second, TZD is time zone) is used,
  ! use a following homonymous subroutine.
  !
  ! If an optional argument *date* is omitted,
  ! the date setting is stored to a "dc_calendar_types#DC_CAL_DATE"
  ! variable that is saved in the "dc_calendar".
  ! When *date* is omitted in subsequent procedures, the internal date
  ! is used.
  ! If *date* is not omitted, the settings is stored to the *date*.
  ! In order to use the date setting, use the "dc_calendar_types#DC_CAL_DATE"
  ! varieble to subsequent procedures.
  !

  use dc_calendar_types, only: DC_CAL_DATE
  use dc_calendar_internal, only: default_date
  use dc_regex, only: match
  use dc_message, only: MessageNotify
  use dc_string, only: LChar
  use dc_trace, only: BeginSub, EndSub
  use dc_error, only: StoreError, DC_NOERR, DC_EALREADYINIT, DC_EBADDATE
  use dc_types, only: STRING, DP
  implicit none
  integer, intent(in):: year  ! å¹´. Year.
  integer, intent(in):: month ! æœˆ. Month.
  integer, intent(in):: day   ! æ—¥. Day.
  integer, intent(in):: hour  ! æ™‚. Hour.
  integer, intent(in):: min   ! åˆ†. Minute.
  real(DP), intent(in):: sec  ! ç§’. Second.
  type(DC_CAL_DATE), intent(out), optional, target:: date
                              ! æ—¥æ™‚æƒ…å ±ã‚’åŽã‚ãŸã‚ªãƒ–ã‚¸ã‚§ã‚¯ãƒˆ.
                              ! çœç•¥ã—ãŸå ´åˆã«ã¯, ãƒ‡ãƒ•ã‚©ãƒ«ãƒˆã®æ—¥æ™‚ã¨ã—ã¦
                              ! æŒ‡å®šã•ã‚Œã‚‹.
                              !
                              ! An object that stores information of
                              ! date and time.
                              ! If this is omitted, these information is
                              ! set as default date and time.
  character(*), intent(in), optional:: zone
                              ! UTC ã‹ã‚‰ã®æ™‚å·®. Time-zone.
  logical, intent(out), optional:: err
                              ! ä¾‹å¤–å‡¦ç†ç”¨ãƒ•ãƒ©ã‚°.
                              ! ãƒ‡ãƒ•ã‚©ãƒ«ãƒˆã§ã¯, ã“ã®æ‰‹ç¶šãå†…ã§ã‚¨ãƒ©ãƒ¼ãŒ
                              ! ç”Ÿã˜ãŸå ´åˆ, ãƒ—ãƒã‚°ãƒ©ãƒ ã¯å¼·åˆ¶çµ‚äº†ã—ã¾ã™.
                              ! å¼•æ•° *err* ãŒä¸Žãˆã‚‰ã‚Œã‚‹å ´åˆ,
                              ! ãƒ—ãƒã‚°ãƒ©ãƒ ã¯å¼·åˆ¶çµ‚äº†ã›ãš, ä»£ã‚ã‚Šã«
                              ! *err* ã« .true. ãŒä»£å…¥ã•ã‚Œã¾ã™.
                              !
                              ! Exception handling flag.
                              ! By default, when error occur in
                              ! this procedure, the program aborts.
                              ! If this *err* argument is given,
                              ! .true. is substituted to *err* and
                              ! the program does not abort.

  ! ä½œæ¥å¤‰æ•°
  ! Work variables
  !
  type(DC_CAL_DATE), pointer:: datep =>null()
  integer:: start, length
  integer:: stat
  character(STRING):: cause_c
  character(*), parameter:: version = &
    & '$Name:  $' // &
    & '$Id: dccaldatecreate.f90,v 1.3 2010-09-24 07:07:31 morikawa Exp $'
  character(*), parameter:: subname = 'DCCalDateCreate1'
continue
  call BeginSub( subname, version )
  stat = DC_NOERR
  cause_c = ''

  ! ã‚ªãƒ–ã‚¸ã‚§ã‚¯ãƒˆã®ãƒã‚¤ãƒ³ã‚¿å‰²ä»˜
  ! Associate pointer of an object
  !
  if ( present( date ) ) then
    datep => date
  else
    datep => default_date
  end if

!!$  ! åˆæœŸè¨å®šã®ãƒã‚§ãƒƒã‚¯
!!$  ! Check initialization
!!$  !
!!$  if ( datep % initialized ) then
!!$    stat = DC_EALREADYINIT
!!$    cause_c = 'DC_CAL_DATE'
!!$    goto 999
!!$  end if

  ! æ—¥æ™‚ã®æ£å½“æ€§ã®ãƒã‚§ãƒƒã‚¯
  ! Validate date and time
  !
!!$  if ( year < 1 ) then
!!$    stat = DC_EBADDATE
!!$    call MessageNotify('W', subname, 'year=<%d> must be natural number', &
!!$      & i = (/ year /) )
!!$    goto 999
!!$  end if

  if ( month < 1 ) then
    stat = DC_EBADDATE
    call MessageNotify('W', subname, 'month=<%d> must be natural number', &
      & i = (/ month /) )
    goto 999
  end if

  if ( day < 1 ) then
    stat = DC_EBADDATE
    call MessageNotify('W', subname, 'day=<%d> must be natural number', &
      & i = (/ day /) )
    goto 999
  end if

  if ( hour < 0 ) then
    stat = DC_EBADDATE
    call MessageNotify('W', subname, 'hour=<%d> must not be negative', &
      & i = (/ hour /) )
    goto 999
  end if

  if ( min < 0 ) then
    stat = DC_EBADDATE
    call MessageNotify('W', subname, 'min=<%d> must not be negative', &
      & i = (/ min /) )
    goto 999
  end if

  if ( sec < 0.0_DP ) then
    stat = DC_EBADDATE
    call MessageNotify('W', subname, 'sec=<%f> must not be negative', &
      & d = (/ sec /) )
    goto 999
  end if

  call match( '^[#+-]#d+:#d+$', zone, & ! (in)
    &         start, length )           ! (out)
  if ( length > 0 ) then
    datep % zone = zone
  else
    datep % zone = ''
  end if

  ! å„è¦ç´ ã¸ã®å€¤ã®è¨å®š
  ! Configure elements
  !
  datep % year  = year
  datep % month = month
  datep % day   = day
  datep % hour  = hour
  datep % min   = min
  datep % sec   = sec

  ! çµ‚äº†å‡¦ç†, ä¾‹å¤–å‡¦ç†
  ! Termination and Exception handling
  !
  datep % initialized = .true.
999 continue
  nullify( datep )
  call StoreError( stat, subname, err, cause_c )
  call EndSub( subname )
end subroutine DCCalDateCreate1

subroutine DCCalDateCreate2( date_str, date, err )
  !
  ! æ—¥æ™‚ã®è¨å®šã‚’è¡Œã„ã¾ã™.
  !
  ! *date_str* ã« YYYY-MM-DDThh:mm:ss.sTZD ã®å½¢å¼ã®æ–‡å—åˆ—
  ! (YYYY ã¯å¹´, MM ã¯æœˆ, DD ã¯æ—¥, hh ã¯æ™‚, mm ã¯åˆ†, ss.s ã¯ç§’,
  ! TZD ã¯ã‚¿ã‚¤ãƒ ã‚¾ãƒ¼ãƒ³) ã‚’æŒ‡å®šã—ã¦ãã ã•ã„.
  ! å¹´æœˆæ—¥æ™‚åˆ†ç§’ã‚’å„å€‹å¤‰æ•°ã§æŒ‡å®šã™ã‚‹å ´åˆã«ã¯
  ! ä¸Šè¨˜ã®åŒåã®ã‚µãƒ–ãƒ«ãƒ¼ãƒãƒ³ã‚’ä½¿ç”¨ã—ã¦ä¸‹ã•ã„.
  ! æ—¥æ™‚ã®æ–‡å—åˆ—å½¢å¼ã¯
  ! gtool4 netCDF è¦ç´„ã€Œ5.5 æ—¥æ™‚å½¢å¼ã€ã«æº–æ‹ ã—ã¦ã„ã¾ã™.
  !
  ! "s since 2009-06-17T11:23:45+09:00" ã®ã‚ˆã†ãªæ–‡å—åˆ—ã‚’ä¸ŽãˆãŸå ´åˆã«ã¯,
  ! "s since " ã®éƒ¨åˆ†ã‚’ã‚µãƒ–ãƒ«ãƒ¼ãƒãƒ³å†…ã§è‡ªå‹•çš„ã«åˆ‡ã‚Šå–ã£ã¦,
  ! "2009-06-17T11:23:45+09:00" ã®éƒ¨åˆ†ã‚’è¨å®šã—ã¾ã™.
  !
  ! çœç•¥å¯èƒ½å¼•æ•° *date* ãŒçœç•¥ã•ã‚ŒãŸå ´åˆã«ã¯, dc_calendar å†…éƒ¨ã§
  ! ä¿æŒã•ã‚Œã‚‹ "dc_calendar_types#DC_CAL_DATE" åž‹ã®å¤‰æ•°ã«æ—¥æ™‚ãŒ
  ! è¨å®šã•ã‚Œã¾ã™. ãã®å¾Œã®æ‰‹ç¶šãã§ *date* ã‚’çœç•¥ã—ãŸå ´åˆã«ã¯
  ! ã“ã®æ—¥æ™‚ãŒä½¿ç”¨ã•ã‚Œã¾ã™.
  ! *date* ãŒçœç•¥ã•ã‚Œãªã„å ´åˆã«ã¯ãã®å¤‰æ•°ã«æ—¥æ™‚ãŒè¨å®šã•ã‚Œã¾ã™.
  ! ãã®æ—¥æ™‚ã‚’ä½¿ç”¨ã™ã‚‹å ´åˆ, æ‰‹ç¶šãã«ãã® "dc_calendar_types#DC_CAL_DATE" åž‹ã®å¤‰æ•°
  ! ã‚’ä¸Žãˆã¦ãã ã•ã„.
  !
  ! Set date.
  !
  ! Specify a string like as "YYYY-MM-DDThh:mm:ss.sTZD"
  ! (YYYY is year, MM is month, DD is day, hh is hour, mm is minute,
  ! ss.s is second, TZD is time zone).
  ! If individual variables (year, month, day, hour, minute, second, zone)
  ! are used, use a foregoing homonymous subroutine.
  ! Format of date is conformed to gtool4 netCDF Convention "5.5 Expression of date and time"
  !
  ! If a string like as "s since 2009-06-17T11:23:45+09:00" is specified,
  ! A part "s since " is truncated automatically, and
  ! a part "2009-06-17T11:23:45+09:00" is set.
  !
  ! If an optional argument *date* is omitted,
  ! the date setting is stored to a "dc_calendar_types#DC_CAL_DATE"
  ! variable that is saved in the "dc_calendar".
  ! When *date* is omitted in subsequent procedures, the internal date
  ! is used.
  ! If *date* is not omitted, the settings is stored to the *date*.
  ! In order to use the date setting, use the "dc_calendar_types#DC_CAL_DATE"
  ! varieble to subsequent procedures.
  !
  use dc_calendar_generic, only: DCCalDateParseStr, DCCalDateCreate
  use dc_calendar_types, only: DC_CAL_DATE
  use dc_calendar_internal, only: default_date
  use dc_message, only: MessageNotify
  use dc_types, only: DP, TOKEN
  use dc_trace, only: BeginSub, EndSub
  use dc_error, only: StoreError, DC_NOERR, DC_EALREADYINIT, DC_EBADDATE
  use dc_types, only: STRING
  implicit none
  character(*), intent(in):: date_str
                              ! æ—¥æ™‚æƒ…å ±ã‚’è¡¨ã™æ–‡å—åˆ—.
                              ! è¡¨ç¤ºå½¢å¼ã«ã¤ã„ã¦ã¯ gtool4 netCDF è¦ç´„
                              ! 5.5 æ—¥æ™‚å½¢å¼ã‚’å‚ç…§ã®ã“ã¨.
                              !
                              ! Strings that express date and time.
                              ! See gtool4 netCDF Convention
                              ! 5.5 Expression of date and time for details.
  type(DC_CAL_DATE), intent(out), optional, target:: date
                              ! æ—¥æ™‚æƒ…å ±ã‚’åŽã‚ãŸã‚ªãƒ–ã‚¸ã‚§ã‚¯ãƒˆ.
                              ! çœç•¥ã—ãŸå ´åˆã«ã¯, ãƒ‡ãƒ•ã‚©ãƒ«ãƒˆã®æ—¥æ™‚ã¨ã—ã¦
                              ! æŒ‡å®šã•ã‚Œã‚‹.
                              !
                              ! An object that stores information of
                              ! date and time.
                              ! If this is omitted, these information is
                              ! set as default date and time.
  logical, intent(out), optional:: err
                              ! ä¾‹å¤–å‡¦ç†ç”¨ãƒ•ãƒ©ã‚°.
                              ! ãƒ‡ãƒ•ã‚©ãƒ«ãƒˆã§ã¯, ã“ã®æ‰‹ç¶šãå†…ã§ã‚¨ãƒ©ãƒ¼ãŒ
                              ! ç”Ÿã˜ãŸå ´åˆ, ãƒ—ãƒã‚°ãƒ©ãƒ ã¯å¼·åˆ¶çµ‚äº†ã—ã¾ã™.
                              ! å¼•æ•° *err* ãŒä¸Žãˆã‚‰ã‚Œã‚‹å ´åˆ,
                              ! ãƒ—ãƒã‚°ãƒ©ãƒ ã¯å¼·åˆ¶çµ‚äº†ã›ãš, ä»£ã‚ã‚Šã«
                              ! *err* ã« .true. ãŒä»£å…¥ã•ã‚Œã¾ã™.
                              !
                              ! Exception handling flag.
                              ! By default, when error occur in
                              ! this procedure, the program aborts.
                              ! If this *err* argument is given,
                              ! .true. is substituted to *err* and
                              ! the program does not abort.

  ! ä½œæ¥å¤‰æ•°
  ! Work variables
  !
  type(DC_CAL_DATE), pointer:: datep =>null()
  integer:: year  ! å¹´. Year.
  integer:: month ! æœˆ. Month.
  integer:: day   ! æ—¥. Day.
  integer:: hour  ! æ™‚. Hour.
  integer:: min   ! åˆ†. Minute.
  real(DP):: sec  ! ç§’. Second.
  character(TOKEN):: zone
                  ! UTC ã‹ã‚‰ã®æ™‚å·®. Time-zone.
  integer:: stat
  character(STRING):: cause_c
  character(*), parameter:: version = &
    & '$Name:  $' // &
    & '$Id: dccaldatecreate.f90,v 1.3 2010-09-24 07:07:31 morikawa Exp $'
  character(*), parameter:: subname = 'DCCalDateCreate2'
continue
  call BeginSub( subname, version )
  stat = DC_NOERR
  cause_c = ''

  ! ã‚ªãƒ–ã‚¸ã‚§ã‚¯ãƒˆã®ãƒã‚¤ãƒ³ã‚¿å‰²ä»˜
  ! Associate pointer of an object
  !
  if ( present( date ) ) then
    datep => date
  else
    datep => default_date
  end if

!!$  ! åˆæœŸè¨å®šã®ãƒã‚§ãƒƒã‚¯
!!$  ! Check initialization
!!$  !
!!$  if ( datep % initialized ) then
!!$    stat = DC_EALREADYINIT
!!$    cause_c = 'DC_CAL_DATE'
!!$    goto 999
!!$  end if

  ! æ—¥æ™‚ã‚’è¡¨ç¾ã—ãŸæ–‡å—åˆ—ã®è§£é‡ˆ
  ! Parse strings that express date and time
  !
  call DCCalDateParseStr( date_str, &           ! (in)
    & year, month, day, hour, min, sec, zone, & ! (out)
    & err = err )                               ! (out) optional
  if ( present(err) ) then
    if ( err ) then
      stat = DC_EBADDATE
      goto 999
    end if
  end if

  ! ã‚ªãƒ–ã‚¸ã‚§ã‚¯ãƒˆã®ä½œæˆ
  ! Create an object
  !
  call DCCalDateCreate( &
    & year, month, day, hour, min, sec, & ! (in)
    & datep, zone, err = err )            ! (out) optional
  if ( present(err) ) then
    if ( err ) then
      stat = DC_EBADDATE
      goto 999
    end if
  end if

  ! çµ‚äº†å‡¦ç†, ä¾‹å¤–å‡¦ç†
  ! Termination and Exception handling
  !
999 continue
  nullify( datep )
  call StoreError( stat, subname, err, cause_c )
  call EndSub( subname )
end subroutine DCCalDateCreate2