<p><b>croesch@ucar.edu</b> 2011-08-10 17:39:55 -0600 (Wed, 10 Aug 2011)</p><p>BRANCH COMMIT<br>
<br>
Replace ESMF Alarms with local implementation<br>
Add timeString parsing<br>
Add addtional error checks and messages<br>
Update alarm interval logic<br>
<br>
M   src/framework/module_mpas_timekeeping.F<br>
</p><hr noshade><pre><font color="gray">Modified: branches/time_manager/src/framework/module_mpas_timekeeping.F
===================================================================
--- branches/time_manager/src/framework/module_mpas_timekeeping.F        2011-08-01 18:18:21 UTC (rev 933)
+++ branches/time_manager/src/framework/module_mpas_timekeeping.F        2011-08-10 23:39:55 UTC (rev 934)
@@ -4,25 +4,25 @@
    use ESMF_Stubs
    use ESMF_CalendarMod
    use ESMF_ClockMod
-   use ESMF_AlarmMod
-   use ESMF_AlarmClockMod
    use ESMF_TimeMod
    use ESMF_TimeIntervalMod
 
+   private :: MPAS_CalibrateAlarms
+   private :: MPAS_inRingingEnvelope
 
    integer, parameter :: MPAS_MAX_ALARMS = 20
    integer, parameter :: MPAS_NOW = 0, &amp;
                          MPAS_START_TIME = 1, &amp;
                          MPAS_STOP_TIME = 2
-   integer, parameter :: MPAS_FORWARD = 0, &amp;
-                         MPAS_BACKWARD = 1
+   integer, parameter :: MPAS_FORWARD = 1, &amp;
+                         MPAS_BACKWARD = -1
    integer, parameter :: MPAS_GREGORIAN = 0, &amp;
                          MPAS_GREGORIAN_NOLEAP = 1, &amp;
                          MPAS_360DAY = 2
 
    integer :: TheCalendar 
 
-   integer, dimension(12), parameter :: daysInMonth = (/31,28,31,30,31,30,31,31,30,31,30,31/)
+   integer, dimension(12), parameter :: daysInMonth     = (/31,28,31,30,31,30,31,31,30,31,30,31/)
    integer, dimension(12), parameter :: daysInMonthLeap = (/31,29,31,30,31,30,31,31,30,31,30,31/)
 
 
@@ -35,15 +35,15 @@
    end type
 
    type MPAS_Alarm_type
-      type (ESMF_Alarm) :: a
-      type (ESMF_Time) :: ringTime
-      type (ESMF_Time) :: relativeToTime
-      type (ESMF_TimeInterval) :: ringTimeInterval
-      logical :: recurring
       integer :: alarmID
+      logical :: isRecurring
+      logical :: isSet
+      type (MPAS_Time_type) :: ringTime
+      type (MPAS_Time_type) :: prevRingTime
+      type (MPAS_TimeInterval_type) :: ringTimeInterval
       type (MPAS_Alarm_type), pointer :: next
    end type
-
+   
    type MPAS_Clock_type
       integer :: direction
       integer :: nAlarms
@@ -51,7 +51,6 @@
       type (MPAS_Alarm_type), pointer :: alarmListHead
    end type
 
-
    interface operator (+)
       module procedure add_t_ti
       module procedure add_ti_ti
@@ -197,7 +196,6 @@
       alarmPtr =&gt; clock % alarmListHead
       do while (associated(alarmPtr))
          clock % alarmListHead =&gt; alarmPtr % next
-         call ESMF_AlarmDestroy(alarmPtr % a, rc=ierr)
          deallocate(alarmPtr)
          alarmPtr =&gt; clock % alarmListHead
       end do
@@ -265,9 +263,6 @@
 
 
    subroutine MPAS_setClockDirection(clock, direction, ierr)
-!TODO: Need to somehow set PrevRingTime for any recurring alarms that are not
-!      ringing so that they will be correctly triggered when advancing time in
-!      a different direction
 
       implicit none
 
@@ -299,85 +294,11 @@
 
 
 
