26 module fms_diag_time_utils_mod
 
   30 use diag_data_mod,    
only: end_of_run, every_time, diag_seconds, diag_minutes, diag_hours, diag_days, diag_months, &
 
   32 USE constants_mod,    
ONLY: seconds_per_day, seconds_per_hour, seconds_per_minute
 
   39 public :: diag_time_inc
 
   47   TYPE(time_type) FUNCTION diag_time_inc(time, output_freq, output_units, err_msg)
 
   48     TYPE(time_type),  
INTENT(in)            :: time
 
   49     INTEGER,          
INTENT(in)            :: output_freq
 
   50     INTEGER,          
INTENT(in)            :: output_units
 
   51     CHARACTER(len=*), 
INTENT(out), 
OPTIONAL :: err_msg
 
   60   end function diag_time_inc
 
   66     TYPE(time_type),  
INTENT(in)            :: time
 
   67     INTEGER,          
INTENT(in)            :: output_freq
 
   68     INTEGER,          
INTENT(in)            :: output_units
 
   69     CHARACTER(len=*), 
INTENT(out), 
OPTIONAL :: err_msg
 
   72     CHARACTER(len=128) :: error_message_local
 
   79     type(time_type) :: my_time
 
   81     IF ( 
PRESENT(err_msg) ) err_msg = 
'' 
   82     error_message_local = 
'' 
   84     IF ( get_calendar_type() == no_calendar) 
then 
   85       error_message_local = 
'If using use_clock_average =.TRUE., your calendar must be set.' 
   86       IF ( fms_error_handler(
'diag_clock_time_inc',error_message_local,err_msg) ) 
RETURN 
   92     IF ( output_freq == end_of_run .OR. output_freq == every_time ) 
THEN 
   97     call get_date(time, cyear, cmonth, cday, chour, cmin, csecond)
 
   99     select case (output_units)
 
  101       my_time = set_date(cyear, cmonth, cday, chour, cmin, csecond) 
 
  102       diag_clock_time_inc = increment_date(my_time, 0, 0, 0, 0, 0, output_freq, err_msg=error_message_local)
 
  104       my_time = set_date(cyear, cmonth, cday, chour, cmin, 0) 
 
  105       diag_clock_time_inc = increment_date(my_time, 0, 0, 0, 0, output_freq, 0, err_msg=error_message_local)
 
  107       my_time = set_date(cyear, cmonth, cday, chour, 0, 0) 
 
  108       diag_clock_time_inc = increment_date(my_time, 0, 0, 0, output_freq, 0, 0, err_msg=error_message_local)
 
  110       my_time = set_date(cyear, cmonth, cday, 0, 0, 0) 
 
  111       diag_clock_time_inc = increment_date(my_time, 0, 0, output_freq, 0, 0, 0, err_msg=error_message_local)
 
  113       my_time = set_date(cyear, cmonth, 1, 0, 0, 0) 
 
  114       diag_clock_time_inc = increment_date(my_time, 0, output_freq, 0, 0, 0, 0, err_msg=error_message_local)
 
  116       my_time = set_date(cyear, 1, 1, 0, 0, 0) 
 
  117       diag_clock_time_inc = increment_date(my_time, output_freq, 0, 0, 0, 0, 0, err_msg=error_message_local)
 
  126     TYPE(time_type),  
INTENT(in)            :: time
 
  127     INTEGER,          
INTENT(in)            :: output_freq
 
  128     INTEGER,          
INTENT(in)            :: output_units
 
  129     CHARACTER(len=*), 
INTENT(out), 
OPTIONAL :: err_msg
 
  133     CHARACTER(len=128) :: error_message_local
 
  142     IF ( 
PRESENT(err_msg) ) err_msg = 
'' 
  143     error_message_local = 
'' 
  148     IF ( output_freq == end_of_run .OR. output_freq == every_time ) 
THEN 
  154     IF ( output_units == diag_seconds ) 
THEN 
  155        IF ( get_calendar_type() == no_calendar ) 
THEN 
  160     ELSE IF ( output_units == diag_minutes ) 
THEN 
  161        IF ( get_calendar_type() == no_calendar ) 
THEN 
  163                &err_msg=error_message_local)
 
  167     ELSE IF ( output_units == diag_hours ) 
THEN 
  168        IF ( get_calendar_type() == no_calendar ) 
