1 #include <ESMF_TimeMgr.inc>
3 ! Factor so abs(Sn) < Sd and ensure that signs of S and Sn match.
4 ! Also, enforce consistency.
5 ! YR and MM fields are ignored.
6 SUBROUTINE normalize_basetime( basetime )
10 TYPE(ESMF_BaseTime), INTENT(INOUT) :: basetime
11 !PRINT *,'DEBUG: BEGIN normalize_basetime()'
12 ! Consistency check...
13 IF ( basetime%Sd < 0 ) THEN
14 CALL wrf_error_fatal( &
15 'normalize_basetime: denominator of seconds cannot be negative' )
17 IF ( ( basetime%Sd == 0 ) .AND. ( basetime%Sn .NE. 0 ) ) THEN
18 CALL wrf_error_fatal( &
19 'normalize_basetime: denominator of seconds cannot be zero when numerator is non-zero' )
21 ! factor so abs(Sn) < Sd
22 IF ( basetime%Sd > 0 ) THEN
23 IF ( ABS( basetime%Sn ) .GE. basetime%Sd ) THEN
24 !PRINT *,'DEBUG: normalize_basetime() A1: S,Sn,Sd = ',basetime%S,basetime%Sn,basetime%Sd
25 basetime%S = basetime%S + ( basetime%Sn / basetime%Sd )
26 basetime%Sn = mod( basetime%Sn, basetime%Sd )
27 !PRINT *,'DEBUG: normalize_basetime() A2: S,Sn,Sd = ',basetime%S,basetime%Sn,basetime%Sd
29 ! change sign of Sn if it does not match S
30 IF ( ( basetime%S > 0 ) .AND. ( basetime%Sn < 0 ) ) THEN
31 !PRINT *,'DEBUG: normalize_basetime() B1: S,Sn,Sd = ',basetime%S,basetime%Sn,basetime%Sd
32 basetime%S = basetime%S - 1_ESMF_KIND_I8
33 basetime%Sn = basetime%Sn + basetime%Sd
34 !PRINT *,'DEBUG: normalize_basetime() B2: S,Sn,Sd = ',basetime%S,basetime%Sn,basetime%Sd
36 IF ( ( basetime%S < 0 ) .AND. ( basetime%Sn > 0 ) ) THEN
37 !PRINT *,'DEBUG: normalize_basetime() C1: S,Sn,Sd = ',basetime%S,basetime%Sn,basetime%Sd
38 basetime%S = basetime%S + 1_ESMF_KIND_I8
39 basetime%Sn = basetime%Sn - basetime%Sd
40 !PRINT *,'DEBUG: normalize_basetime() C2: S,Sn,Sd = ',basetime%S,basetime%Sn,basetime%Sd
43 !PRINT *,'DEBUG: END normalize_basetime()'
44 END SUBROUTINE normalize_basetime
48 ! A normalized time has time%basetime >= 0, time%basetime less than the current
49 ! year expressed as a timeInterval, and time%YR can take any value
50 SUBROUTINE normalize_time( time )
55 TYPE(ESMF_Time), INTENT(INOUT) :: time
56 INTEGER(ESMF_KIND_I8) :: nsecondsinyear
58 TYPE(ESMF_BaseTime) :: cmptime, zerotime
62 ! first, normalize basetime
63 ! this will force abs(Sn) < Sd and ensure that signs of S and Sn match
64 CALL normalize_basetime( time%basetime )
66 !$$$ add tests for these edge cases
68 ! next, underflow negative seconds into YEARS
69 ! time%basetime must end up non-negative
70 !$$$ push this down into ESMF_BaseTime constructor
74 DO WHILE ( time%basetime < zerotime )
76 !$$$ push this down into ESMF_BaseTime constructor
77 cmptime%S = nsecondsinyear( time%YR )
80 time%basetime = time%basetime + cmptime
83 ! next, overflow seconds into YEARS
85 DO WHILE ( .NOT. done )
86 !$$$ push this down into ESMF_BaseTime constructor
87 cmptime%S = nsecondsinyear( time%YR )
90 IF ( time%basetime >= cmptime ) THEN
91 time%basetime = time%basetime - cmptime
97 END SUBROUTINE normalize_time
101 SUBROUTINE normalize_timeint( timeInt )
103 USE esmf_timeintervalmod
105 TYPE(ESMF_TimeInterval), INTENT(INOUT) :: timeInt
108 ! this will force abs(Sn) < Sd and ensure that signs of S and Sn match
109 ! YR and MM are ignored
110 CALL normalize_basetime( timeInt%basetime )
111 END SUBROUTINE normalize_timeint
116 FUNCTION signnormtimeint ( timeInt )
117 ! Compute the sign of a time interval.
118 ! YR and MM fields are *IGNORED*.
119 ! returns 1, 0, or -1 or exits if timeInt fields have inconsistent signs.
122 USE esmf_timeintervalmod
124 TYPE(ESMF_TimeInterval), INTENT(IN) :: timeInt
125 INTEGER :: signnormtimeint
126 LOGICAL :: positive, negative
131 ! Note that Sd is required to be non-negative. This is enforced in
132 ! normalize_timeint().
133 ! Note that Sn is required to be zero when Sd is zero. This is enforced
134 ! in normalize_timeint().
135 IF ( ( timeInt%basetime%S > 0 ) .OR. &
136 ( timeInt%basetime%Sn > 0 ) ) THEN
139 IF ( ( timeInt%basetime%S < 0 ) .OR. &
140 ( timeInt%basetime%Sn < 0 ) ) THEN
143 IF ( positive .AND. negative ) THEN
144 CALL wrf_error_fatal( &
145 'signnormtimeint: signs of fields cannot be mixed' )
146 ELSE IF ( positive ) THEN
148 ELSE IF ( negative ) THEN
151 END FUNCTION signnormtimeint
154 ! Exits with error message if timeInt is not normalized.
155 SUBROUTINE timeintchecknormalized( timeInt, msgstr )
156 USE esmf_timeintervalmod
158 TYPE(ESMF_TimeInterval), INTENT(IN) :: timeInt
159 CHARACTER(LEN=*), INTENT(IN) :: msgstr
161 CHARACTER(LEN=256) :: outstr
162 IF ( ( timeInt%YR /= 0 ) .OR. &
163 ( timeInt%MM /= 0 ) ) THEN
164 outstr = 'un-normalized TimeInterval not allowed: '//TRIM(msgstr)
165 CALL wrf_error_fatal( outstr )
167 END SUBROUTINE timeintchecknormalized
170 ! added from share/module_date_time in WRF.
171 FUNCTION nfeb ( year ) RESULT (num_days)
172 ! Compute the number of days in February for the given year
176 ! TBH: TODO: Replace this hack with run-time decision based on
177 ! TBH: TODO: passed-in calendar.
178 #ifdef NO_LEAP_CALENDAR
179 num_days = 28 ! By default, February has 28 days ...
181 num_days = 28 ! By default, February has 28 days ...
182 IF (MOD(year,4).eq.0) THEN
183 num_days = 29 ! But every four years, it has 29 days ...
184 IF (MOD(year,100).eq.0) THEN
185 num_days = 28 ! Except every 100 years, when it has 28 days ...
186 IF (MOD(year,400).eq.0) THEN
187 num_days = 29 ! Except every 400 years, when it has 29 days.
196 FUNCTION ndaysinyear ( year ) RESULT (num_diy)
197 ! Compute the number of days in the given year
199 INTEGER, INTENT(IN) :: year
207 IF ( nfeb( year ) .EQ. 29 ) THEN
213 END FUNCTION ndaysinyear
217 FUNCTION nsecondsinyear ( year ) RESULT (numseconds)
218 ! Compute the number of seconds in the given year
221 INTEGER, INTENT(IN) :: year
222 INTEGER(ESMF_KIND_I8) :: numseconds
223 INTEGER :: ndaysinyear
224 numseconds = SECONDS_PER_DAY * INT( ndaysinyear(year) , ESMF_KIND_I8 )
225 END FUNCTION nsecondsinyear
232 USE ESMF_CalendarMod, only : months_per_year, mday, daym, mdaycum, monthbdys, &
233 mdayleap, mdayleapcum, monthbdysleap, daymleap
238 !$$$ push this down into ESMF_BaseTime constructor
242 DO i = 1,MONTHS_PER_YEAR
247 mdaycum(i) = mdaycum(i-1) + mday(i)
248 !$$$ push this down into ESMF_BaseTime constructor
249 monthbdys(i)%S = SECONDS_PER_DAY * INT( mdaycum(i), ESMF_KIND_I8 )
255 !$$$ push this down into ESMF_BaseTime constructor
256 monthbdysleap(0)%S = 0
257 monthbdysleap(0)%Sn = 0
258 monthbdysleap(0)%Sd = 0
259 DO i = 1,MONTHS_PER_YEAR
264 mdayleapcum(i) = mdayleapcum(i-1) + mdayleap(i)
265 !$$$ push this down into ESMF_BaseTime constructor
266 monthbdysleap(i)%S = SECONDS_PER_DAY * INT( mdayleapcum(i), ESMF_KIND_I8 )
267 monthbdysleap(i)%Sn = 0
268 monthbdysleap(i)%Sd = 0
270 END SUBROUTINE initdaym
273 !$$$ useful, but not used at the moment...
274 SUBROUTINE compute_dayinyear(YR,MM,DD,dayinyear)
275 use ESMF_CalendarMod, only : mday
277 INTEGER, INTENT(IN) :: YR,MM,DD ! DD is day of month
278 INTEGER, INTENT(OUT) :: dayinyear
288 dayinyear = dayinyear + nfeb(YR)
290 dayinyear = dayinyear + mday(i)
293 dayinyear = dayinyear + DD
295 END SUBROUTINE compute_dayinyear
299 SUBROUTINE timegetmonth( time, MM )
303 USE ESMF_CalendarMod, only : MONTHS_PER_YEAR, monthbdys, monthbdysleap
305 TYPE(ESMF_Time), INTENT(IN) :: time
306 INTEGER, INTENT(OUT) :: MM
314 IF ( nfeb(time%YR) == 29 ) THEN
315 DO i = 1,MONTHS_PER_YEAR
316 IF ( ( time%basetime >= monthbdysleap(i-1) ) .AND. ( time%basetime < monthbdysleap(i) ) ) THEN
322 DO i = 1,MONTHS_PER_YEAR
323 IF ( ( time%basetime >= monthbdys(i-1) ) .AND. ( time%basetime < monthbdys(i) ) ) THEN
331 CALL wrf_error_fatal( 'timegetmonth: could not extract month of year from time' )
333 END SUBROUTINE timegetmonth
336 !$$$ may need to change dependencies in Makefile...
338 SUBROUTINE timegetdayofmonth( time, DD )
342 USE esmf_calendarmod, only : monthbdys, monthbdysleap
344 TYPE(ESMF_Time), INTENT(IN) :: time
345 INTEGER, INTENT(OUT) :: DD
349 TYPE(ESMF_BaseTime) :: tmpbasetime
351 tmpbasetime = time%basetime
353 CALL timegetmonth( time, MM )
354 IF ( nfeb(time%YR) == 29 ) THEN
355 tmpbasetime = time%basetime - monthbdysleap(MM-1)
357 tmpbasetime = time%basetime - monthbdys(MM-1)
360 DD = ( tmpbasetime%S / SECONDS_PER_DAY ) + 1
361 END SUBROUTINE timegetdayofmonth
364 ! Increment Time by number of seconds between start of year and start
367 ! Time is NOT normalized.
368 SUBROUTINE timeaddmonths( time, MM, ierr )
372 USE esmf_calendarmod, only : MONTHS_PER_YEAR, monthbdys, monthbdysleap
374 TYPE(ESMF_Time), INTENT(INOUT) :: time
375 INTEGER, INTENT(IN) :: MM
376 INTEGER, INTENT(OUT) :: ierr
380 ! PRINT *,'DEBUG: BEGIN timeaddmonths()'
382 ! time%basetime = time%basetime
384 IF ( ( MM < 1 ) .OR. ( MM > MONTHS_PER_YEAR ) ) THEN
387 IF ( nfeb(time%YR) == 29 ) THEN
388 time%basetime = time%basetime + monthbdysleap(MM-1)
390 time%basetime = time%basetime + monthbdys(MM-1)
394 END SUBROUTINE timeaddmonths
397 ! Increment Time by number of seconds in the current month.
398 ! Time is NOT normalized.
399 SUBROUTINE timeincmonth( time )
403 USE esmf_calendarmod, only : mday, mdayleap
405 TYPE(ESMF_Time), INTENT(INOUT) :: time
410 ! time%basetime%S = time%basetime%S
412 CALL timegetmonth( time, MM )
413 IF ( nfeb(time%YR) == 29 ) THEN
414 time%basetime%S = time%basetime%S + &
415 ( INT( mdayleap(MM), ESMF_KIND_I8 ) * SECONDS_PER_DAY )
417 time%basetime%S = time%basetime%S + &
418 ( INT( mday(MM), ESMF_KIND_I8 ) * SECONDS_PER_DAY )
421 END SUBROUTINE timeincmonth
425 ! Decrement Time by number of seconds in the previous month.
426 ! Time is NOT normalized.
427 SUBROUTINE timedecmonth( time )
431 USE esmf_calendarmod, only : mday, months_per_year, mdayleap
433 TYPE(ESMF_Time), INTENT(INOUT) :: time
438 ! time%basetime%S = time%basetime%S
440 CALL timegetmonth( time, MM ) ! current month, 1-12
441 ! find previous month
444 ! wrap around Jan -> Dec
447 IF ( nfeb(time%YR) == 29 ) THEN
448 time%basetime%S = time%basetime%S - &
449 ( INT( mdayleap(MM), ESMF_KIND_I8 ) * SECONDS_PER_DAY )
451 time%basetime%S = time%basetime%S - &
452 ( INT( mday(MM), ESMF_KIND_I8 ) * SECONDS_PER_DAY )
455 END SUBROUTINE timedecmonth
459 ! spaceship operator for Times
460 SUBROUTINE timecmp(time1, time2, retval )
465 INTEGER, INTENT(OUT) :: retval
468 TYPE(ESMF_Time), INTENT(IN) :: time1
469 TYPE(ESMF_Time), INTENT(IN) :: time2
470 IF ( time1%YR .GT. time2%YR ) THEN ; retval = 1 ; RETURN ; ENDIF
471 IF ( time1%YR .LT. time2%YR ) THEN ; retval = -1 ; RETURN ; ENDIF
472 CALL seccmp( time1%basetime%S, time1%basetime%Sn, time1%basetime%Sd, &
473 time2%basetime%S, time2%basetime%Sn, time2%basetime%Sd, &
475 END SUBROUTINE timecmp
479 ! spaceship operator for TimeIntervals
480 SUBROUTINE timeintcmp(timeint1, timeint2, retval )
483 USE esmf_timeintervalmod
485 INTEGER, INTENT(OUT) :: retval
488 TYPE(ESMF_TimeInterval), INTENT(IN) :: timeint1
489 TYPE(ESMF_TimeInterval), INTENT(IN) :: timeint2
490 CALL timeintchecknormalized( timeint1, 'timeintcmp arg1' )
491 CALL timeintchecknormalized( timeint2, 'timeintcmp arg2' )
492 CALL seccmp( timeint1%basetime%S, timeint1%basetime%Sn, &
493 timeint1%basetime%Sd, &
494 timeint2%basetime%S, timeint2%basetime%Sn, &
495 timeint2%basetime%Sd, retval )
496 END SUBROUTINE timeintcmp
500 ! spaceship operator for seconds + Sn/Sd
501 SUBROUTINE seccmp(S1, Sn1, Sd1, S2, Sn2, Sd2, retval )
504 INTEGER, INTENT(OUT) :: retval
507 INTEGER(ESMF_KIND_I8), INTENT(IN) :: S1, Sn1, Sd1
508 INTEGER(ESMF_KIND_I8), INTENT(IN) :: S2, Sn2, Sd2
510 INTEGER(ESMF_KIND_I8) :: lcd, n1, n2
514 if ( ( n1 .ne. 0 ) .or. ( n2 .ne. 0 ) ) then
515 CALL compute_lcd( Sd1, Sd2, lcd )
516 if ( Sd1 .ne. 0 ) n1 = n1 * ( lcd / Sd1 )
517 if ( Sd2 .ne. 0 ) n2 = n2 * ( lcd / Sd2 )
520 if ( S1 .GT. S2 ) retval = 1
521 if ( S1 .LT. S2 ) retval = -1
522 IF ( S1 .EQ. S2 ) THEN
523 IF (n1 .GT. n2) retval = 1
524 IF (n1 .LT. n2) retval = -1
525 IF (n1 .EQ. n2) retval = 0
527 END SUBROUTINE seccmp
530 SUBROUTINE c_esmc_basetimeeq (time1, time2, outflag)
537 USE esmf_timeintervalmod
540 logical, intent(OUT) :: outflag
541 type(ESMF_Time), intent(in) :: time1
542 type(ESMF_Time), intent(in) :: time2
544 CALL timecmp(time1,time2,res)
545 outflag = (res .EQ. 0)
546 END SUBROUTINE c_esmc_basetimeeq
547 SUBROUTINE c_esmc_basetimege(time1, time2, outflag)
554 USE esmf_timeintervalmod
556 logical, intent(OUT) :: outflag
557 type(ESMF_Time), intent(in) :: time1
558 type(ESMF_Time), intent(in) :: time2
560 CALL timecmp(time1,time2,res)
561 outflag = (res .EQ. 1 .OR. res .EQ. 0)
562 END SUBROUTINE c_esmc_basetimege
563 SUBROUTINE c_esmc_basetimegt(time1, time2, outflag)
570 USE esmf_timeintervalmod
573 logical, intent(OUT) :: outflag
574 type(ESMF_Time), intent(in) :: time1
575 type(ESMF_Time), intent(in) :: time2
577 CALL timecmp(time1,time2,res)
578 outflag = (res .EQ. 1)
579 END SUBROUTINE c_esmc_basetimegt
580 SUBROUTINE c_esmc_basetimele(time1, time2, outflag)
587 USE esmf_timeintervalmod
590 logical, intent(OUT) :: outflag
591 type(ESMF_Time), intent(in) :: time1
592 type(ESMF_Time), intent(in) :: time2
594 CALL timecmp(time1,time2,res)
595 outflag = (res .EQ. -1 .OR. res .EQ. 0)
596 END SUBROUTINE c_esmc_basetimele
597 SUBROUTINE c_esmc_basetimelt(time1, time2, outflag)
604 USE esmf_timeintervalmod
607 logical, intent(OUT) :: outflag
608 type(ESMF_Time), intent(in) :: time1
609 type(ESMF_Time), intent(in) :: time2
611 CALL timecmp(time1,time2,res)
612 outflag = (res .EQ. -1)
613 END SUBROUTINE c_esmc_basetimelt
614 SUBROUTINE c_esmc_basetimene(time1, time2, outflag)
621 USE esmf_timeintervalmod
624 logical, intent(OUT) :: outflag
625 type(ESMF_Time), intent(in) :: time1
626 type(ESMF_Time), intent(in) :: time2
628 CALL timecmp(time1,time2,res)
629 outflag = (res .NE. 0)
630 END SUBROUTINE c_esmc_basetimene
632 SUBROUTINE c_esmc_basetimeinteq(timeint1, timeint2, outflag)
633 USE esmf_timeintervalmod
635 LOGICAL, INTENT(OUT) :: outflag
636 TYPE(ESMF_TimeInterval), INTENT(IN) :: timeint1
637 TYPE(ESMF_TimeInterval), INTENT(IN) :: timeint2
639 CALL timeintcmp(timeint1,timeint2,res)
640 outflag = (res .EQ. 0)
641 END SUBROUTINE c_esmc_basetimeinteq
642 SUBROUTINE c_esmc_basetimeintne(timeint1, timeint2, outflag)
643 USE esmf_timeintervalmod
645 LOGICAL, INTENT(OUT) :: outflag
646 TYPE(ESMF_TimeInterval), INTENT(IN) :: timeint1
647 TYPE(ESMF_TimeInterval), INTENT(IN) :: timeint2
649 CALL timeintcmp(timeint1,timeint2,res)
650 outflag = (res .NE. 0)
651 END SUBROUTINE c_esmc_basetimeintne
652 SUBROUTINE c_esmc_basetimeintlt(timeint1, timeint2, outflag)
653 USE esmf_timeintervalmod
655 LOGICAL, INTENT(OUT) :: outflag
656 TYPE(ESMF_TimeInterval), INTENT(IN) :: timeint1
657 TYPE(ESMF_TimeInterval), INTENT(IN) :: timeint2
659 CALL timeintcmp(timeint1,timeint2,res)
660 outflag = (res .LT. 0)
661 END SUBROUTINE c_esmc_basetimeintlt
662 SUBROUTINE c_esmc_basetimeintgt(timeint1, timeint2, outflag)
663 USE esmf_timeintervalmod
665 LOGICAL, INTENT(OUT) :: outflag
666 TYPE(ESMF_TimeInterval), INTENT(IN) :: timeint1
667 TYPE(ESMF_TimeInterval), INTENT(IN) :: timeint2
669 CALL timeintcmp(timeint1,timeint2,res)
670 outflag = (res .GT. 0)
671 END SUBROUTINE c_esmc_basetimeintgt
672 SUBROUTINE c_esmc_basetimeintle(timeint1, timeint2, outflag)
673 USE esmf_timeintervalmod
675 LOGICAL, INTENT(OUT) :: outflag
676 TYPE(ESMF_TimeInterval), INTENT(IN) :: timeint1
677 TYPE(ESMF_TimeInterval), INTENT(IN) :: timeint2
679 CALL timeintcmp(timeint1,timeint2,res)
680 outflag = (res .LE. 0)
681 END SUBROUTINE c_esmc_basetimeintle
682 SUBROUTINE c_esmc_basetimeintge(timeint1, timeint2, outflag)
683 USE esmf_timeintervalmod
685 LOGICAL, INTENT(OUT) :: outflag
686 TYPE(ESMF_TimeInterval), INTENT(IN) :: timeint1
687 TYPE(ESMF_TimeInterval), INTENT(IN) :: timeint2
689 CALL timeintcmp(timeint1,timeint2,res)
690 outflag = (res .GE. 0)
691 END SUBROUTINE c_esmc_basetimeintge
693 SUBROUTINE compute_lcd( e1, e2, lcd )
696 INTEGER(ESMF_KIND_I8), INTENT(IN) :: e1, e2
697 INTEGER(ESMF_KIND_I8), INTENT(OUT) :: lcd
698 INTEGER, PARAMETER :: nprimes = 9
699 INTEGER(ESMF_KIND_I8), DIMENSION(nprimes), PARAMETER :: primes = (/2,3,5,7,11,13,17,19,23/)
701 INTEGER(ESMF_KIND_I8) d1, d2, p
704 IF ( d1 .EQ. 0 .AND. d2 .EQ. 0 ) THEN ; lcd = 1 ; RETURN ; ENDIF
705 IF ( d1 .EQ. 0 ) d1 = d2
706 IF ( d2 .EQ. 0 ) d2 = d1
707 IF ( d1 .EQ. d2 ) THEN ; lcd = d1 ; RETURN ; ENDIF
711 DO WHILE (lcd/p .NE. 0 .AND. &
712 mod(lcd/p,d1) .EQ. 0 .AND. mod(lcd/p,d2) .EQ. 0)
716 END SUBROUTINE compute_lcd
718 SUBROUTINE simplify( ni, di, no, do )
721 INTEGER(ESMF_KIND_I8), INTENT(IN) :: ni, di
722 INTEGER(ESMF_KIND_I8), INTENT(OUT) :: no, do
723 INTEGER, PARAMETER :: nprimes = 9
724 INTEGER(ESMF_KIND_I8), DIMENSION(nprimes), PARAMETER :: primes = (/2,3,5,7,11,13,17,19,23/)
725 INTEGER(ESMF_KIND_I8) :: pr, d, n
728 IF ( ni .EQ. 0 ) THEN
733 IF ( mod( di , ni ) .EQ. 0 ) THEN
743 DO WHILE ( keepgoing )
745 IF ( d/pr .NE. 0 .AND. n/pr .NE. 0 .AND. MOD(d,pr) .EQ. 0 .AND. MOD(n,pr) .EQ. 0 ) THEN
755 END SUBROUTINE simplify
758 !$$$ this should be named "c_esmc_timesum" or something less misleading
759 SUBROUTINE c_esmc_basetimesum( time1, timeinterval, timeOut )
762 USE esmf_timeintervalmod
765 TYPE(ESMF_Time), INTENT(IN) :: time1
766 TYPE(ESMF_TimeInterval), INTENT(IN) :: timeinterval
767 TYPE(ESMF_Time), INTENT(INOUT) :: timeOut
771 timeOut%basetime = timeOut%basetime + timeinterval%basetime
775 DO m = 1, abs(timeinterval%MM)
776 IF ( timeinterval%MM > 0 ) THEN
777 CALL timeincmonth( timeOut )
779 CALL timedecmonth( timeOut )
783 timeOut%YR = timeOut%YR + timeinterval%YR
784 CALL normalize_time( timeOut )
785 END SUBROUTINE c_esmc_basetimesum
788 !$$$ this should be named "c_esmc_timedec" or something less misleading
789 SUBROUTINE c_esmc_basetimedec( time1, timeinterval, timeOut )
792 USE esmf_timeintervalmod
795 TYPE(ESMF_Time), INTENT(IN) :: time1
796 TYPE(ESMF_TimeInterval), INTENT(IN) :: timeinterval
797 TYPE(ESMF_Time), INTENT(OUT) :: timeOut
799 TYPE (ESMF_TimeInterval) :: neginterval
800 neginterval = timeinterval
801 !$$$push this down into a unary negation operator on TimeInterval
802 neginterval%basetime%S = -neginterval%basetime%S
803 neginterval%basetime%Sn = -neginterval%basetime%Sn
804 neginterval%YR = -neginterval%YR
806 neginterval%MM = -neginterval%MM
808 timeOut = time1 + neginterval
809 END SUBROUTINE c_esmc_basetimedec
812 !$$$ this should be named "c_esmc_timediff" or something less misleading
813 SUBROUTINE c_esmc_basetimediff( time1, time2, timeIntOut )
816 USE esmf_timeintervalmod
819 TYPE(ESMF_Time), INTENT(IN) :: time1
820 TYPE(ESMF_Time), INTENT(IN) :: time2
821 TYPE(ESMF_TimeInterval), INTENT(OUT) :: timeIntOut
823 INTEGER(ESMF_KIND_I8) :: nsecondsinyear
825 CALL ESMF_TimeIntervalSet( timeIntOut )
826 timeIntOut%basetime = time1%basetime - time2%basetime
827 ! convert difference in years to basetime...
828 IF ( time1%YR > time2%YR ) THEN
829 DO yr = time2%YR, ( time1%YR - 1 )
830 timeIntOut%basetime%S = timeIntOut%basetime%S + nsecondsinyear( yr )
832 ELSE IF ( time2%YR > time1%YR ) THEN
833 DO yr = time1%YR, ( time2%YR - 1 )
834 timeIntOut%basetime%S = timeIntOut%basetime%S - nsecondsinyear( yr )
837 !$$$ add tests for multi-year differences
838 CALL normalize_timeint( timeIntOut )
839 END SUBROUTINE c_esmc_basetimediff
842 ! some extra wrf stuff
845 ! Convert fraction to string with leading sign.
846 ! If fraction simplifies to a whole number or if
847 ! denominator is zero, return empty string.
848 ! INTEGER*8 interface.
849 SUBROUTINE fraction_to_stringi8( numerator, denominator, frac_str )
852 INTEGER(ESMF_KIND_I8), INTENT(IN) :: numerator
853 INTEGER(ESMF_KIND_I8), INTENT(IN) :: denominator
854 CHARACTER (LEN=*), INTENT(OUT) :: frac_str
855 IF ( denominator > 0 ) THEN
856 IF ( mod( numerator, denominator ) /= 0 ) THEN
857 IF ( numerator > 0 ) THEN
858 WRITE(frac_str,FMT="('+',I2.2,'/',I2.2)") abs(numerator), denominator
860 WRITE(frac_str,FMT="('-',I2.2,'/',I2.2)") abs(numerator), denominator
862 ELSE ! includes numerator == 0 case
865 ELSE ! no-fraction case
868 END SUBROUTINE fraction_to_stringi8
871 ! Convert fraction to string with leading sign.
872 ! If fraction simplifies to a whole number or if
873 ! denominator is zero, return empty string.
875 SUBROUTINE fraction_to_string( numerator, denominator, frac_str )
878 INTEGER, INTENT(IN) :: numerator
879 INTEGER, INTENT(IN) :: denominator
880 CHARACTER (LEN=*), INTENT(OUT) :: frac_str
882 INTEGER(ESMF_KIND_I8) :: numerator_i8, denominator_i8
883 numerator_i8 = INT( numerator, ESMF_KIND_I8 )
884 denominator_i8 = INT( denominator, ESMF_KIND_I8 )
885 CALL fraction_to_stringi8( numerator_i8, denominator_i8, frac_str )
886 END SUBROUTINE fraction_to_string
889 SUBROUTINE print_a_time( time )
896 CALL ESMF_TimeGet( time, timeString=s, rc=rc )
897 print *,'Print a time|',TRIM(s),'|'
899 END SUBROUTINE print_a_time
901 SUBROUTINE print_a_timeinterval( time )
903 use ESMF_TimeIntervalmod
905 type(ESMF_TimeInterval) time
908 CALL ESMFold_TimeIntervalGetString( time, s, rc )
909 print *,'Print a time interval|',TRIM(s),'|'
911 END SUBROUTINE print_a_timeinterval