-
-   ! specify a valid previousRingTime for each alarm
-   subroutine MPAS_CalibrateAlarms(clock, ierr)
-
-      type (MPAS_Clock_type), intent(inout) :: clock
-      integer, intent(out), optional :: ierr
-
-      type (MPAS_Alarm_type), pointer :: alarmPtr
-
-      type (MPAS_Time_type) :: now
-      type (MPAS_Time_type) :: previousRingTime
-      type (MPAS_Time_type) :: negativeNeighborRingTime
-      type (MPAS_Time_type) :: positiveNeighborRingTime
-
-      type (MPAS_TimeInterval_type) :: ringTimeInterval 
-
-      now = MPAS_getClockTime(clock, MPAS_NOW, ierr)
-      alarmPtr =&gt; clock % alarmListHead
-      do while (associated(alarmPtr))
-         
-         if (alarmPtr % recurring) then
-         
-            call ESMF_AlarmGetPrevRingTime(alarmPtr % a, previousRingTime % t, ierr)
-            ringTimeInterval % ti = alarmPtr % ringTimeInterval
-
-            if (previousRingTime &lt;= now) then
-            
-               do while(previousRingTime &lt;= now)
-                  previousRingTime = previousRingTime + ringTimeInterval
-               end do
-               positiveNeighborRingTime = previousRingTime
-            
-               do while(previousRingTime &gt;= now)
-                  previousRingTime = previousRingTime - ringTimeInterval
-               end do
-               negativeNeighborRingTime = previousRingTime
-            
-            else
-
-               do while(previousRingTime &gt;= now)
-                  previousRingTime = previousRingTime - ringTimeInterval
-               end do
-               negativeNeighborRingTime = previousRingTime
-
-               do while(previousRingTime &lt;= now)
-                  previousRingTime = previousRingTime + ringTimeInterval
-               end do
-               positiveNeighborRingTime = previousRingTime
-         
-            end if
-
-            if (clock % direction == MPAS_FORWARD) then
-               call ESMF_AlarmSetPrevRingTime(alarmPtr % a, negativeNeighborRingTime % t, ierr)
-            else
-               call ESMF_AlarmSetPrevRingTime(alarmPtr % a, positiveNeighborRingTime % t, ierr)
-            end if
-   
-         else
-            call ESMF_AlarmSet(alarmPtr % a, &amp;
-                               RingTime=alarmPtr%RingTime, &amp;
-                               Enabled=.true., rc=ierr)
-         end if
-   
-         alarmPtr =&gt; alarmPtr % next
-         
-      end do
-   
-      if (present(ierr)) then
-         if (ierr == ESMF_SUCCESS) ierr = 0
-      end if
-   
-   end subroutine MPAS_CalibrateAlarms
-
-
    integer function MPAS_getClockDirection(clock, ierr)
 
       implicit none
 
-      type (MPAS_Clock_type), intent(inout) :: clock
+      type (MPAS_Clock_type), intent(in) :: clock
       integer, intent(out), optional :: ierr
 
       write(0,*) 'Called MPAS_getClockDirection'
@@ -410,7 +331,7 @@
 
       implicit none
 
-      type (MPAS_Clock_type), intent(inout) :: clock
+      type (MPAS_Clock_type), intent(in) :: clock
       integer, intent(out), optional :: ierr
 
       type (MPAS_TimeInterval_type) :: timeStep
@@ -486,7 +407,7 @@
 
       implicit none
 
-      type (MPAS_Clock_type), intent(inout) :: clock
+      type (MPAS_Clock_type), intent(in) :: clock
       integer, intent(in) :: whichTime
       integer, intent(out), optional :: ierr
 
@@ -556,23 +477,21 @@
 
       clock % nAlarms = clock % nAlarms + 1
 
+      alarmPtr % isSet = .true.
+      alarmPtr % ringTime = alarmTime
+      
+
       if (present(alarmTimeInterval)) then
-         alarmPtr % a = ESMF_AlarmCreate(clock % c, &amp;
-                                         RingTime=alarmTime%t, &amp;
-                                         RingInterval=alarmTimeInterval%ti, &amp;
-                                         Enabled=.true., &amp;
-                                         rc=ierr)
-         alarmPtr % ringTime = alarmTime%t
-         alarmPtr % relativeToTime = alarmTime%t
-         alarmPtr % ringTimeInterval = alarmTimeInterval%ti
-         alarmPtr % recurring = .true.
+         alarmPtr % isRecurring = .true.
+         alarmPtr % ringTimeInterval = alarmTimeInterval
+         if(clock % direction == MPAS_FORWARD) then
+            alarmPtr % prevRingTime = alarmTime - alarmTimeInterval
+         else
+            alarmPtr % prevRingTime = alarmTime + alarmTimeInterval         
+         end if
       else
-         alarmPtr % a = ESMF_AlarmCreate(clock % c, &amp;
-                                         RingTime=alarmTime%t, &amp;
-                                         Enabled=.true., &amp;
-                                         rc=ierr)
-         alarmPtr % ringTime = alarmTime%t
-         alarmPtr % recurring = .false.
+         alarmPtr % isRecurring = .false.
+         alarmPtr % prevRingTime = alarmTime
       end if
       if (present(ierr)) then
          if (ierr == ESMF_SUCCESS) ierr = 0
@@ -581,6 +500,36 @@
    end subroutine MPAS_addClockAlarm
 
 
+   subroutine MPAS_removeClockAlarm(clock, alarmID, ierr)
+
+      implicit none
+
+      type (MPAS_Clock_type), intent(inout) :: clock
+      integer, intent(in) :: alarmID
+      integer, intent(out), optional :: ierr
+
+      type (MPAS_Alarm_type), pointer :: alarmPtr
+      type (MPAS_Alarm_type), pointer :: alarmParentPtr
+
+      write(0,*) 'Called MPAS_removeClockAlarm'
+      if (present(ierr)) ierr = 0
+
+      alarmPtr =&gt; clock % alarmListHead
+      alarmParentPtr = alarmPtr
+      do while (associated(alarmPtr))
+         if (alarmPtr % alarmID == alarmID) then
+            alarmParentPtr % next =&gt; alarmPtr % next
+            deallocate(alarmPtr)
+            exit
+         end if
+         alarmParentPtr = alarmPtr
+         alarmPtr =&gt; alarmPtr % next
+      end do
+
+   end subroutine MPAS_removeClockAlarm
+
+
+
    subroutine MPAS_printAlarm(clock, alarmID, ierr)
 
       implicit none
