I have a fortran 90 function that is meant to parse a time stamp in the form day as %Y%m%d.%f where %f is fraction of a day /48 and return an array with year, month, day, fraction of day.
function parseTimeStamp (timeStamp)
implicit none
real, dimension(5) :: parseTimeStamp
real, intent(in) :: timeStamp
real :: date, moment
integer :: intdate, day, month, year, t
date = floor(timeStamp) ! remove the part days
parseTimeStamp(4) = timeStamp - date ! save the part days
intdate = int(date)
day = mod(intdate,100); intdate = intdate / 100
month = mod(intdate,100); intdate = intdate / 100
year = intdate
parseTimeStamp(1) = real(year)
parseTimeStamp(2) = real(month)
parseTimeStamp(3) = real(day)
end function parseTimeStamp
The issue is the output shows fraction of the day always at 0. When printing the timestamp (!print *, timeStamp) I get the date without fraction of the day 48 times before rolling over to the next day, even when I know with 100% certainty the data being read contains the proper fraction.
ex: I am getting
20220101.0 20220101.0 20220101.0 .... 20220102.0 20220102.0 ...
instead of
20220101.0 20220101.02083 20220101.04167 .... 20220102.0 20220102.02083 ...
I've tried using several different input files and have confirmed that the input files contain the part day data.
I think you would be better creating a user-defined type to hold your date and time variables than to try to return an array. Year, month and day are more naturally whole numbers (integer type). If you want higher precision use kind=real64 from iso_fortran_env (worth looking up: it has other goodies in that make codes portable).
program test
use iso_fortran_env
implicit none
integer y, m, d ! year, month, day
real(real64) f ! fraction of a day
call parseTimeStamp( "20220101.02083", y, m, d, f )
write( *, "( 3(a, ': ', i0, :, / ) )" ) "year", y, "month", m, "day", d
write( *, "( a, ': ', f7.5 )" ) "fraction", f
contains
subroutine parseTimeStamp( dateTime, year, month, day, dayfraction )
character(len=*), intent(in) :: dateTime
integer, intent(out) :: year, month, day
real(real64), intent(out) :: dayfraction
real(real64) temp
! *** TO DO *** check that timestamp is well formed before anything else
read( dateTime(1:4), * ) year
read( dateTime(5:6), * ) month
read( dateTime(7: ), * ) temp
day = temp
dayfraction = temp - day
end subroutine parseTimeStamp
end program test
year: 2022
month: 1
day: 1
fraction: 0.02083
If you want to go with a user-defined type then you can return that from a function:
module timemod
use iso_fortran_env
implicit none
type DTime
integer year
integer month
integer day
real(real64) fraction ! fraction of a day
end type DTime
contains
type(DTime) function parseTimeStamp( dateStamp ) result( res )
character(len=*), intent(in) :: dateStamp
real(real64) temp
read( dateStamp(1:4), * ) res%year
read( dateStamp(5:6), * ) res%month
read( dateStamp(7: ), * ) temp
res%day = temp
res%fraction = temp - res%day
end function parseTimeStamp
end module timemod
!=======================================================================
program test
use iso_fortran_env
use timemod
implicit none
write( *, "( 3( i0, / ), f7.5 )" ) parseTimeStamp( "20220101.02083" )
end program test