THEN 
  170                &err_msg=error_message_local)
 
  174     ELSE IF ( output_units == diag_days ) 
THEN 
  175        IF (get_calendar_type() == no_calendar) 
THEN 
  180     ELSE IF ( output_units == diag_months ) 
THEN 
  181        IF (get_calendar_type() == no_calendar) 
THEN 
  182           error_message_local = 
'output units of months NOT allowed with no calendar' 
  186     ELSE IF ( output_units == diag_years ) 
THEN 
  187        IF ( get_calendar_type() == no_calendar ) 
THEN 
  188           error_message_local = 
'output units of years NOT allowed with no calendar' 
  190         call get_date(time, cyear, cmonth, cday, chour, cmin, csecond)
 
  191         if (cmonth .eq. 2 .and. cday .eq. 29) 
then 
  197             output_freq, 0, 0, 0, 0, 0, err_msg=error_message_local)
 
  203        error_message_local = 
'illegal output units' 
  206     IF ( error_message_local /= 
'' ) 
THEN 
  207       IF ( fms_error_handler(
'diag_forecast_time_inc',error_message_local,err_msg) ) 
RETURN 
  215     CHARACTER(len=*),   
INTENT(in) :: filename
 
  216     TYPE(time_type),    
INTENT(in) :: current_time
 
  236     INTEGER :: days_per_month(12) = (/31,28,31,30,31,30,31,31,30,31,30,31/)
 
  237     INTEGER :: julian_day, i, position, len, first_percent
 
  238     CHARACTER(len=1) :: width
 
  239     CHARACTER(len=10) :: format
 
  240     CHARACTER(len=20) :: yr
 
  241     CHARACTER(len=20) :: mo
 
  242     CHARACTER(len=20) :: dy
 
  243     CHARACTER(len=20) :: hr
 
  244     CHARACTER(len=20) :: mi
 
  245     CHARACTER(len=20) :: sc
 
  246     CHARACTER(len=128) :: filetail
 
  248     format = 
'("_",i*.*)' 
  249     CALL get_date(current_time, yr1, mo1, dy1, hr1, mi1, sc1)
 
  250     len = len_trim(filename)
 
  251     first_percent = index(filename, 
'%')
 
  252     filetail = filename(first_percent:len)
 
  254     position = index(filetail, 
'yr')
 
  255     IF ( position > 0 ) 
THEN 
  256        width = filetail(position-1:position-1)
 
  258        format(7:9) = width//
'.'//width
 
  259        WRITE(yr, format) yr1_s
 
  266     position = index(filetail, 
'mo')
 
  267     IF ( position > 0 ) 
THEN 
  268        width = filetail(position-1:position-1)
 
  270        format(7:9) = width//
'.'//width
 
  271        WRITE(mo, format) mo1_s
 
  276     IF ( len_trim(mo) > 0 ) 
THEN  
  279     ELSE IF ( len_trim(yr) >0 )  
THEN  
  286              julian_day = julian_day + days_per_month(i)
 
  288           IF ( leap_year(current_time) .AND. mo1 > 2 ) julian_day = julian_day + 1
 
  289           julian_day = julian_day + dy1
 
  294        CALL get_time(current_time, abs_sec, abs_day)
 
  298     position = index(filetail, 
'dy')
 
  299     IF ( position > 0 ) 
THEN 
  300        width = filetail(position-1:position-1)
 
  301        FORMAT(7:9) = width//
'.'//width
 
  302        WRITE(dy, format) dy1_s
 
  307     IF ( len_trim(dy) > 0 ) 
THEN 
  313     position = index(filetail, 
'hr')
 
  314     IF ( position > 0 ) 
THEN 
  315        width = filetail(position-1:position-1)
 
  316        format(7:9) = width//
'.'//width
 
  317        WRITE(hr, format) hr1_s
 
  322     IF ( len_trim(hr) > 0 ) 
THEN 
  328     position = index(filetail, 
'mi')
 
  330        width = filetail(position-1:position-1)
 
  331        format(7:9) = width//
'.'//width
 
  332        WRITE(mi, format) mi1_s
 
  337     IF ( len_trim(mi) > 0 ) 
THEN 
  340        sc1_s = nint(mi2*seconds_per_minute) + sc1
 
  342     position = index(filetail, 
'sc')
 
  343     IF ( position > 0 ) 