@@ -591,19 +540,30 @@
 
       type (MPAS_Alarm_type), pointer :: alarmPtr
 
+      type (MPAS_TimeInterval_type) :: alarmTimeInterval
+      type (MPAS_Time_type) :: alarmTime
+      character (len=32) :: printString
+
       ierr = 0
 
       alarmPtr =&gt; clock % alarmListHead
       do while (associated(alarmPtr))
          if (alarmPtr % alarmID == alarmID) then
-            write(0,*) 'ALARM ',alarmID
-            write(0,*) alarmPtr % a % alarmint % ID
-            write(0,*) alarmPtr % a % alarmint % AlarmMutex
-            write(0,*) alarmPtr % a % alarmint % Ringing
-            write(0,*) alarmPtr % a % alarmint % Enabled
-            write(0,*) alarmPtr % a % alarmint % RingTimeSet
-            write(0,*) alarmPtr % a % alarmint % RingIntervalSet
-            write(0,*) alarmPtr % a % alarmint % StopTimeSet
+            write(0,*) 'ALARM ', alarmID
+
+            write(0,*) 'isRecurring', alarmPtr % isRecurring
+            
+            write(0,*) 'isSet', alarmPtr % isSet
+
+            call MPAS_getTime(alarmPtr % ringTime, dateTimeString=printString, ierr=ierr)
+            write(0,*) 'ringTime', printString
+
+            call MPAS_getTime(alarmPtr % prevRingTime, dateTimeString=printString, ierr=ierr)
+            write(0,*) 'prevRingTime', printString
+
+            call MPAS_getTimeInterval(alarmPtr % ringTimeInterval, timeString=printString, ierr=ierr)
+            write(0,*) 'ringTimeInterval', printString
+            
             exit
          end if
          alarmPtr =&gt; alarmPtr % next
@@ -612,46 +572,31 @@
    end subroutine MPAS_printAlarm
 
 
+
    logical function MPAS_isAlarmRinging(clock, alarmID, interval, ierr)
-! TODO: check for alarms ringing within the specified interval rather than just now
 
       implicit none
 
-      type (MPAS_Clock_type), intent(inout) :: clock               ! BETTER IF INTENT(IN)
+      type (MPAS_Clock_type), intent(in) :: clock
       integer, intent(in) :: alarmID
       type (MPAS_TimeInterval_type), intent(in), optional :: interval
       integer, intent(out), optional :: ierr
 
       type (MPAS_Alarm_type), pointer :: alarmPtr
-      type (ESMF_TimeInterval) :: timeStep
-      type (MPAS_TimeInterval_type) :: userInterval
 
       write(0,*) 'Called MPAS_isAlarmRinging'
       if (present(ierr)) ierr = 0
 
       MPAS_isAlarmRinging = .false.
+      
       alarmPtr =&gt; clock % alarmListHead
       do while (associated(alarmPtr))
          if (alarmPtr % alarmID == alarmID) then
-            if (present(interval)) then
-               userInterval = interval
-               call ESMF_ClockGet(clock % c, TimeStep=timeStep, rc=ierr)
-               call ESMF_ClockSet(clock % c, TimeStep=userInterval % ti, rc=ierr)
-               call ESMF_ClockAdvance(clock % c, rc=ierr)
-               MPAS_isAlarmRinging = ESMF_AlarmIsRinging(alarmPtr % a, rc=ierr)
-               userInterval = -userInterval
-               call ESMF_ClockSet(clock % c, TimeStep=userInterval % ti, rc=ierr)
-               call ESMF_ClockAdvance(clock % c, rc=ierr)
-               call ESMF_ClockSet(clock % c, TimeStep=timeStep, rc=ierr)
-! TODO: Do these next two steps only if the alarm was not already ringing?
-               call ESMF_AlarmRingerOff(alarmPtr % a, rc=ierr)
-               call ESMF_AlarmSet(alarmPtr % a, RingTime=alarmPtr % RingTime, Enabled=.true., rc=ierr)
-            else
-               MPAS_isAlarmRinging = ESMF_AlarmIsRinging(alarmPtr % a, rc=ierr)
+            if (alarmPtr % isSet) then
+               if (MPAS_inRingingEnvelope(clock, alarmPtr, interval, ierr)) then
+                  MPAS_isAlarmRinging = .true.
+               end if
             end if
-            if (present(ierr)) then
-               if (ierr == ESMF_SUCCESS) ierr = 0
-            end if
             exit
          end if
          alarmPtr =&gt; alarmPtr % next
@@ -660,55 +605,134 @@
    end function MPAS_isAlarmRinging
 
 
-   subroutine MPAS_removeClockAlarm(clock, alarmID, ierr)
-! TODO: Actually remove the alarm from the list and decrement clock%nAlarms?
 
+   subroutine MPAS_getClockRingingAlarms(clock, nAlarms, alarmList, interval, ierr)
+
       implicit none
 
