2 ! Author(s)/Contact(s):
7 ! Parameters: <Specify typical arguments passed>
9 ! <list file names and briefly describe the data they include>
11 ! <list file names and briefly describe the information they include>
14 ! <list exit condition or error codes returned >
15 ! If appropriate, descriptive troubleshooting instructions or
16 ! likely causes for failures could be mentioned here with the
17 ! appropriate error code
19 ! User controllable options: <if applicable>
21 module module_date_utils_nudging
22 use module_hydro_stop, only: HYDRO_stop
25 !===================================================================================================
26 ! Subroutine Name: geth_newdate
27 ! Author(s)/Contact(s):
28 ! Wei Yu? or NoahMP developers?
29 ! James L McCreight, jamesmcc><ucar><edu
31 ! Calculate a time difference from two time strings: idts=newdate-olddate
33 ! 7/22/15 -Header Created, JLM
35 ! call geth_newdate(ndate, odate, idt)
37 ! newdate : the resulting date: odate+idt
38 ! olddate : the start time for the sum: odate+id
39 ! idts : the time increment in seconds: odate+id
45 ! call hydro_stop("geth_newdate") is used.
46 ! User controllable options:
49 ! This routine was copied from ../LandModel/Utility_routines/module_date_utilities.F
50 ! There are some advantages to having a separate copy here, both compiling and
53 subroutine geth_newdate (ndate, odate, idt)
56 ! From old date ("YYYY-MM-DD HH:MM:SS.ffff" or "YYYYMMDDHHMMSSffff") and
57 ! delta-time, compute the new date.
59 ! on entry - odate - the old hdate.
60 ! idt - the change in time
62 ! on exit - ndate - the new hdate.
64 integer, intent(in) :: idt
65 character (len=*), intent(out) :: ndate
66 character (len=*), intent(in) :: odate
70 ! yrold - indicates the year associated with "odate"
71 ! moold - indicates the month associated with "odate"
72 ! dyold - indicates the day associated with "odate"
73 ! hrold - indicates the hour associated with "odate"
74 ! miold - indicates the minute associated with "odate"
75 ! scold - indicates the second associated with "odate"
77 ! yrnew - indicates the year associated with "ndate"
78 ! monew - indicates the month associated with "ndate"
79 ! dynew - indicates the day associated with "ndate"
80 ! hrnew - indicates the hour associated with "ndate"
81 ! minew - indicates the minute associated with "ndate"
82 ! scnew - indicates the second associated with "ndate"
84 ! mday - a list assigning the number of days in each month
87 ! nday - the integer number of days represented by "idt"
88 ! nhour - the integer number of hours in "idt" after taking out
90 ! nmin - the integer number of minutes in "idt" after taking out
91 ! all the whole days and whole hours.
92 ! nsec - the integer number of minutes in "idt" after taking out
93 ! all the whole days, whole hours, and whole minutes.
95 integer :: newlen, oldlen
96 integer :: yrnew, monew, dynew, hrnew, minew, scnew, frnew
97 integer :: yrold, moold, dyold, hrold, miold, scold, frold
98 integer :: nday, nhour, nmin, nsec, nfrac, i, ifrc
100 character (len=10) :: hfrc
101 character (len=1) :: sp
103 integer :: yrstart, yrend, mostart, moend, dystart, dyend
104 integer :: hrstart, hrend, mistart, miend, scstart, scend, frstart
106 integer, dimension(12) :: mday = (/31,28,31,30,31,30,31,31,30,31,30,31/)
108 ! Determine if odate is "YYYY-MM-DD_HH ... " or "YYYYMMDDHH...."
109 if (odate(5:5) == "-") then
115 ! Break down old hdate into parts
163 write(*,*) 'FATAL ERROR: geth_newdate: odd length: #'//trim(odate)//'#'
164 call hydro_stop("geth_newdate")
168 if (oldlen.ge.11) then
217 write(*,*) 'FATAL ERROR: geth_newdate: odd length: #'//trim(odate)//'#'
218 call hydro_stop("geth_newdate")
223 ! Use internal READ statements to convert the CHARACTER string
224 ! date into INTEGER components.
226 read(odate(yrstart:yrend), '(i4)') yrold
227 read(odate(mostart:moend), '(i2)') moold
228 read(odate(dystart:dyend), '(i2)') dyold
230 read(odate(hrstart:hrend),'(i2)') hrold
232 read(odate(mistart:miend),'(i2)') miold
234 read(odate(scstart:scend),'(i2)') scold
236 read(odate(frstart:oldlen),*) frold
242 ! Set the number of days in February for that year.
244 mday(2) = nfeb(yrold)
246 ! Check that ODATE makes sense.
250 ! Check that the month of ODATE makes sense.
252 if ((moold.gt.12).or.(moold.lt.1)) then
254 write(*,*) 'GETH_NEWDATE: Month of ODATE = ', moold
259 ! Check that the day of ODATE makes sense.
261 if ((dyold.gt.mday(moold)).or.(dyold.lt.1)) then
263 write(*,*) 'GETH_NEWDATE: Day of ODATE = ', dyold
268 ! Check that the hour of ODATE makes sense.
270 if ((hrold.gt.23).or.(hrold.lt.0)) then
272 write(*,*) 'GETH_NEWDATE: Hour of ODATE = ', hrold
277 ! Check that the minute of ODATE makes sense.
279 if ((miold.gt.59).or.(miold.lt.0)) then
281 write(*,*) 'GETH_NEWDATE: Minute of ODATE = ', miold
286 ! Check that the second of ODATE makes sense.
288 if ((scold.gt.59).or.(scold.lt.0)) then
290 write(*,*) 'GETH_NEWDATE: Second of ODATE = ', scold
295 ! Check that the fractional part of ODATE makes sense.
300 write(*,*) 'FATAL ERROR: Crazy ODATE: ', odate(1:oldlen), oldlen
305 ! Date Checks are completed. Continue.
308 ! Compute the number of days, hours, minutes, and seconds in idt
310 if (units.ge.5) then !idt should be in fractions of seconds
311 ifrc = oldlen-(frstart)+1
313 nday = abs(idt)/(86400*ifrc)
314 nhour = mod(abs(idt),86400*ifrc)/(3600*ifrc)
315 nmin = mod(abs(idt),3600*ifrc)/(60*ifrc)
316 nsec = mod(abs(idt),60*ifrc)/(ifrc)
317 nfrac = mod(abs(idt), ifrc)
318 else if (units.eq.4) then !idt should be in seconds
320 nday = abs(idt)/86400 ! integer number of days in delta-time
321 nhour = mod(abs(idt),86400)/3600
322 nmin = mod(abs(idt),3600)/60
323 nsec = mod(abs(idt),60)
325 else if (units.eq.3) then !idt should be in minutes
327 nday = abs(idt)/1440 ! integer number of days in delta-time
328 nhour = mod(abs(idt),1440)/60
329 nmin = mod(abs(idt),60)
332 else if (units.eq.2) then !idt should be in hours
334 nday = abs(idt)/24 ! integer number of days in delta-time
335 nhour = mod(abs(idt),24)
339 else if (units.eq.1) then !idt should be in days
341 nday = abs(idt) ! integer number of days in delta-time
348 write(*,'(''GETH_NEWDATE: Strange length for ODATE: '', i3)') &
350 write(*,*) '#'//odate(1:oldlen)//'#'
351 call hydro_stop("geth_newdate")
357 frnew = frold + nfrac
358 if (frnew.ge.ifrc) then
364 if (scnew .ge. 60) then
370 if (minew .ge. 60) then
375 hrnew = hrold + nhour
376 if (hrnew .ge. 24) then
386 if (dynew.gt.mday(monew)) then
387 dynew = dynew - mday(monew)
389 if (monew .gt. 12) then
392 ! If the year changes, recompute the number of days in February
393 mday(2) = nfeb(yrnew)
398 else if (idt.lt.0) then
400 frnew = frold - nfrac
401 if (frnew .lt. 0) then
407 if (scnew .lt. 00) then
413 if (minew .lt. 00) then
418 hrnew = hrold - nhour
419 if (hrnew .lt. 00) then
434 ! If the year changes, recompute the number of days in February
435 mday(2) = nfeb(yrnew)
442 ! Now construct the new mdate
448 if (newlen.gt.frstart) then
449 write(ndate(1:scend),19) yrnew, monew, dynew, hrnew, minew, scnew
450 write(hfrc,'(i10)') frnew+1000000000
451 ndate = ndate(1:scend)//'.'//hfrc(31-newlen:10)
453 else if (newlen.eq.scend) then
454 write(ndate(1:scend),19) yrnew, monew, dynew, hrnew, minew, scnew
455 19 format(i4,'-',i2.2,'-',i2.2,'_',i2.2,':',i2.2,':',i2.2)
457 else if (newlen.eq.miend) then
458 write(ndate,16) yrnew, monew, dynew, hrnew, minew
459 16 format(i4,'-',i2.2,'-',i2.2,'_',i2.2,':',i2.2)
461 else if (newlen.eq.hrend) then
462 write(ndate,13) yrnew, monew, dynew, hrnew
463 13 format(i4,'-',i2.2,'-',i2.2,'_',i2.2)
465 else if (newlen.eq.dyend) then
466 write(ndate,10) yrnew, monew, dynew
467 10 format(i4,'-',i2.2,'-',i2.2)
473 if (newlen.gt.frstart) then
474 write(ndate(1:scend),119) yrnew, monew, dynew, hrnew, minew, scnew
475 write(hfrc,'(i10)') frnew+1000000000
476 ndate = ndate(1:scend)//'.'//hfrc(31-newlen:10)
478 else if (newlen.eq.scend) then
479 write(ndate(1:scend),119) yrnew, monew, dynew, hrnew, minew, scnew
480 119 format(i4,i2.2,i2.2,i2.2,i2.2,i2.2)
482 else if (newlen.eq.miend) then
483 write(ndate,116) yrnew, monew, dynew, hrnew, minew
484 116 format(i4,i2.2,i2.2,i2.2,i2.2)
486 else if (newlen.eq.hrend) then
487 write(ndate,113) yrnew, monew, dynew, hrnew
488 113 format(i4,i2.2,i2.2,i2.2)
490 else if (newlen.eq.dyend) then
491 write(ndate,110) yrnew, monew, dynew
492 110 format(i4,i2.2,i2.2)
498 if (punct .and. (oldlen.ge.11) .and. (newlen.ge.11)) ndate(11:11) = sp
500 end subroutine geth_newdate
504 !===================================================================================================
505 ! Subroutine Name: geth_idts
506 ! Author(s)/Contact(s):
507 ! Wei Yu? or NoahMP developers?
508 ! James L McCreight, jamesmcc><ucar><edu
510 ! Calculate a time difference from two time strings: idts=newdate-olddate
512 ! 7/22/15 -Header Created, JLM
514 ! call geth_idts(newdate, olddate, idt)
516 ! newdate : first date in difference (newdate-olddate).
517 ! olddate : second date in difference (newdate-olddate).
518 ! idts : difference with units dependent on input resolution.
524 ! Currently incomplete error handling.
525 ! User controllable options:
528 ! This routine was copied from ../LandModel/Utility_routines/module_date_utilities.F
529 ! There are some advantages to having a separate copy here, both compiling and
531 subroutine geth_idts(newdate, olddate, idt)
535 ! From 2 input mdates ('YYYY-MM-DD HH:MM:SS.ffff'),
536 ! compute the time difference.
537 ! on entry - newdate - the new hdate.
538 ! olddate - the old hdate.
539 ! on exit - idt - the change in time.
540 ! Units depend on length of date strings.
542 character (len=*) , intent(in) :: newdate, olddate
543 integer , intent(out) :: idt
547 ! yrnew - indicates the year associated with "ndate"
548 ! yrold - indicates the year associated with "odate"
549 ! monew - indicates the month associated with "ndate"
550 ! moold - indicates the month associated with "odate"
551 ! dynew - indicates the day associated with "ndate"
552 ! dyold - indicates the day associated with "odate"
553 ! hrnew - indicates the hour associated with "ndate"
554 ! hrold - indicates the hour associated with "odate"
555 ! minew - indicates the minute associated with "ndate"
556 ! miold - indicates the minute associated with "odate"
557 ! scnew - indicates the second associated with "ndate"
558 ! scold - indicates the second associated with "odate"
560 ! mday - a list assigning the number of days in each month
562 ! ndate, odate: local values of newdate and olddate
563 character(len=24) :: ndate, odate
565 integer :: oldlen, newlen
566 integer :: yrnew, monew, dynew, hrnew, minew, scnew, frnew
567 integer :: yrold, moold, dyold, hrold, miold, scold, frold
568 integer :: i, newdys, olddys
569 logical :: npass, opass
572 integer, dimension(12) :: mday = (/31,28,31,30,31,30,31,31,30,31,30,31/)
574 integer :: yrstart, yrend, mostart, moend, dystart, dyend
575 integer :: hrstart, hrend, mistart, miend, scstart, scend, frstart
578 oldlen = len(olddate)
579 newlen = len(newdate)
580 if (newlen.ne.oldlen) then
582 write(*,'("GETH_IDTS: NEWLEN /= OLDLEN: ", A, 3x, A)') newdate(1:newlen), olddate(1:oldlen)
583 call hydro_stop("geth_newdate")
587 if (olddate.gt.newdate) then
602 ! Break down old hdate into parts
604 ! Determine if olddate is punctuated or not
605 if (odate(5:5) == "-") then
607 if (ndate(5:5) /= "-") then
609 write(*,'("GETH_IDTS: Dates appear to be different formats: ", A, 3x, A)') &
610 ndate(1:newlen), odate(1:oldlen)
611 call hydro_stop("geth_idts utils_nudging -1")
616 if (ndate(5:5) == "-") then
618 write(*,'("GETH_IDTS: Dates appear to be different formats: ", A, 3x, A)') &
619 ndate(1:newlen), odate(1:oldlen)
620 call hydro_stop("geth_idts utils_nudging 0")
666 write(*,*) 'ERROR: geth_idts: odd length: #'//trim(odate)//'#'
667 call hydro_stop("geth_idts utils_nudging 1")
713 write(*,*) 'ERROR: geth_idts: odd length: #'//trim(odate)//'#'
714 call hydro_stop("geth_idts nudging_utils 2")
725 read(odate(yrstart:yrend), '(i4)') yrold
726 read(odate(mostart:moend), '(i2)') moold
727 read(odate(dystart:dyend), '(i2)') dyold
729 read(odate(hrstart:hrend),'(i2)') hrold
731 read(odate(mistart:miend),'(i2)') miold
733 read(odate(scstart:scend),'(i2)') scold
735 read(odate(frstart:oldlen),*) frold
741 ! Break down new hdate into parts
748 read(ndate(yrstart:yrend), '(i4)') yrnew
749 read(ndate(mostart:moend), '(i2)') monew
750 read(ndate(dystart:dyend), '(i2)') dynew
752 read(ndate(hrstart:hrend),'(i2)') hrnew
754 read(ndate(mistart:miend),'(i2)') minew
756 read(ndate(scstart:scend),'(i2)') scnew
758 read(ndate(frstart:newlen),*) frnew
764 ! Check that the dates make sense.
769 ! Check that the month of NDATE makes sense.
771 if ((monew.gt.12).or.(monew.lt.1)) then
773 write(*,*) 'GETH_IDTS: Month of NDATE = ', monew
778 ! Check that the month of ODATE makes sense.
780 if ((moold.gt.12).or.(moold.lt.1)) then
782 print*, 'GETH_IDTS: Month of ODATE = ', moold
787 ! Check that the day of NDATE makes sense.
790 ! ...... For all months but February
791 if ((dynew.gt.mday(monew)).or.(dynew.lt.1)) then
793 print*, 'GETH_IDTS: Day of NDATE = ', dynew
797 else if (monew.eq.2) then
798 ! ...... For February
799 if ((dynew > nfeb(yrnew)).or.(dynew < 1)) then
801 print*, 'GETH_IDTS: Day of NDATE = ', dynew
807 ! Check that the day of ODATE makes sense.
810 ! ...... For all months but February
811 if ((dyold.gt.mday(moold)).or.(dyold.lt.1)) then
813 print*, 'GETH_IDTS: Day of ODATE = ', dyold
817 else if (moold.eq.2) then
818 ! ....... For February
819 if ((dyold > nfeb(yrold)).or.(dyold < 1)) then
821 print*, 'GETH_IDTS: Day of ODATE = ', dyold
827 ! Check that the hour of NDATE makes sense.
829 if ((hrnew.gt.23).or.(hrnew.lt.0)) then
831 print*, 'GETH_IDTS: Hour of NDATE = ', hrnew
836 ! Check that the hour of ODATE makes sense.
838 if ((hrold.gt.23).or.(hrold.lt.0)) then
840 print*, 'GETH_IDTS: Hour of ODATE = ', hrold
845 ! Check that the minute of NDATE makes sense.
847 if ((minew.gt.59).or.(minew.lt.0)) then
849 print*, 'GETH_IDTS: Minute of NDATE = ', minew
854 ! Check that the minute of ODATE makes sense.
856 if ((miold.gt.59).or.(miold.lt.0)) then
858 print*, 'GETH_IDTS: Minute of ODATE = ', miold
863 ! Check that the second of NDATE makes sense.
865 if ((scnew.gt.59).or.(scnew.lt.0)) then
867 print*, 'GETH_IDTS: SECOND of NDATE = ', scnew
872 ! Check that the second of ODATE makes sense.
874 if ((scold.gt.59).or.(scold.lt.0)) then
876 print*, 'GETH_IDTS: Second of ODATE = ', scold
881 if (.not. npass) then
883 print*, 'Screwy NDATE: ', ndate(1:newlen)
884 call hydro_stop("geth_idts nudging_utils 3")
888 if (.not. opass) then
890 print*, 'FATAL ERROR: Screwy ODATE: ', odate(1:oldlen)
891 call hydro_stop("geth_idts nudging_utils 4")
895 ! Date Checks are completed. Continue.
897 ! Compute number of days from 1 January ODATE, 00:00:00 until ndate
898 ! Compute number of hours from 1 January ODATE, 00:00:00 until ndate
899 ! Compute number of minutes from 1 January ODATE, 00:00:00 until ndate
902 do i = yrold, yrnew - 1
903 newdys = newdys + 337 + nfeb(i)
906 if (monew .gt. 1) then
907 mday(2) = nfeb(yrnew)
909 newdys = newdys + mday(i)
914 newdys = newdys + dynew - 1
916 ! Compute number of hours from 1 January ODATE, 00:00:00 until odate
917 ! Compute number of minutes from 1 January ODATE, 00:00:00 until odate
921 if (moold .gt. 1) then
922 mday(2) = nfeb(yrold)
924 olddys = olddys + mday(i)
929 olddys = olddys + dyold -1
931 ! Determine the time difference
933 idt = (newdys - olddys)
935 idt = idt*24 + (hrnew - hrold)
937 idt = idt*60 + (minew - miold)
939 idt = idt*60 + (scnew - scold)
941 ifrc = oldlen-(frstart-1)
943 idt = idt * ifrc + (frnew-frold)
949 if (timesign .eq. -1) then
953 end subroutine geth_idts
956 !===================================================================================================
957 ! Function Name: get_idts_elemental
958 ! Author(s)/Contact(s):
959 ! James L McCreight, jamesmcc><ucar><edu
961 ! get_idts on a vector.
964 ! 10/11/16 -Header Created, JLM
975 ! User controllable options:
978 !elemental subroutine geth_idts_elemental(newdate, olddate, idt)
983 !===================================================================================================
984 ! Function Name: nfeb
985 ! Author(s)/Contact(s):
986 ! Wei Yu? or NoahMP developers?
987 ! James L McCreight, jamesmcc><ucar><edu
991 ! 7/22/15 -Header Created, JLM
1002 ! User controllable options:
1005 ! This routine was copied from ../LandModel/Utility_routines/module_date_utilities.F
1006 ! There are some advantages to having a separate copy here, both compiling and
1009 integer function nfeb(year)
1011 ! Compute the number of days in February for the given year.
1014 integer, intent(in) :: year ! Four-digit year
1016 nfeb = 28 ! By default, February has 28 days ...
1017 if (mod(year,4).eq.0) then
1018 nfeb = 29 ! But every four years, it has 29 days ...
1019 if (mod(year,100).eq.0) then
1020 nfeb = 28 ! Except every 100 years, when it has 28 days ...
1021 if (mod(year,400).eq.0) then
1022 nfeb = 29 ! Except every 400 years, when it has 29 days ...
1023 if (mod(year,3600).eq.0) then
1024 nfeb = 28 ! Except every 3600 years, when it has 28 days.
1031 !===================================================================================================
1032 ! Function Name: nmdays
1033 ! Author(s)/Contact(s):
1034 ! Wei Yu? or NoahMP developers?
1035 ! James L McCreight, jamesmcc><ucar><edu
1039 ! 7/22/15 -Header Created, JLM
1050 ! User controllable options:
1053 ! This routine was copied from ../LandModel/Utility_routines/module_date_utilities.F
1054 ! There are some advantages to having a separate copy here, both compiling and
1057 integer function nmdays(hdate)
1059 ! Compute the number of days in the month of given date hdate.
1062 character(len=*), intent(in) :: hdate
1064 integer :: year, month
1065 integer, dimension(12), parameter :: ndays = (/ 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 /)
1067 read(hdate(1:7), '(I4,1x,I2)') year, month
1069 if (month == 2) then
1072 nmdays = ndays(month)
1076 !===================================================================================================
1077 ! Function Name: monthabbr_to_mm
1078 ! Author(s)/Contact(s):
1079 ! Wei Yu? or NoahMP developers?
1080 ! James L McCreight, jamesmcc><ucar><edu
1084 ! 7/22/15 -Header Created, JLM
1095 ! User controllable options:
1098 ! This routine was copied from ../LandModel/Utility_routines/module_date_utilities.F
1099 ! There are some advantages to having a separate copy here, both compiling and
1102 function monthabbr_to_mm(mon) result(mm)
1105 character(len=3), intent(in) :: mon
1109 if (mon == "Jan") then
1111 elseif (mon == "Feb") then
1113 elseif (mon == "Mar") then
1115 elseif (mon == "Apr") then
1117 elseif (mon == "May") then
1119 elseif (mon == "Jun") then
1121 elseif (mon == "Jul") then
1123 elseif (mon == "Aug") then
1125 elseif (mon == "Sep") then
1127 elseif (mon == "Oct") then
1129 elseif (mon == "Nov") then
1131 elseif (mon == "Dec") then
1135 write(*, '("Function monthabbr_to_mm: mon = <",A,">")') mon
1136 print*, "FATAL ERROR: Function monthabbr_to_mm: Unrecognized mon"
1137 call hydro_stop("monthabbr_to_mm")
1140 end function monthabbr_to_mm
1142 !===================================================================================================
1143 ! Subroutine Name: swap_date_format
1144 ! Author(s)/Contact(s):
1145 ! Wei Yu? or NoahMP developers?
1146 ! James L McCreight, jamesmcc><ucar><edu
1150 ! 7/22/15 -Header Created, JLM
1161 ! User controllable options:
1164 ! This routine was copied from ../LandModel/Utility_routines/module_date_utilities.F
1165 ! There are some advantages to having a separate copy here, both compiling and
1168 subroutine swap_date_format(indate, outdate)
1170 character(len=*), intent(in) :: indate
1171 character(len=*), intent(out) :: outdate
1175 if (indate(5:5) == "-") then
1179 outdate = indate(1:4)//indate(6:7)//indate(9:10)
1182 outdate = indate(1:4)//indate(6:7)//indate(9:10)//indate(12:13)
1185 outdate = indate(1:4)//indate(6:7)//indate(9:10)//indate(12:13)//indate(15:16)
1187 ! YYYY-MM-DD_HH:mm:ss
1188 outdate = indate(1:4)//indate(6:7)//indate(9:10)//indate(12:13)//indate(15:16)//&
1191 ! YYYY-MM-DD_HH:mm:ss.f[f[f[f]]]
1192 outdate = indate(1:4)//indate(6:7)//indate(9:10)//indate(12:13)//indate(15:16)//&
1193 indate(18:19)//indate(21:inlen)
1196 write(*,'("Unrecognized length: <", A,">")') indate
1197 call hydro_stop("swap_date_format")
1204 outdate = indate(1:4)//"-"//indate(5:6)//"-"//indate(7:8)
1207 outdate = indate(1:4)//"-"//indate(5:6)//"-"//indate(7:8)//"_"//&
1211 outdate = indate(1:4)//"-"//indate(5:6)//"-"//indate(7:8)//"_"//&
1212 indate(9:10)//":"//indate(11:12)
1215 outdate = indate(1:4)//"-"//indate(5:6)//"-"//indate(7:8)//"_"//&
1216 indate(9:10)//":"//indate(11:12)//":"//indate(13:14)
1218 ! YYYYMMDDHHmmssf[f[f[f]]]
1219 outdate = indate(1:4)//"-"//indate(5:6)//"-"//indate(7:8)//"_"//&
1220 indate(9:10)//":"//indate(11:12)//":"//indate(13:14)//"."//indate(15:inlen)
1223 write(*,'("FATAL ERROR: Unrecognized length: <", A,">")') indate
1224 call hydro_stop("swap_date_format")
1229 end subroutine swap_date_format
1231 !===================================================================================================
1232 ! Function Name: mm_to_monthabbr
1233 ! Author(s)/Contact(s):
1234 ! Wei Yu? or NoahMP developers?
1235 ! James L McCreight, jamesmcc><ucar><edu
1239 ! 7/22/15 -Header Created, JLM
1250 ! User controllable options:
1253 ! This routine was copied from ../LandModel/Utility_routines/module_date_utilities.F
1254 ! There are some advantages to having a separate copy here, both compiling and
1257 character(len=3) function mm_to_monthabbr(ii) result(mon)
1259 integer, intent(in) :: ii
1260 character(len=3), parameter, dimension(12) :: month = (/ &
1261 "Jan", "Feb", "Mar", "Apr", "May", "Jun", &
1262 "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" /)
1263 if (ii > 0 .and. ii < 13 ) then
1267 print*, "FATAL ERROR: mm_to_monthabbr"
1268 call hydro_stop("mm_to_monthabbr")
1271 end function mm_to_monthabbr
1273 !===================================================================================================
1274 ! Function Name: round_resolution_minute
1275 ! Author(s)/Contact(s):
1276 ! James L McCreight, jamesmcc><ucar><edu
1277 ! Abstract: Round a time to some time resolution specified in minutes:
1278 ! 1) the resolution evenly divides 60
1279 ! 2) the first time chunk in a hour is centered on 0 minutes and
1280 ! subesquent chunks are centered on N*resoluton (mod 60).
1282 ! 7/29/15 -Header Created, JLM
1293 ! User controllable options:
1295 ! Notes: Some tests:
1296 ! print*,round_resolution_minute('2003-02-01_01:00:00', 5)
1297 ! print*,round_resolution_minute('2003-02-01_01:02:29', 5)
1298 ! print*,round_resolution_minute('2003-02-01_01:02:30', 5)
1299 ! print*,round_resolution_minute('2003-02-01_01:57:29', 5)
1300 ! print*,round_resolution_minute('2003-02-01_01:57:30', 5)
1302 ! print*,round_resolution_minute('2003-02-01_01:00:00', 15)
1303 ! print*,round_resolution_minute('2003-02-01_01:07:29', 15)
1304 ! print*,round_resolution_minute('2003-02-01_01:07:30', 15)
1305 ! print*,round_resolution_minute('2003-02-01_01:52:29', 15)
1306 ! print*,round_resolution_minute('2003-02-01_01:52:30', 15)
1308 function round_resolution_minute(time, resolution)
1310 character(len=19) :: round_resolution_minute ! return value
1311 character(len=19), intent(in) :: time ! time to round
1312 integer :: resolution ! the time resolution in minutes
1315 real :: resolutionInv, theMinute, theSecond, resMin
1316 character(len=19) :: roundTime, timeCopy
1318 ! nearest defines a time resolution
1319 resolutionInv = 1./resolution
1320 !1234567890123456789
1321 !YYYY-MM-DD_HH:mm:ss
1322 read(time(15:16),*) theMinute
1323 read(time(18:19),*) theSecond
1324 theMinute = theMinute + (theSecond/60.)
1325 ! What fraction of the time resolution is the current time?
1326 resMin = (theMinute * resolutionInv)
1327 ! Round to the time resolution.
1328 ! nint doesnt document its rounding rule on gfortran! boo.
1329 if(resMin - floor(resMin) .ge. .5) resMin=ceiling(resMin)
1330 if(resMin - floor(resMin) .lt. .5) resMin=floor(resMin)
1331 ! Convert back to regular minutes.
1332 resMin = resMin / resolutionInv
1333 ! To get the exact right time, some floor/ceil operations are helpful.
1335 timeCopy(18:19) = '00' ! Floor of theMinute in string form
1336 ! nint is needed b/c resMin is real and often slightly off integer,
1337 ! and this is exacerbated by *60
1338 diffMin = (nint(resMin) - floor(theMinute))*60
1339 !print*, nint(resMin), floor(theMinute), timeCopy, diffMin
1340 call geth_newdate(round_resolution_minute, timeCopy, diffMin)
1342 end function round_resolution_minute
1346 end module module_date_utils_nudging