27 module fms_diag_time_utils_mod
31 use diag_data_mod,
only: end_of_run, every_time, diag_seconds, diag_minutes, diag_hours, diag_days, diag_months, &
33 USE constants_mod,
ONLY: seconds_per_day, seconds_per_hour, seconds_per_minute
40 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')
386 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...
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...
Type to represent amounts of time. Implemented as seconds and days to allow for larger intervals.