-      type (MPAS_Clock_type), intent(inout) :: clock
-      integer, intent(in) :: alarmID
+      type (MPAS_Clock_type), intent(in) :: clock
+      integer, intent(out) :: nAlarms
+      integer, dimension(MPAS_MAX_ALARMS), intent(out) :: alarmList
+      type (MPAS_TimeInterval_type), intent(in), optional :: interval
       integer, intent(out), optional :: ierr
 
       type (MPAS_Alarm_type), pointer :: alarmPtr
 
-      write(0,*) 'Called MPAS_removeClockAlarm'
+      write(0,*) 'Called MPAS_getClockRingingAlarms'
       if (present(ierr)) ierr = 0
 
+      nAlarms = 0
+
       alarmPtr =&gt; clock % alarmListHead
       do while (associated(alarmPtr))
-         if (alarmPtr % alarmID == alarmID) then
-            call ESMF_AlarmDisable(alarmPtr % a, rc=ierr)
-            if (present(ierr)) then
-               if (ierr == ESMF_SUCCESS) ierr = 0
+         if (alarmPtr % isSet) then
+            if (MPAS_inRingingEnvelope(clock, alarmPtr, interval, ierr)) then
+               nAlarms = nAlarms + 1
+               alarmList(nAlarms) = alarmPtr % alarmID
             end if
-            exit
          end if
          alarmPtr =&gt; alarmPtr % next
       end do
 
-   end subroutine MPAS_removeClockAlarm
+   end subroutine MPAS_getClockRingingAlarms
 
 
-   subroutine MPAS_resetClockAlarm(clock, alarmID, ierr)
+   logical function MPAS_inRingingEnvelope(clock, alarmPtr, interval, ierr)
 
       implicit none
+      
+      type (MPAS_Clock_type), intent(in) :: clock
+      type (MPAS_Alarm_type), pointer, intent(in) :: alarmPtr
+      type (MPAS_TimeInterval_type), intent(in), optional :: interval
+      integer, intent(out), optional :: ierr
+      
+      type (MPAS_Time_type) :: alarmNow
+      type (MPAS_Time_type) :: alarmThreshold
 
+      alarmNow = MPAS_getClockTime(clock, MPAS_NOW, ierr)
+      alarmThreshold = alarmPtr % ringTime 
+      
+      MPAS_inRingingEnvelope = .false.      
+               
+      if(clock % direction == MPAS_FORWARD) then
+
+         if (present(interval)) then
+            alarmNow = alarmNow + interval; 
+         end if
+
+         if (alarmPtr % isRecurring) then
+            alarmThreshold = alarmPtr % prevRingTime + alarmPtr % ringTimeInterval
+         end if
+
+         if (alarmThreshold &lt;= alarmNow) then
+            MPAS_inRingingEnvelope = .true.
+         end if
+      else
+
+         if (present(interval)) then
+            alarmNow = alarmNow - interval; 
+         end if
+
+         if (alarmPtr % isRecurring) then
+            alarmThreshold = alarmPtr % prevRingTime - alarmPtr % ringTimeInterval
+         end if
+            
+         if (alarmThreshold &gt;= alarmNow) then
+            MPAS_inRingingEnvelope = .true.
+         end if
+      end if
+
+   end function MPAS_inRingingEnvelope
+
+
+
+   subroutine MPAS_resetClockAlarm(clock, alarmID, interval, ierr)
+
+      implicit none
+
       type (MPAS_Clock_type), intent(inout) :: clock
       integer, intent(in) :: alarmID
+      type (MPAS_TimeInterval_type), intent(in), optional :: interval
       integer, intent(out), optional :: ierr
 
+      type (MPAS_Time_type) :: alarmNow
       type (MPAS_Alarm_type), pointer :: alarmPtr
-      type (ESMF_Time) :: ringTime
 
       write(0,*) 'Called MPAS_resetClockAlarm'
       if (present(ierr)) ierr = 0
 
       alarmPtr =&gt; clock % alarmListHead
       do while (associated(alarmPtr))
+      
          if (alarmPtr % alarmID == alarmID) then
-            call ESMF_AlarmRingerOff(alarmPtr % a, rc=ierr)
-            if (present(ierr)) then
-               if (ierr == ESMF_SUCCESS) ierr = 0
+
+            if (MPAS_inRingingEnvelope(clock, alarmPtr, interval, ierr)) then
+
+               if (.not. alarmPtr % isRecurring) then
+                  alarmPtr % isSet = .false. 
+               else
+                  alarmNow = MPAS_getClockTime(clock, MPAS_NOW, ierr)
+
+                  if(clock % direction == MPAS_FORWARD) then
+                     if (present(interval)) then
+                        alarmNow = alarmNow + interval
+                     end if
+
+                     do while(alarmPtr % prevRingTime &lt;= alarmNow)
+                        alarmPtr % prevRingTime = alarmPtr % prevRingTime + alarmPtr % ringTimeInterval
+                     end do
+                     alarmPtr % prevRingTime =  alarmPtr % prevRingTime - alarmPtr % ringTimeInterval
+                  else
+                     if (present(interval)) then
+                        alarmNow = alarmNow - interval
+                     end if
+
+                     do while(alarmPtr % prevRingTime &gt;= alarmNow)
+                        alarmPtr % prevRingTime = alarmPtr % prevRingTime - alarmPtr % ringTimeInterval
+                     end do
+                     alarmPtr % prevRingTime = alarmPtr % prevRingTime + alarmPtr % ringTimeInterval
+                  end if
+               end if
             end if
             exit
          end if