THEN 
  344        width = filetail(position-1:position-1)
 
  345        format(7:9) = width//
'.'//width
 
  346        WRITE(sc, format) sc1_s
 
  350     get_time_string = trim(yr)//trim(mo)//trim(dy)//trim(hr)//trim(mi)//trim(sc)
 
  356     TYPE(time_type), 
INTENT(in) :: t2
 
  357     TYPE(time_type), 
INTENT(in) :: t1
 
  358     INTEGER, 
INTENT(in) :: units
 
  360     INTEGER :: dif_seconds, dif_days
 
  361     TYPE(time_type) :: dif_time
 
  363     IF ( t2 < t1 ) 
CALL mpp_error(fatal, 
'diag_util_mod::get_date_dif '//&
 
  364          &
'in variable t2 is less than in variable t1')
 
  368     CALL get_time(dif_time, dif_seconds, dif_days)
 
  370     IF ( units == diag_seconds ) 
THEN 
  372     ELSE IF ( units == diag_minutes ) 
THEN 
  373        get_date_dif = 1440 * dif_days + dif_seconds / seconds_per_minute
 
  374     ELSE IF ( units == diag_hours ) 
THEN 
  375        get_date_dif = 24 * dif_days + dif_seconds / seconds_per_hour
 
  376     ELSE IF ( units == diag_days ) 
THEN 
  378     ELSE IF ( units == diag_months ) 
THEN 
  379        CALL mpp_error(fatal, 
'diag_util_mod::get_date_dif months not supported as output units')
 
  380     ELSE IF ( units == diag_years ) 
THEN 
  381        CALL mpp_error(fatal, 
'diag_util_mod::get_date_dif years not supported as output units')
 
  383        CALL mpp_error(fatal, 
'diag_util_mod::diag_date_dif illegal time units')
 
  390   integer,         
intent(in)    :: time_int(6)
 
  391   type(time_type), 
intent(inout) :: time
 
  408   IF ( get_calendar_type() /= no_calendar ) 
THEN 
  409     IF ( year==0 .OR. month==0 .OR. day==0 ) 
THEN 
  410        call mpp_error(fatal, 
'fms_diag_time_utils_mod::set_time_type'//&
 
  411           &  
'The year/month/day can not equal zero')
 
  413     time = set_date(year, month, day, hour, minute, second)
 
  416     time = set_time(nint(hour*seconds_per_hour)+nint(minute*seconds_per_minute)+second, &
 
  420 end module fms_diag_time_utils_mod
 
logical use_clock_average
.TRUE. if the averaging of variable is done based on the clock For example, if doing daily averages a...
 
character(len=128) function, public get_time_string(filename, current_time)
This function determines a string based on current time. This string is used as suffix in output file...
 
type(time_type) function diag_clock_time_inc(time, output_freq, output_units, err_msg)
Determine the next time data/file is to be written based on the frequency and units using the clock....
 
type(time_type) function diag_forecast_time_inc(time, output_freq, output_units, err_msg)
Determine the next time data/file is to be written based on the frequency and units using forecast ti...
 
subroutine, public set_time_type(time_int, time)
Sets up a time_type based on 6 member array of integers defining the [year month day hour min sec].
 
real function, public get_date_dif(t2, t1, units)
Return the difference between two times in units.
 
logical function, public fms_error_handler(routine, message, err_msg)
Facilitates the control of fatal error conditions.
 
logical function, public leap_year(Time, err_msg)
Returns true if the year corresponding to the input time is a leap year (for default calendar)....
 
subroutine, public get_time(Time, seconds, days, ticks, err_msg)
Returns days and seconds ( < 86400 ) corresponding to a time. err_msg should be checked for any error...
 
subroutine, public get_date(time, year, month, day, hour, minute, second, tick, err_msg)
Gets the date for different calendar types. Given a time_interval, returns the corresponding date und...
 
type(time_type) function, public increment_time(Time, seconds, days, ticks, err_msg, allow_neg_inc)
Increments a time by seconds and days.
 
integer function, public get_calendar_type()
Returns default calendar type for mapping from time to date.
 
Given an input date in year, month, days, etc., creates a time_type that represents this time interva...
 
Given some number of seconds and days, returns the corresponding time_type.
 
Type to represent amounts of time. Implemented as seconds and days to allow for larger intervals.