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 LOGICAL :: field_written
239 CHARACTER(len=1) :: width
240 CHARACTER(len=6) :: format
241 CHARACTER(len=20) :: yr
242 CHARACTER(len=20) :: mo
243 CHARACTER(len=20) :: dy
244 CHARACTER(len=20) :: hr
245 CHARACTER(len=20) :: mi
246 CHARACTER(len=20) :: sc
247 CHARACTER(len=20) :: fields(6)
248 CHARACTER(len=128) :: filetail
251 CALL get_date(current_time, yr1, mo1, dy1, hr1, mi1, sc1)
252 len = len_trim(filename)
253 first_percent = index(filename,
'%')
254 filetail = filename(first_percent:len)
256 position = index(filetail,
'yr')
257 IF ( position > 0 )
THEN
258 width = filetail(position-1:position-1)
260 format(3:5) = width//
'.'//width
261 WRITE(yr, format) yr1_s
268 position = index(filetail,
'mo')
269 IF ( position > 0 )
THEN
270 width = filetail(position-1:position-1)
272 format(3:5) = width//
'.'//width
273 WRITE(mo, format) mo1_s
278 IF ( len_trim(mo) > 0 )
THEN
281 ELSE IF ( len_trim(yr) >0 )
THEN
288 julian_day = julian_day + days_per_month(i)
290 IF ( leap_year(current_time) .AND. mo1 > 2 ) julian_day = julian_day + 1
291 julian_day = julian_day + dy1
296 CALL get_time(current_time, abs_sec, abs_day)
300 position = index(filetail,
'dy')
301 IF ( position > 0 )
THEN
302 width = filetail(position-1:position-1)
303 FORMAT(3:5) = width//
'.'//width
304 WRITE(dy, format) dy1_s
309 IF ( len_trim(dy) > 0 )
THEN
315 position = index(filetail,
'hr')
316 IF ( position > 0 )
THEN
317 width = filetail(position-1:position-1)
318 format(3:5) = width//
'.'//width
319 WRITE(hr, format) hr1_s
324 IF ( len_trim(hr) > 0 )
THEN
330 position = index(filetail,
'mi')
332 width = filetail(position-1:position-1)
333 format(3:5) = width//
'.'//width
334 WRITE(mi, format) mi1_s
339 IF ( len_trim(mi) > 0 )
THEN
342 sc1_s = nint(mi2*seconds_per_minute) + sc1
344 position = index(filetail,
'sc')
345 IF ( position > 0 )
THEN
346 width = filetail(position-1:position-1)
347 format(3:5) = width//
'.'//width
348 WRITE(sc, format) sc1_s
354 fields(1) = yr; fields(2) = mo; fields(3) = dy
355 fields(4) = hr; fields(5) = mi; fields(6) = sc
357 field_written = .false.
358 DO i = 1,
SIZE(fields)
359 IF ( len_trim(fields(i)) == 0 ) cycle
360 IF ( field_written )
THEN
364 field_written = .true.
372 TYPE(time_type),
INTENT(in) :: t2
373 TYPE(time_type),
INTENT(in) :: t1
374 INTEGER,
INTENT(in) :: units
376 INTEGER :: dif_seconds, dif_days
377 TYPE(time_type) :: dif_time
379 IF ( t2 < t1 )
CALL mpp_error(fatal,
'diag_util_mod::get_date_dif '//&
380 &
'in variable t2 is less than in variable t1')
384 CALL get_time(dif_time, dif_seconds, dif_days)
386 IF ( units == diag_seconds )
THEN
388 ELSE IF ( units == diag_minutes )
THEN
389 get_date_dif = 1440 * dif_days + dif_seconds / seconds_per_minute
390 ELSE IF ( units == diag_hours )
THEN
391 get_date_dif = 24 * dif_days + dif_seconds / seconds_per_hour
392 ELSE IF ( units == diag_days )
THEN
394 ELSE IF ( units == diag_months )
THEN
395 CALL mpp_error(fatal,
'diag_util_mod::get_date_dif months not supported as output units')
396 ELSE IF ( units == diag_years )
THEN
397 CALL mpp_error(fatal,
'diag_util_mod::get_date_dif years not supported as output units')
399 CALL mpp_error(fatal,
'diag_util_mod::diag_date_dif illegal time units')
406 integer,
intent(in) :: time_int(6)
407 type(time_type),
intent(inout) :: time
424 IF ( get_calendar_type() /= no_calendar )
THEN
425 IF ( year==0 .OR. month==0 .OR. day==0 )
THEN
426 call mpp_error(fatal,
'fms_diag_time_utils_mod::set_time_type'//&
427 &
'The year/month/day can not equal zero')
429 time = set_date(year, month, day, hour, minute, second)
432 time = set_time(nint(hour*seconds_per_hour)+nint(minute*seconds_per_minute)+second, &
436 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=16) wildcard_filename_separator
String inserted between each subsequent substituted time field when using a wildcard (%) file name.
character(len=16) wildcard_filename_prefix
String inserted immediately before the first substituted time field when using a wildcard (%) file na...
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.