@@ -718,86 +742,80 @@
    end subroutine MPAS_resetClockAlarm
 
 
-   subroutine MPAS_getClockRingingAlarms(clock, nAlarms, alarmList, interval, ierr)
-! TODO: check for alarms ringing within the specified interval rather than just now
 
+   ! specify a valid previousRingTime for each alarm
+   subroutine MPAS_CalibrateAlarms(clock, ierr)
+
       implicit none
 
-      type (MPAS_Clock_type), intent(inout) :: clock                   ! BETTER IF INTENT(IN)
-      integer, intent(out) :: nAlarms
-      integer, dimension(MPAS_MAX_ALARMS), intent(out) :: alarmList
-      type (MPAS_TimeInterval_type), intent(in), optional :: interval
+      type (MPAS_Clock_type), intent(in) :: clock
       integer, intent(out), optional :: ierr
 
+      type (MPAS_Time_type) :: now
+      type (MPAS_Time_type) :: previousRingTime
+      type (MPAS_Time_type) :: negativeNeighborRingTime
+      type (MPAS_Time_type) :: positiveNeighborRingTime
+      type (MPAS_TimeInterval_type) :: ringTimeInterval 
       type (MPAS_Alarm_type), pointer :: alarmPtr
-      type (ESMF_TimeInterval) :: timeStep
-      type (MPAS_TimeInterval_type) :: userInterval
 
-      write(0,*) 'Called MPAS_getClockRingingAlarms'
-      if (present(ierr)) ierr = 0
+      now = MPAS_getClockTime(clock, MPAS_NOW, ierr)
+      
+      alarmPtr =&gt; clock % alarmListHead
+      do while (associated(alarmPtr))
+         
+         if (.not. alarmPtr % isRecurring) then
+            alarmPtr % isSet = .true.            
+         else
+         
+            previousRingTime = alarmPtr % prevRingTime
 
-      if (present(interval)) then
-         userInterval = interval
-         call ESMF_ClockGet(clock % c, TimeStep=timeStep, rc=ierr)
-         call ESMF_ClockSet(clock % c, TimeStep=userInterval % ti, rc=ierr)
-         call ESMF_ClockAdvance(clock % c, rc=ierr)
-         nAlarms = 0
-         alarmPtr =&gt; clock % alarmListHead
-         do while (associated(alarmPtr))
-            if (ESMF_AlarmIsRinging(alarmPtr % a, rc=ierr)) then
-               if (present(ierr)) then
-                  if (ierr == ESMF_SUCCESS) ierr = 0
-               end if
-               nAlarms = nAlarms + 1
-               alarmList(nAlarms) = alarmPtr % alarmID
+            if (previousRingTime &lt;= now) then
+            
+               do while(previousRingTime &lt;= now)
+                  previousRingTime = previousRingTime + alarmPtr % ringTimeInterval
+               end do
+               positiveNeighborRingTime = previousRingTime
+            
+               do while(previousRingTime &gt;= now)
+                  previousRingTime = previousRingTime - alarmPtr % ringTimeInterval
+               end do
+               negativeNeighborRingTime = previousRingTime
+            
+            else
+
+               do while(previousRingTime &gt;= now)
+                  previousRingTime = previousRingTime - alarmPtr % ringTimeInterval
+               end do
+               negativeNeighborRingTime = previousRingTime
+
+               do while(previousRingTime &lt;= now)
+                  previousRingTime = previousRingTime + alarmPtr % ringTimeInterval
+               end do
+               positiveNeighborRingTime = previousRingTime
+         
             end if
-            alarmPtr =&gt; alarmPtr % next
-         end do
-         userInterval = -userInterval
-         call ESMF_ClockSet(clock % c, TimeStep=userInterval % ti, rc=ierr)
-         call ESMF_ClockAdvance(clock % c, rc=ierr)
-         call ESMF_ClockSet(clock % c, TimeStep=timeStep, rc=ierr)
-! TODO: Do the operations in this loop only for alarms that were not already ringing?
-         alarmPtr =&gt; clock % alarmListHead
-         do while (associated(alarmPtr))
-            if (ESMF_AlarmIsRinging(alarmPtr % a, rc=ierr)) then
-               call ESMF_AlarmRingerOff(alarmPtr % a, rc=ierr)
-               if (alarmPtr % recurring) then
-                  call ESMF_AlarmSet(alarmPtr % a, &amp;
-                                     RingTime=alarmPtr%RingTime, &amp;
-                                     RingInterval=alarmPtr%RingTimeInterval, &amp;
-                                     Enabled=.true., rc=ierr)
-               else
-                  call ESMF_AlarmSet(alarmPtr % a, &amp;
-                                     RingTime=alarmPtr%RingTime, &amp;
-                                     Enabled=.true., rc=ierr)
-               end if
-               if (present(ierr)) then
-                  if (ierr == ESMF_SUCCESS) ierr = 0
-               end if
+
+            if (clock % direction == MPAS_FORWARD) then
+               alarmPtr % prevRingTime = negativeNeighborRingTime
+            else
+               alarmPtr % prevRingTime = positiveNeighborRingTime
             end if
