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
48 TYPE(time_type) FUNCTION diag_time_inc(time, output_freq, output_units, err_msg)
49 TYPE(time_type),
INTENT(in) :: time
50 INTEGER,
INTENT(in) :: output_freq
51 INTEGER,
INTENT(in) :: output_units
52 CHARACTER(len=*),
INTENT(out),
OPTIONAL :: err_msg
61 end function diag_time_inc
67 TYPE(time_type),
INTENT(in) :: time
68 INTEGER,
INTENT(in) :: output_freq
69 INTEGER,
INTENT(in) :: output_units
70 CHARACTER(len=*),
INTENT(out),
OPTIONAL :: err_msg
73 CHARACTER(len=128) :: error_message_local
80 type(time_type) :: my_time
82 IF (
PRESENT(err_msg) ) err_msg =
''
83 error_message_local =
''
85 IF ( get_calendar_type() == no_calendar)
then
86 error_message_local =
'If using use_clock_average =.TRUE., your calendar must be set.'
87 IF ( fms_error_handler(
'diag_clock_time_inc',error_message_local,err_msg) )
RETURN
93 IF ( output_freq == end_of_run .OR. output_freq == every_time )
THEN
98 call get_date(time, cyear, cmonth, cday, chour, cmin, csecond)
100 select case (output_units)
102 my_time = set_date(cyear, cmonth, cday, chour, cmin, csecond)
103 diag_clock_time_inc = increment_date(my_time, 0, 0, 0, 0, 0, output_freq, err_msg=error_message_local)
105 my_time = set_date(cyear, cmonth, cday, chour, cmin, 0)
106 diag_clock_time_inc = increment_date(my_time, 0, 0, 0, 0, output_freq, 0, err_msg=error_message_local)
108 my_time = set_date(cyear, cmonth, cday, chour, 0, 0)
109 diag_clock_time_inc = increment_date(my_time, 0, 0, 0, output_freq, 0, 0, err_msg=error_message_local)
111 my_time = set_date(cyear, cmonth, cday, 0, 0, 0)
112 diag_clock_time_inc = increment_date(my_time, 0, 0, output_freq, 0, 0, 0, err_msg=error_message_local)
114 my_time = set_date(cyear, cmonth, 1, 0, 0, 0)
115 diag_clock_time_inc = increment_date(my_time, 0, output_freq, 0, 0, 0, 0, err_msg=error_message_local)
117 my_time = set_date(cyear, 1, 1, 0, 0, 0)
118 diag_clock_time_inc = increment_date(my_time, output_freq, 0, 0, 0, 0, 0, err_msg=error_message_local)
127 TYPE(time_type),
INTENT(in) :: time
128 INTEGER,
INTENT(in) :: output_freq
129 INTEGER,
INTENT(in) :: output_units
130 CHARACTER(len=*),
INTENT(out),
OPTIONAL :: err_msg
134 CHARACTER(len=128) :: error_message_local
143 IF (
PRESENT(err_msg) ) err_msg =
''
144 error_message_local =
''
149 IF ( output_freq == end_of_run .OR. output_freq == every_time )
THEN
155 IF ( output_units == diag_seconds )
THEN
156 IF ( get_calendar_type() == no_calendar )
THEN
161 ELSE IF ( output_units == diag_minutes )
THEN
162 IF ( get_calendar_type() == no_calendar )
THEN
164 &err_msg=error_message_local)
168 ELSE IF ( output_units == diag_hours )
THEN
169 IF ( get_calendar_type() == no_calendar )
THEN
171 &err_msg=error_message_local)
175 ELSE IF ( output_units == diag_days )
THEN
176 IF (get_calendar_type() == no_calendar)
THEN
181 ELSE IF ( output_units == diag_months )
THEN
182 IF (get_calendar_type() == no_calendar)
THEN
183 error_message_local =
'output units of months NOT allowed with no calendar'
187 ELSE IF ( output_units == diag_years )
THEN
188 IF ( get_calendar_type() == no_calendar )
THEN
189 error_message_local =
'output units of years NOT allowed with no calendar'
191 call get_date(time, cyear, cmonth, cday, chour, cmin, csecond)
192 if (cmonth .eq. 2 .and. cday .eq. 29)
then
198 output_freq, 0, 0, 0, 0, 0, err_msg=error_message_local)
204 error_message_local =
'illegal output units'
207 IF ( error_message_local /=
'' )
THEN
208 IF ( fms_error_handler(
'diag_forecast_time_inc',error_message_local,err_msg) )
RETURN
216 CHARACTER(len=*),
INTENT(in) :: filename
217 TYPE(time_type),
INTENT(in) :: current_time
237 INTEGER :: days_per_month(12) = (/31,28,31,30,31,30,31,31,30,31,30,31/)
238 INTEGER :: julian_day, i, position, len, first_percent
239 CHARACTER(len=1) :: width
240 CHARACTER(len=10) :: 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=128) :: filetail
249 format =
'("_",i*.*)'
250 CALL get_date(current_time, yr1, mo1, dy1, hr1, mi1, sc1)
251 len = len_trim(filename)
252 first_percent = index(filename,
'%')
253 filetail = filename(first_percent:len)
255 position = index(filetail,
'yr')
256 IF ( position > 0 )
THEN
257 width = filetail(position-1:position-1)
259 format(7:9) = width//
'.'//width
260 WRITE(yr, format) yr1_s
267 position = index(filetail,
'mo')
268 IF ( position > 0 )
THEN
269 width = filetail(position-1:position-1)
271 format(7:9) = width//
'.'//width
272 WRITE(mo, format) mo1_s
277 IF ( len_trim(mo) > 0 )
THEN
280 ELSE IF ( len_trim(yr) >0 )
THEN
287 julian_day = julian_day + days_per_month(i)
289 IF ( leap_year(current_time) .AND. mo1 > 2 ) julian_day = julian_day + 1
290 julian_day = julian_day + dy1
295 CALL get_time(current_time, abs_sec, abs_day)
299 position = index(filetail,
'dy')
300 IF ( position > 0 )
THEN
301 width = filetail(position-1:position-1)
302 FORMAT(7:9) = width//
'.'//width
303 WRITE(dy, format) dy1_s
308 IF ( len_trim(dy) > 0 )
THEN
314 position = index(filetail,
'hr')
315 IF ( position > 0 )
THEN
316 width = filetail(position-1:position-1)
317 format(7:9) = width//
'.'//width
318 WRITE(hr, format) hr1_s
323 IF ( len_trim(hr) > 0 )
THEN
329 position = index(filetail,
'mi')
331 width = filetail(position-1:position-1)
332 format(7:9) = width//
'.'//width
333 WRITE(mi, format) mi1_s
338 IF ( len_trim(mi) > 0 )
THEN
341 sc1_s = nint(mi2*seconds_per_minute) + sc1
343 position = index(filetail,
'sc')
344 IF ( position > 0 )
THEN
345 width = filetail(position-1:position-1)
346 format(7:9) = width//
'.'//width
347 WRITE(sc, format) sc1_s
351 get_time_string = trim(yr)//trim(mo)//trim(dy)//trim(hr)//trim(mi)//trim(sc)
357 TYPE(time_type),
INTENT(in) :: t2
358 TYPE(time_type),
INTENT(in) :: t1
359 INTEGER,
INTENT(in) :: units
361 INTEGER :: dif_seconds, dif_days
362 TYPE(time_type) :: dif_time
364 IF ( t2 < t1 )
CALL mpp_error(fatal,
'diag_util_mod::get_date_dif '//&
365 &
'in variable t2 is less than in variable t1')
369 CALL get_time(dif_time, dif_seconds, dif_days)
371 IF ( units == diag_seconds )
THEN
373 ELSE IF ( units == diag_minutes )
THEN
374 get_date_dif = 1440 * dif_days + dif_seconds / seconds_per_minute
375 ELSE IF ( units == diag_hours )
THEN
376 get_date_dif = 24 * dif_days + dif_seconds / seconds_per_hour
377 ELSE IF ( units == diag_days )
THEN
379 ELSE IF ( units == diag_months )
THEN
380 CALL mpp_error(fatal,
'diag_util_mod::get_date_dif months not supported as output units')
381 ELSE IF ( units == diag_years )
THEN
382 CALL mpp_error(fatal,
'diag_util_mod::get_date_dif years not supported as output units')
384 CALL mpp_error(fatal,
'diag_util_mod::diag_date_dif illegal time units')
391 integer,
intent(in) :: time_int(6)
392 type(time_type),
intent(inout) :: time
409 IF ( get_calendar_type() /= no_calendar )
THEN
410 IF ( year==0 .OR. month==0 .OR. day==0 )
THEN
411 call mpp_error(fatal,
'fms_diag_time_utils_mod::set_time_type'//&
412 &
'The year/month/day can not equal zero')
414 time = set_date(year, month, day, hour, minute, second)
417 time = set_time(nint(hour*seconds_per_hour)+nint(minute*seconds_per_minute)+second, &
421 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.