25 module get_cal_time_mod
32 no_calendar, thirty_day_months, noleap, julian, gregorian, &
35 use mpp_mod,
only: input_nml_file
36 use platform_mod,
only: r8_kind, r4_kind
43 logical :: module_is_initialized=.false.
54 logical :: allow_calendar_conversion=.true.
56 namelist / get_cal_time_nml / allow_calendar_conversion
60 #include<file_version.h>
162 real(r8_kind),
intent(in) :: time_increment
163 character(len=*),
intent(in) :: units
164 character(len=*),
intent(in) :: calendar
165 logical,
intent(in),
optional :: permit_calendar_conversion
167 integer :: year, month, day, hour, minute, second
168 integer :: i1, increment_seconds, increment_days, increment_years, increment_months
169 real(r8_kind) :: month_fraction
170 integer :: calendar_tm_i, calendar_in_i, ierr, io, logunit
171 logical :: correct_form
172 character(len=32) :: calendar_in_c
173 character(len=64) :: err_msg
174 type(
time_type) :: base_time, base_time_plus_one_yr
176 logical :: permit_conversion_local
177 integer,
parameter :: spd_int = 86400
178 real(r8_kind),
parameter :: spd_real = 86400.0_r8_kind
180 if(.not.module_is_initialized)
then
181 read (input_nml_file, get_cal_time_nml, iostat=io)
186 if(
mpp_pe() == mpp_root_pe())
write (logunit, nml=get_cal_time_nml)
187 module_is_initialized = .true.
190 if(
present(permit_calendar_conversion))
then
191 permit_conversion_local = permit_calendar_conversion
193 permit_conversion_local = allow_calendar_conversion
196 calendar_in_c = lowercase(trim(cut0(calendar)))
198 correct_form = (trim(calendar_in_c)) ==
'noleap' .or. (trim(calendar_in_c)) ==
'365_day' .or. &
199 (trim(calendar_in_c)) ==
'365_days' .or. &
200 (trim(calendar_in_c)) ==
'360_day' .or. (trim(calendar_in_c)) ==
'julian' .or. &
201 (trim(calendar_in_c)) ==
'no_calendar'.or. (trim(calendar_in_c)) ==
'thirty_day_months' .or. &
202 (trim(calendar_in_c)) ==
'gregorian'
204 if(.not.correct_form)
then
205 call error_mesg(
'get_calendar_time',
'"'//trim(calendar_in_c)//
'"'// &
206 ' is not an acceptable calendar attribute. acceptable calendars are: '// &
207 ' noleap, 365_day, 365_days, 360_day, julian, no_calendar, thirty_day_months, gregorian',fatal)
212 if(.not.permit_conversion_local)
then
213 correct_form = (trim(calendar_in_c) ==
'noleap' .and. calendar_tm_i == noleap) .or. &
214 (trim(calendar_in_c) ==
'365_day' .and. calendar_tm_i == noleap) .or. &
215 (trim(calendar_in_c) ==
'365_days' .and. calendar_tm_i == noleap) .or. &
216 (trim(calendar_in_c) ==
'360_day' .and. calendar_tm_i == thirty_day_months) .or. &
217 (trim(calendar_in_c) ==
'thirty_day_months' .and. calendar_tm_i == thirty_day_months) .or. &
218 (trim(calendar_in_c) ==
'julian' .and. calendar_tm_i == julian) .or. &
219 (trim(calendar_in_c) ==
'no_calendar' .and. calendar_tm_i == no_calendar) .or. &
220 (trim(calendar_in_c) ==
'gregorian' .and. calendar_tm_i == gregorian)
221 if(.not.correct_form)
then
222 call error_mesg(
'get_calendar_time',
'calendar not consistent with calendar type in use by time_manager.'// &
223 ' calendar='//trim(calendar_in_c)//
'. Type in use by time_manager='// &
228 if (permit_conversion_local)
then
229 select case (trim(calendar_in_c))
231 calendar_in_i = noleap
233 calendar_in_i = noleap
235 calendar_in_i = noleap
237 calendar_in_i = thirty_day_months
238 case (
'thirty_day_months')
239 calendar_in_i = thirty_day_months
241 calendar_in_i = julian
243 calendar_in_i = no_calendar
245 calendar_in_i = gregorian
248 trim(calendar_in_c)//
' is an invalid calendar type (specified in call to get_calendar_time)',fatal)
251 calendar_in_i = calendar_tm_i
254 correct_form = lowercase(units(1:10)) ==
'days since' .or. &
255 lowercase(units(1:11)) ==
'hours since' .or. &
256 lowercase(units(1:13)) ==
'minutes since' .or. &
257 lowercase(units(1:13)) ==
'seconds since'
259 if(calendar_in_i /= no_calendar)
then
260 correct_form = correct_form .or. &
261 lowercase(units(1:11)) ==
'years since' .or. &
262 lowercase(units(1:12)) ==
'months since'
265 if(.not.correct_form)
then
266 call error_mesg(
'get_calendar_time',trim(units)//
' is an invalid string for units.' // &
267 ' units must begin with a time unit then the word "since"' // &
268 ' Valid time units are: "seconds" "minutes", "hours", "days", and, ' // &
269 ' except when NO_CALENDAR is in effect, "months" and "years"',fatal)
272 if(calendar_in_i /= calendar_tm_i)
then
286 i1 = index(units,
'since') + 5
287 if(calendar_in_i == no_calendar)
then
288 base_time =
set_time(units(i1:len_trim(units)))
290 base_time =
set_date(units(i1:len_trim(units)))
293 if(lowercase(units(1:10)) ==
'days since')
then
294 increment_days = floor(time_increment)
295 increment_seconds = int(spd_real*(time_increment - real(increment_days, r8_kind)))
296 else if(lowercase(units(1:11)) ==
'hours since')
then
297 increment_days = floor(time_increment/24.0_r8_kind)
298 increment_seconds = int(spd_real*(time_increment/24.0_r8_kind - real(increment_days, r8_kind)))
299 else if(lowercase(units(1:13)) ==
'minutes since')
then
300 increment_days = floor(time_increment/1440.0_r8_kind)
301 increment_seconds = int(spd_real*(time_increment/1440.0_r8_kind - real(increment_days, r8_kind)))
302 else if(lowercase(units(1:13)) ==
'seconds since')
then
303 increment_days = floor(time_increment/spd_real)
304 increment_seconds = int(spd_real*(time_increment/spd_real - real(increment_days, r8_kind)))
305 else if(lowercase(units(1:11)) ==
'years since')
then
309 call get_date(base_time, year,month,day,hour,minute,second)
310 base_time =
set_date(year+floor(time_increment) ,month,day,hour,minute,second)
311 base_time_plus_one_yr =
set_date(year+floor(time_increment)+1,month,day,hour,minute,second)
312 call get_time(base_time_plus_one_yr - base_time, second, day)
313 dt = real(day*spd_int+second, r8_kind)*(time_increment-real(floor(time_increment), r8_kind))
314 increment_days = floor(dt/spd_real)
315 increment_seconds = int(dt - real(increment_days*spd_int, r8_kind))
316 else if(lowercase(units(1:12)) ==
'months since')
then
317 month_fraction = time_increment - real(floor(time_increment), r8_kind)
318 increment_years = floor(time_increment/12.0_r8_kind)
319 increment_months = floor(time_increment) - 12*increment_years
320 call get_date(base_time, year,month,day,hour,minute,second)
321 base_time =
set_date(year+increment_years,month+increment_months ,day,hour,minute,second)
322 dt = real( spd_int*
days_in_month(base_time), r8_kind) * month_fraction
323 increment_days = floor(dt/spd_real)
324 increment_seconds = int(dt - real(increment_days, r8_kind)*spd_real)
326 call error_mesg(
'get_calendar_time',
'"'//trim(units)//
'" is not an acceptable units attribute of time.'// &
327 &
' It must begin with: "years since", "months since", "days since", "hours since", "minutes since",'// &
328 &
' or "seconds since"',fatal)
331 if (calendar_in_i /= calendar_tm_i)
then
332 if(calendar_in_i == no_calendar .or. calendar_tm_i == no_calendar)
then
333 call error_mesg(
'get_calendar_time',
'Cannot do calendar conversion because input calendar is '// &
336 ' Conversion cannot be done if either is NO_CALENDAR',fatal)
338 call get_date(base_time,year, month, day, hour, minute, second)
343 if(err_msg /=
'')
then
344 call error_mesg(
'get_calendar_time',
'Error in function get_calendar_time: '//trim(err_msg)// &
345 ' Note that the time_manager is using the '//trim(
valid_calendar_types(calendar_tm_i))//
' calendar '// &
346 'while the calendar type passed to function get_calendar_time is '//calendar_in_c,fatal)
358 real(r4_kind),
intent(in) :: time_increment
359 character(len=*),
intent(in) :: units
360 character(len=*),
intent(in) :: calendar
361 logical,
intent(in),
optional :: permit_calendar_conversion
365 permit_calendar_conversion=permit_calendar_conversion)
370 function cut0(string)
371 character(len=256) :: cut0
372 character(len=*),
intent(in) :: string
378 if(ichar(string(i:i)) == 0 )
then
386 end module get_cal_time_mod
integer function, public check_nml_error(IOSTAT, NML_NAME)
Checks the iostat argument that is returned after reading a namelist and determines if the error code...
subroutine, public write_version_number(version, tag, unit)
Prints to the log file (or a specified unit) the version id string and tag name.
subroutine, public error_mesg(routine, message, level)
Print notes, warnings and error messages; terminates program for warning and error messages....
type(time_type) function get_calendar_time(time_increment, units, calendar, permit_calendar_conversion)
Calculates what a given calendar time would be after a interval of time.
type(time_type) function get_calendar_time_wrap(time_increment, units, calendar, permit_calendar_conversion)
For mixed precision support, just casts to passed in increment to r8.
Added for mixed precision support. Updates force time_manager math to be done with kind=8 reals _wrap...
integer function stdlog()
This function returns the current standard fortran unit numbers for log messages. Log messages,...
integer function mpp_pe()
Returns processor ID.
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...
character(len=24) function, public valid_calendar_types(ncal, err_msg)
Returns a character string that describes the calendar type corresponding to the input integer.
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...
integer function, public days_in_month(Time, err_msg)
Given a time, computes the corresponding date given the selected date time mapping algorithm.
integer function, public get_calendar_type()
Returns default calendar type for mapping from time to date.
subroutine, public set_calendar_type(type, err_msg)
Sets calendar_type for mapping an interval to a date. For the Gregorian calendar, negative years and ...
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.