-            alarmPtr =&gt; alarmPtr % next
-         end do
-      else
-         nAlarms = 0
-         alarmPtr =&gt; clock % alarmListHead
-         do while (associated(alarmPtr))
-            if (ESMF_AlarmIsRinging(alarmPtr % a, rc=ierr)) then
-               if (present(ierr)) then
-                  if (ierr == ESMF_SUCCESS) ierr = 0
-               end if
-               nAlarms = nAlarms + 1
-               alarmList(nAlarms) = alarmPtr % alarmID
-            end if
-            alarmPtr =&gt; alarmPtr % next
-         end do
+
+         end if
+   
+         alarmPtr =&gt; alarmPtr % next
+         
+      end do
+   
+      if (present(ierr)) then
+         if (ierr == ESMF_SUCCESS) ierr = 0
       end if
+   
+   end subroutine MPAS_CalibrateAlarms
 
-   end subroutine MPAS_getClockRingingAlarms
 
+   subroutine MPAS_setTime(curr_time, YYYY, MM, DD, DoY, H, M, S, S_n, S_d, dateTimeString, ierr)
 
-   subroutine MPAS_setTime(curr_time, YYYY, MM, DD, DoY, H, M, S, S_n, S_d, dateString, ierr)
-
       implicit none
 
       type (MPAS_Time_type), intent(out) :: curr_time
@@ -810,53 +828,143 @@
       integer, intent(in), optional :: S
       integer, intent(in), optional :: S_n
       integer, intent(in), optional :: S_d
-      character (len=*), intent(in), optional :: dateString
+      character (len=*), intent(in), optional :: dateTimeString
       integer, intent(out), optional :: ierr
 
-      integer :: month, day
+      integer, parameter :: integerMaxDigits = 8
+      integer :: year, month, day, hour, min, sec
+      integer :: numerator, denominator, denominatorPower
 
+      character (len=50) :: dateTimeString_
+      character (len=50) :: dateSubString
+      character (len=50) :: timeSubString
+      character (len=50) :: secDecSubString
+      character(len=50), pointer, dimension(:) :: subStrings
+
       write(0,*) 'Called MPAS_setTime'
 
-      if (present(DoY)) then
-         call getMonthDay(YYYY, DoY, month, day)
-         
-         ! consistency check
-         if (present(MM)) then
-            if (MM /= month) then
-               if (present(ierr)) ierr = 1
-               write(0,*) 'ERROR: MPAS_setTime : DoY and MM are inconsistent - using DoY'
+      if (present(dateTimeString)) then
+
+         dateTimeString_ = dateTimeString
+         numerator = 0
+         denominator = 1
+
+         call SplitString(dateTimeString_, &quot;.&quot;, subStrings)
+         if (size(subStrings) == 2) then ! contains second decimals
+            dateTimeString_ = subStrings(1)
+            secDecSubString = subStrings(2)(:integerMaxDigits)
+            deallocate(subStrings)
+            denominatorPower = len_trim(secDecSubString)
+            if(denominatorPower &gt; 0) then
+               read(secDecSubString,*) numerator 
+               if(numerator &gt; 0) then
+                  denominator = 10**denominatorPower
+               end if
             end if
+         else if (size(subStrings) /= 1) then
+            deallocate(subStrings)
+            if (present(ierr)) ierr = 1
+            write(0,*) 'ERROR: Invalid DateTime string', dateTimeString
+            return
          end if
-         if (present(DD)) then
-            if (DD /= day) then
+
+         call SplitString(dateTimeString_, &quot;_&quot;, subStrings)
+
+         if(size(subStrings) == 2) then   ! contains a date and time
+            dateSubString = subStrings(1)
+            timeSubString = subStrings(2)
+            deallocate(subStrings)
+            
+            call SplitString(timeSubString, &quot;:&quot;, subStrings)
+            
+            if (size(subStrings) == 3) then
+               read(subStrings(1),*) hour 
+               read(subStrings(2),*) min 
+               read(subStrings(3),*) sec 
+               deallocate(subStrings)
+            else
+               deallocate(subStrings)
                if (present(ierr)) ierr = 1
-               write(0,*) 'ERROR: MPAS_setTime : DoY and DD are inconsistent - using DoY'
+               write(0,*) 'ERROR: Invalid DateTime string (invalid time substring)', dateTimeString
+               return
             end if
-         end if
-      else
-         if (present(MM)) then
-            month = MM
+
+         else if(size(subStrings) == 1) then   ! contains only a date- assume all time values are 0 
+            dateSubString = subStrings(1)
+            deallocate(subStrings)
+           
+            hour = 0
+            min = 0
+            sec = 0
+         
          else
+            deallocate(subStrings)
             if (present(ierr)) ierr = 1
-            write(0,*) 'ERROR: MPAS_setTime : Neither DoY nor MM are specified'
+            write(0,*) 'ERROR: Invalid DateTime string', dateTimeString
             return
          end if
 
