!= æ—¥æ™‚ã®æ–‡å—åˆ—ã®è§£é‡ˆ
!= Parse strings of date
!
! Authors::   Yasuhiro MORIKAWA
! Version::   $Id: dccaldateparsestr.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 DCCalDateParseStr1( date_str, &
  & year, month, day, hour, min, sec, zone, &
  & err )
  ! *date_str* ã§ä¸Žãˆã‚‰ã‚Œã‚‹æ—¥æ™‚å½¢å¼
  ! (gtool4 netCDF è¦ç´„ã€Œ5.5 æ—¥æ™‚å½¢å¼ã€ã«æº–æ‹ ) ã‚’è§£é‡ˆã—,
  ! *year* ã€œ *zone* ã«è¿”ã—ã¾ã™.
  !
  ! Parse strings of date (conformed to gtool4 netCDF Convention
  ! "5.5 Expression of date and time") specified as *date_str*,
  ! and return *year* -- *zone*.
  !

  use dc_regex, only: match
  use dc_message, only: MessageNotify
  use dc_string, only: LChar, StoI, StoD
  use dc_trace, only: BeginSub, EndSub, DbgMessage
  use dc_error, only: StoreError, DC_NOERR, DC_EALREADYINIT, DC_EBADDATE
  use dc_types, only: STRING, DP, TOKEN
  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.
  integer, intent(out):: year  ! å¹´. Year.
  integer, intent(out):: month ! æœˆ. Month.
  integer, intent(out):: day   ! æ—¥. Day.
  integer, intent(out):: hour  ! æ™‚. Hour.
  integer, intent(out):: min   ! åˆ†. Minute.
  real(DP), intent(out):: sec  ! ç§’. Second.
  character(*), intent(out):: 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
  !
  integer:: start, length
  character(STRING):: str1, str2
  character(TOKEN):: zone_pm, zone_hrs, zone_min
  integer:: stat
  character(STRING):: cause_c
  character(*), parameter:: subname = 'DCCalDateParseStr1'
continue
  call BeginSub( subname )
  stat = DC_NOERR
  cause_c = ''

  ! ä¸Žãˆã‚‰ã‚ŒãŸæ–‡å—åˆ—ãŒæ—¥æ™‚è¡¨ç¾ã¨ã—ã¦æœ‰åŠ¹ã‹ã©ã†ã‹ã‚’ãƒã‚§ãƒƒã‚¯
  ! Check validation of strings as an expression of date
  !
  call match( '[-]*#d+-#d+-#d+[#w#s]+#d+:#d+:#d+', date_str, & ! (in)
    &         start, length ) ! (out)

  if ( length > 0 ) then
    str1 = date_str(start:)
  else
    stat = DC_EBADDATE
    call MessageNotify('W', subname, &
      & 'date_str=<%c> is invalid expression as date.', &
      & c1 = trim(date_str) )
    goto 999
  end if

  ! å¹´ã®è§£é‡ˆ
  ! Parse year
  !
  call match( '^[-]*#d+-', str1, & ! (in)
    &         start, length ) ! (out)
  str2 = str1(start:start+length-2)
  str1 = str1(start+length:)
  year = StoI(str2)

  ! æœˆã®è§£é‡ˆ
  ! Parse month
  !
  call match( '^#d+-', str1, & ! (in)
    &         start, length ) ! (out)
  str2 = str1(start:start+length-2)
  str1 = str1(start+length:)
  month = StoI(str2)

  ! æ—¥ã®è§£é‡ˆ
  ! Parse day
  !
  call match( '^#d+[#w#s]', str1, & ! (in)
    &         start, length ) ! (out)
  str2 = str1(start:start+length-2)
  str1 = str1(start+length:)
  day = StoI(str2)

  ! æ™‚ã®è§£é‡ˆ
  ! Parse hour
  !
  call match( '#d+:', str1, & ! (in)
    &         start, length ) ! (out)
  str2 = str1(start:start+length-2)
  str1 = str1(start+length:)
  hour = StoI(str2)

  ! åˆ†ã®è§£é‡ˆ
  ! Parse minute
  !
  call match( '#d+:', str1, & ! (in)
    &         start, length ) ! (out)
  str2 = str1(start:start+length-2)
  str1 = str1(start+length:)
  min = StoI(str2)

  ! ç§’ã®è§£é‡ˆ
  ! Parse min
  !
  call match( '#d+', str1, & ! (in)
    &         start, length ) ! (out)
  str2 = str1(start:start+length-1)
  str1 = str1(start+length:)

  call match( '^#.#d+', str1, & ! (in)
    &         start, length ) ! (out)

  if ( length > 0 ) then
    str2 = trim(str2) // str1(start:start+length-1)
    str1 = str1(start+length:)
  end if
  sec = StoD(str2)

  ! UTC ã‹ã‚‰ã®æ™‚å·®ã®è§£é‡ˆ
  ! Parse time-zone difference
  !
  call match( '[#+-]#d+:#d+', str1, & ! (in)
    &         start, length ) ! (out)
  if ( length > 0 ) then
    zone_pm = str1(start:start)
    str1 = str1(start+1:start+length-1)

    call match( '^#d+:', str1, & ! (in)
      &         start, length ) ! (out)
    zone_hrs = str1(start:start+length-2)
    zone_min = str1(start+length:)
    zone = trim(zone_pm) // trim(zone_hrs) // ':' // trim(zone_min)
  else
    zone = ''
  end if

  call DbgMessage('year=<%d> month=<%d> day=<%d> hour=<%d> min=<%d> sec=<%f>' // &
    & ' zone=<%c>', &
    & i = (/year, month, day, hour, min/), d = (/sec/), &
    & c1 = trim(zone) )

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