!== ã‚¿ã‚¤ãƒ ã‚¾ãƒ¼ãƒ³ã«é–¢ã™ã‚‹æ‰‹ç¶šã
!
! Authors::   Yasuhiro MORIKAWA
! Version::   $Id: dcdatetimezone.f90,v 1.2 2009-05-25 10:01:34 morikawa Exp $
! Tag Name::  $Name:  $
! Copyright:: Copyright (C) GFD Dennou Club, 2000-2005. All rights reserved.
! License::   See COPYRIGHT[link:../../COPYRIGHT]
!
! ã“ã®ãƒ•ã‚¡ã‚¤ãƒ«ã§æä¾›ã•ã‚Œã‚‹æ‰‹ç¶šãç¾¤ã¯ dc_date ãƒ¢ã‚¸ãƒ¥ãƒ¼ãƒ«ã«ã¦æä¾›ã•ã‚Œã¾ã™ã€‚
!

subroutine DCDateTimeSetZone(time, zone, err)
  !
  ! å¼•æ•° *time* ã®ã‚¿ã‚¤ãƒ ã‚¾ãƒ¼ãƒ³ã‚’ *zone* ã¸ã¨å¤‰æ›´ã—ã¾ã™.
  ! å®Ÿè³ªçš„ãªæ—¥æ™‚ã¯å¤‰æ›´ã—ã¾ã›ã‚“.
  !
  ! å¼•æ•° *zone* ã«ä¸é©åˆ‡ãªå€¤ãŒä¸Žãˆã‚‰ã‚ŒãŸå ´åˆ,
  ! ã‚¨ãƒ©ãƒ¼ã‚’ç™ºç”Ÿã•ã›ã¾ã™.
  ! å¼•æ•° *err* ã‚’ä¸Žãˆã¦ã„ã‚‹å ´åˆã«ã¯ *err* ã« .true. ãŒè¿”ã‚Š,
  ! ãƒ—ãƒã‚°ãƒ©ãƒ ã¯ç¶šè¡Œã—ã¾ã™.
  !
  use dc_types,      only: STRING
  use dc_date_types, only: DC_DATETIME, DC_DIFFTIME
  use dc_date_generic, only: ValidZone, ZoneToDiff, toChar, Eval, &
    & operator(-), operator(+)
  use dc_error, only: StoreError, DC_EBADTIMEZONE, DC_NOERR
  use dc_message, only: MessageNotify
  use dc_trace, only: BeginSub, EndSub
  use dc_string, only: StoI
  implicit none
  type(DC_DATETIME), intent(inout):: time
  character(*), intent(in):: zone
  logical, intent(out), optional:: err
  type(DC_DIFFTIME):: diff, diff_in
  integer :: stat
  character(STRING) :: zone_in, cause_c
  character(*), parameter :: subname = 'DCDateTimeSetZone'
continue
  call BeginSub(subname, 'time=%c, zone=%c', &
    & c1=trim(toChar(time)), c2=trim(zone))
  stat = DC_NOERR
  cause_c = ''

  if (.not. ValidZone(zone)) then
    stat = DC_EBADTIMEZONE
    cause_c = zone
    if (present(err)) then
      call MessageNotify('W', subname, &
        & 'zone=<%c> is invalid.', &
        & c1=trim(zone))
    else
      goto 999
    end if
  end if

  call Eval(time, zone = zone_in)
  diff_in = ZoneToDiff(zone_in)
  diff = ZoneToDiff(zone)

  time = time + (diff_in - diff)
  time % zone = zone

999 continue
  call StoreError(stat, subname, err, cause_c)
  call EndSub(subname, 'time=%c', &
    & c1=trim(toChar(time)))
end subroutine DCDateTimeSetZone

function DCDateTimeZoneToDiff(zone) result(diff)
  !
  ! ä¸Žãˆã‚‰ã‚Œã‚‹ã‚¿ã‚¤ãƒ ã‚¾ãƒ¼ãƒ³ã‚’ dc_date_types#DC_DIFFTIME å¤‰æ•°ã¸ã¨
  ! å¤‰æ›ã—ã¦è¿”ã—ã¾ã™. ã‚¿ã‚¤ãƒ ã‚¾ãƒ¼ãƒ³ã®è¡¨è¨˜ãŒç„¡åŠ¹ãªå ´åˆã¯ '+00:00'
  ! ãŒä¸Žãˆã‚‰ã‚ŒãŸã¨è§£é‡ˆã—ã¾ã™.
  !
  use dc_date_types, only: DC_DIFFTIME
  use dc_date_generic, only: ValidZone, DCDiffTimeCreate
  use dc_string, only: StoI
  implicit none
  type(DC_DIFFTIME):: diff
  character(*), intent(in):: zone
  integer:: hour, min, sgn
continue
  if (.not. ValidZone(zone)) then
    call DCDiffTimeCreate(diff)
  else
    if (zone(1:1) == '-') then
      sgn = 1
    else
      sgn = -1
    end if
    hour = StoI(zone(2:3))
    min = StoI(zone(5:6))
    call DCDiffTimeCreate(diff, hour = hour * sgn, min = min * sgn)
  end if
end function DCDateTimeZoneToDiff

function DCDateTimeValidZone(zone) result(result)
  !
  ! ä¸Žãˆã‚‰ã‚Œã‚‹ã‚¿ã‚¤ãƒ ã‚¾ãƒ¼ãƒ³ã®è¡¨è¨˜ãŒæœ‰åŠ¹ã§ã‚ã‚Œã°
  ! .true. ã‚’, ãã‚Œä»¥å¤–ã®å ´åˆã¯ .false. ã‚’è¿”ã—ã¾ã™.
  !
  ! ã‚¿ã‚¤ãƒ ã‚¾ãƒ¼ãƒ³ã®è¡¨è¨˜ã¯ '+09:00' ã®ã‚ˆã†ã«, 1 æ–‡å—ç›®ãŒ '+' ã¾ãŸã¯ '-',
  ! 2ã€œ3, 5ã€œ6 æ–‡å—ç›®ãŒæ•°å€¤ã§, 4 æ–‡å—ç›®ãŒ ':' ã¨ãªã‚Šã¾ã™.
  !
  implicit none
  character(*), intent(in):: zone
  logical:: result
continue
  result = .false.
  if (len(zone) < 6) return
  if (verify(zone(1:1), '+-') /= 0) return
  if (verify(zone(2:3), '1234567890') /= 0) return
  if (verify(zone(5:6), '1234567890') /= 0) return
  if (zone(4:4) /= ':') return
  result = .true.
end function DCDateTimeValidZone