-         if (present(DD)) then
-            day = DD
+         call SplitString(dateSubString, &quot;-&quot;, subStrings)
+            
+         if (size(subStrings) == 3) then
+            read(subStrings(1),*) year 
+            read(subStrings(2),*) month
+            read(subStrings(3),*) day
+            deallocate(subStrings)
          else
+            deallocate(subStrings)
             if (present(ierr)) ierr = 1
-            write(0,*) 'ERROR: MPAS_setTime : Neither DoY nor DD are specified'
+            write(0,*) 'ERROR: Invalid DateTime string (invalid date substring)', dateTimeString
             return
          end if
-      end if
 
-      if (.not. isValidDate(YYYY,month,day)) then
-         write(0,*) 'ERROR: MPAS_setTime : Invalid date'
-         return
+         call ESMF_TimeSet(curr_time % t, YY=year, MM=month, DD=day, H=hour, M=min, S=sec, Sn=numerator, Sd=denominator, rc=ierr)
+
+      else
+      
+         if (present(DoY)) then
+            call getMonthDay(YYYY, DoY, month, day)
+         
+            ! consistency check
+            if (present(MM)) then
+               if (MM /= month) then
+                  if (present(ierr)) ierr = 1
+                  write(0,*) 'ERROR: MPAS_setTime : DoY and MM are inconsistent - using DoY'
+               end if
+            end if
+            if (present(DD)) then
+               if (DD /= day) then
+                  if (present(ierr)) ierr = 1
+                  write(0,*) 'ERROR: MPAS_setTime : DoY and DD are inconsistent - using DoY'
+               end if
+            end if
+         else
+            if (present(MM)) then
+               month = MM
+            else
+               if (present(ierr)) ierr = 1
+               write(0,*) 'ERROR: MPAS_setTime : Neither DoY nor MM are specified'
+               return
+            end if
+
+            if (present(DD)) then
+               day = DD
+            else
+               if (present(ierr)) ierr = 1
+               write(0,*) 'ERROR: MPAS_setTime : Neither DoY nor DD are specified'
+               return
+            end if
+         end if
+
+         if (.not. isValidDate(YYYY,month,day)) then
+            write(0,*) 'ERROR: MPAS_setTime : Invalid date'
+            return
+         end if
+
+         call ESMF_TimeSet(curr_time % t, YY=YYYY, MM=month, DD=day, H=H, M=M, S=S, Sn=S_n, Sd=S_d, rc=ierr)
+      
       end if
-
-      call ESMF_TimeSet(curr_time % t, YY=YYYY, MM=month, DD=day, H=H, M=M, S=S, Sn=S_n, Sd=S_d, rc=ierr)
+      
       if (present(ierr)) then
          if (ierr == ESMF_SUCCESS) ierr = 0
       end if
@@ -864,7 +972,7 @@
    end subroutine MPAS_setTime
 
 
-   subroutine MPAS_getTime(curr_time, YYYY, MM, DD, DoY, H, M, S, S_n, S_d, dateString, ierr)
+   subroutine MPAS_getTime(curr_time, YYYY, MM, DD, DoY, H, M, S, S_n, S_d, dateTimeString, ierr)
 
       implicit none
 
@@ -878,14 +986,14 @@
       integer, intent(out), optional :: S
       integer, intent(out), optional :: S_n
       integer, intent(out), optional :: S_d
-      character (len=32), intent(out), optional :: dateString
+      character (len=32), intent(out), optional :: dateTimeString
       integer, intent(out), optional :: ierr
 
       write(0,*) 'Called MPAS_getTime'
 
       call ESMF_TimeGet(curr_time % t, YY=YYYY, MM=MM, DD=DD, H=H, M=M, S=S, Sn=S_n, Sd=S_d, rc=ierr)
       call ESMF_TimeGet(curr_time % t, dayOfYear=DoY, rc=ierr)
-      call ESMF_TimeGet(curr_time % t, timeString=dateString, rc=ierr)
+      call ESMF_TimeGet(curr_time % t, timeString=dateTimeString, rc=ierr)
       if (present(ierr)) then
          if (ierr == ESMF_SUCCESS) ierr = 0
       end if
@@ -893,9 +1001,8 @@
    end subroutine MPAS_getTime
 
 
-   subroutine MPAS_setTimeInterval(interval, DD, H, M, S, S_n, S_d, timeString, ierr)
+   subroutine MPAS_setTimeInterval(interval, DD, H, M, S, S_n, S_d, timeString, dt, ierr)
 ! TODO: add double-precision seconds
-! TODO: support timeString
 
       implicit none
 
@@ -907,10 +1014,21 @@
       integer, intent(in), optional :: S_n
       integer, intent(in), optional :: S_d
       character (len=*), intent(in), optional :: timeString
+      real (kind=RKIND), intent(in), optional :: dt
       integer, intent(out), optional :: ierr
 
+      integer, parameter :: integerMaxDigits = 8
       integer :: days, hours, minutes, seconds
+      integer :: numerator, denominator, denominatorPower
+      type (MPAS_TimeInterval_type) :: zeroInterval
 
