subroutine cdaten(cdate,ndate,error)
  use gbl_message
  use gkernel_interfaces
  use astro_interfaces, except_this=>cdaten
  !---------------------------------------------------------------------
  ! @ public
  !  Convert the date '01-JAN-1984' in integers for year, month, and day
  !---------------------------------------------------------------------
  character(len=*), intent(in)    :: cdate     ! String date
  integer(kind=4),  intent(out)   :: ndate(3)  ! Integer values
  logical,          intent(inout) :: error     ! Logical error flag
  ! Local
  character(len=40) :: kdate
  character(len=3) :: m
  integer(kind=4) :: id, iy, im, idate(7), i, idx1, idx2, iend
  ! Data
  character(len=3), parameter :: cm(0:12) = (/ '***','JAN','FEB','MAR',  &
    'APR','MAY','JUN','JUL','AUG','SEP','OCT','NOV','DEC' /)
  integer(kind=4), parameter :: cd(0:12) = (/0,31,29,31,30,31,30,31,31, 30,31,30,31/)
  !
  kdate = cdate
  call sic_upper(kdate)
  iend = lenc(kdate)
  call sic_blanc(kdate, iend)
  if (kdate(1:1) .eq. '*') then
    call utc(idate)
    do i=1, 3
      ndate(i) = idate(i)
    enddo
    return
  endif
  do i=1, iend
    if ((kdate(i:i).lt.'0' .and. kdate(i:i).ne.' ') .or. (kdate(i:i).gt.'9'  &
        .and. kdate(i:i).lt.'A') .or. kdate(i:i).gt.'Z') then
      kdate(i:i) = '-'
    endif
  enddo
  idx1 = index(kdate,'-')
  if (idx1 .le. 1) then
    goto 900
  else
    read(kdate(1:idx1-1),*,err=900) id
    idx2 = idx1 + index(kdate(idx1+1:iend),'-')
    if (idx2.le.idx1+1 .or. idx2.eq.iend) then
      goto 900
    else
      m = kdate(idx1+1:idx2-1)
      do im=1,12
        if (cm(im).eq.m) then
          goto 100
        endif
      enddo
      read(kdate(idx1+1:idx2-1),*,err=900) im
      100         read(kdate(idx2+1:iend),*,err=900) iy
    endif
    if (id.gt.cd(im)) goto 900
  endif
  ndate(1) = iy
  ndate(2) = im
  ndate(3) = id
  return
  !
  ! Wrong date
900  call astro_message(seve%e,'CDATEN','Date conversion error')
  error = .true.
  return
end subroutine cdaten
!
subroutine ndatec(ndate,cdate,error)
  use gbl_message
  use astro_interfaces, except_this=>ndatec
  !------------------------------------------------------------------------
  ! @ private
  !  Convert the integers for year, month, and day into date '01-JAN-1984'
  !------------------------------------------------------------------------
  integer(kind=4),  intent(in)    :: ndate(3)  !
  character(len=*), intent(out)   :: cdate     !
  logical,          intent(inout) :: error     !
  ! Local
  integer(kind=4) :: ier
  character(len=3), parameter :: cm(0:12) = (/ '***','JAN','FEB','MAR',  &
    'APR','MAY','JUN','JUL','AUG','SEP','OCT','NOV','DEC' /)
  !
  write(cdate,1001,iostat=ier) ndate(3), cm(ndate(2)), ndate(1)
  if (ier.ne.0) then
    call astro_message(seve%e,'NDATEC','Date conversion error')
    error = .true.
    return
  endif
  !
1001  format(i2.2,'-',a3,'-',i4.4)
end subroutine ndatec
!
subroutine ctimen(ctime,ntime,error)
  use gbl_message
  use gkernel_interfaces
  use astro_interfaces, except_this=>ctimen
  !---------------------------------------------------------------------
  ! @ public
  ! Converts the TIME '12:34:56.1234' in integers for Hours, Minutes,
  ! Seconds, and milliSeconds
  !---------------------------------------------------------------------
  character(len=*), intent(in)    :: ctime     !
  integer(kind=4),  intent(out)   :: ntime(4)  !
  logical,          intent(inout) :: error     ! Logical error flag
  ! Local
  integer(kind=4) :: i, ndate(7), ltime
  real(kind=8) :: tt
  character(len=32) :: chain
  !
  ltime = len_trim(ctime)
  if (ctime(1:ltime).eq.'*') then
    call utc(ndate)            ! get current time
    do i = 1, 4
      ntime(i) = ndate(i+3)
    enddo
    return
  endif
  call sic_sexa (ctime,ltime,tt,error) ! TT in hours
  if (error) then
    call astro_message(seve%e,'CTIMEN','TIME conversion error')
    return
  endif
  if (tt.lt.0 .or. tt.gt.24d0) then
    write(chain,*) tt
    call astro_message(seve%e,'CTIMEN','Invalid time '//ctime(1:ltime)//' = '//chain)
    return
  endif
  ntime(1) = tt
  tt = (tt-ntime(1)) * 60.d0
  ntime(2) = tt
  tt = (tt-ntime(2)) * 60.d0
  ntime(3) = tt
  ntime(4) = (tt - ntime(3)) * 1000.d0
end subroutine ctimen
  !
subroutine ntimec(ntime,ctime,error)
  use gbl_message
  use astro_interfaces, except_this=>ntimec
  !---------------------------------------------------------------------
  ! @ private
  ! Converts the integers for Hours, Minutes, Seconds, milliSeconds to
  ! formatted TIME
  !---------------------------------------------------------------------
  character(len=*), intent(out)   :: ctime     !
  integer(kind=4),  intent(in)    :: ntime(4)  !
  logical,          intent(inout) :: error     !
  ! Local
  integer(kind=4) :: ier
  !
  write(ctime,1001,iostat=ier) ntime
  if (ier.ne.0) then
    call astro_message(seve%e,'NTIMEC','TIME conversion error')
    error = .true.
    return
  endif
1001  format(i2.2,':',i2.2,':',i2.2,'.',i3.3)
end subroutine ntimec
!
subroutine utc(date)
  use gbl_message
  use astro_interfaces, except_this=>utc
  !---------------------------------------------------------------------
  ! @ public
  !  Lecture de l'heure du systeme par appel des routines systeme
  ! SIC_DATE en sortie : DATE date gregorienne (year, month, day, hour,
  ! minute, second)
  !---------------------------------------------------------------------
  integer(kind=4), intent(out) :: date(7)  !
  ! Local
  character(len=*), parameter :: rname='UTC'
  logical :: error
  character(len=30) :: date_chain
  !
  date(:) = 0
  call sic_date(date_chain)
  !
  error = .false.
  call cdaten (date_chain,date(1:3),error)
  if (error)  goto 10
  call ctimen (date_chain(13:),date(4:7),error)
  if (error)  goto 10
  !
  return
  !
10 continue
  call astro_message(seve%e,rname,'Error decoding '''//trim(date_chain)//'''')
end subroutine utc
!
subroutine jdate_to_datetime(jdate,datetime,error)
  use astro_interfaces, except_this=>jdate_to_datetime
  !---------------------------------------------------------------------
  ! @ private
  ! Convert input Julian date to Astro's specific date-time formatted
  ! string e.g.:
  !    18-JAN-2018 11:03:33.400
  ! At least 24 characters are needed for the full output string.
  ! However, shorter strings are accepted. Result will be truncated,
  ! this may be useful to get e.g. the leading date part.
  !---------------------------------------------------------------------
  real(kind=8),     intent(in)    :: jdate     !
  character(len=*), intent(out)   :: datetime  !
  logical,          intent(inout) :: error     ! Logical error flag
  ! Local
  integer(kind=4) :: code(7),nd
  character(len=32) :: chain
  !
  ! Split date into 7 integers
  call jjdate(jdate,code)
  !
  ! Date part
  call ndatec(code(1:3),chain,error)
  if (error)  return
  nd = len_trim(chain)
  ! call sic_blanc(chain,nd)  ! Is this useful?
  !
  ! Time part
  call ntimec(code(4:7),chain(nd+2:),error)
  if (error)  return
  ! nt = len_trim(chain)
  ! call sic_blanc(chain,nt)  ! Is this useful?
  !
  datetime = chain  ! Copy/truncate here
  !
end subroutine jdate_to_datetime