+      integer :: day, hour, min, sec
+      character (len=50) :: timeString_
+      character (len=50) :: daySubString
+      character (len=50) :: timeSubString
+      character (len=50) :: secDecSubString
+      character(len=50), pointer, dimension(:) :: subStrings
+
       write(0,*) 'Called MPAS_setTimeInterval'
 
 !      if (present(DD)) then
@@ -976,11 +1094,95 @@
 !      seconds = seconds + hours*3600 + minutes*60
 
 !      call ESMF_TimeIntervalSet(interval % ti, D=days, S=seconds, Sn=S_n, Sd=S_d, rc=ierr)
-      call ESMF_TimeIntervalSet(interval % ti, D=DD, H=H, M=M, S=S, Sn=S_n, Sd=S_d, rc=ierr)
+
+
+      if (present(timeString) .or. present(dt)) then
+
+
+         if(present(dt)) then
+            write (timeString_,*) &quot;00:00:&quot;, dt         
+         else
+            timeString_ = timeString
+         end if
+
+         numerator = 0
+         denominator = 1
+
+         call SplitString(timeString_, &quot;.&quot;, subStrings)
+         
+         if (size(subStrings) == 2) then ! contains second decimals
+            timeString_ = subStrings(1)
+            secDecSubString = subStrings(2)(:integerMaxDigits)
+            deallocate(subStrings)
+
+            denominatorPower = len_trim(secDecSubString)
+            if(denominatorPower &gt; 0) then
+               read(secDecSubString,*) numerator 
+               if(numerator &gt; 0) then
+                  denominator = 10**denominatorPower
+               end if
+            end if
+         else if (size(subStrings) /= 1) then
+            deallocate(subStrings)
+            if (present(ierr)) ierr = 1
+            write(0,*) 'ERROR: Invalid TimeInterval string', timeString
+            return
+         end if
+
+         call SplitString(timeString_, &quot;_&quot;, subStrings)
+
+         if(size(subStrings) == 2) then   ! contains a day and time
+            daySubString = subStrings(1)
+            timeSubString = subStrings(2)
+            deallocate(subStrings)
+            read(daySubString,*) day 
+         else if(size(subStrings) == 1) then   ! contains only a time- assume day is 0 
+            timeSubString = subStrings(1)
+            deallocate(subStrings)
+            day = 0
+         else
+            deallocate(subStrings)
+            if (present(ierr)) ierr = 1
+            write(0,*) 'ERROR: Invalid TimeInterval string', timeString
+            return
+         end if
+
+         call SplitString(timeSubString, &quot;:&quot;, subStrings)
+            
+         if (size(subStrings) == 3) then
+            read(subStrings(1),*) hour 
+            read(subStrings(2),*) min 
+            read(subStrings(3),*) sec 
+            deallocate(subStrings)
+         else
+            deallocate(subStrings)
+            if (present(ierr)) ierr = 1
+            write(0,*) 'ERROR: Invalid TimeInterval string (invalid time substring)', timeString
+            return
+         end if
+
+         call ESMF_TimeIntervalSet(interval % ti, D=day, H=hour, M=min, S=sec, Sn=numerator, Sd=denominator, rc=ierr)
+
+      else
+
+         call ESMF_TimeIntervalSet(interval % ti, D=DD, H=H, M=M, S=S, Sn=S_n, Sd=S_d, rc=ierr)
+      
+      end if
+
+      ! verify that time interval is positive
+      call ESMF_TimeIntervalSet(zeroInterval % ti, D=0, H=0, M=0, S=0, rc=ierr)
+
       if (present(ierr)) then
          if (ierr == ESMF_SUCCESS) ierr = 0
       end if
 
+      if (interval &lt;= zeroInterval) then
+         if (present(ierr)) ierr = 1   
+         write(0,*) 'ERROR: TimeInterval must be greater than 0', timeString !'ERROR: TimeInterval cannot be negative'
+      end if
+      
+
+      
    end subroutine MPAS_setTimeInterval
 
 
@@ -1290,6 +1492,39 @@
 !   end function mod
 
 
+   subroutine SplitString(string, delimiter, subStrings)   
+      
+      implicit none
+      
+      character(len=*), intent(in) :: string
+      character, intent(in) :: delimiter
+      character(len=*), pointer, dimension(:) :: subStrings
+      
+      integer :: i, start, index
+
+      index = 1
+      do i = 1, len(string)
+         if(string(i:i) == delimiter) then
+            index = index + 1
+         end if
+      end do
+
+      allocate(subStrings(1:index))
+
+      start = 1
+      index = 1
+      do i = 1, len(string)
+         if(string(i:i) == delimiter) then
+               subStrings(index) = string(start:i-1) 
+               index = index + 1
+               start = i + 1
+         end if
+      end do
+      subStrings(index) = string(start:len(string)) 
+      
+   end subroutine SplitString
+
+
     subroutine getMonthDay(YYYY, DoY, month, day)
        
        implicit none
@@ -1376,9 +1611,14 @@
 
     end function isLeapYear
 
+
+
+
+
 end module mpas_timekeeping
 
 
+
 subroutine wrf_error_fatal(msg)
 
    implicit none

</font>
</pre>