163real(r8_kind),
intent(in) :: time_increment
164character(len=*),
intent(in) :: units
165character(len=*),
intent(in) :: calendar
166logical,
intent(in),
optional :: permit_calendar_conversion
168integer :: year, month, day, hour, minute, second
169integer :: i1, increment_seconds, increment_days, increment_years, increment_months
170real(r8_kind) :: month_fraction
171integer :: calendar_tm_i, calendar_in_i, ierr, io, logunit
172logical :: correct_form
173character(len=32) :: calendar_in_c
174character(len=64) :: err_msg
175type(
time_type) :: base_time, base_time_plus_one_yr
177logical :: permit_conversion_local
178integer,
parameter :: spd_int = 86400
179real(r8_kind),
parameter :: spd_real = 86400.0_r8_kind
181if(.not.module_is_initialized)
then
182 read (input_nml_file, get_cal_time_nml, iostat=io)
183 ierr = check_nml_error(io,
'get_cal_time_nml')
185 call write_version_number(
"get_cal_time_MOD", version)
187 if(mpp_pe() == mpp_root_pe())
write (logunit, nml=get_cal_time_nml)
188 module_is_initialized = .true.
191if(
present(permit_calendar_conversion))
then
192 permit_conversion_local = permit_calendar_conversion
194 permit_conversion_local = allow_calendar_conversion
197calendar_in_c = lowercase(trim(cut0(calendar)))
199correct_form = (trim(calendar_in_c)) ==
'noleap' .or. (trim(calendar_in_c)) ==
'365_day' .or. &
200 (trim(calendar_in_c)) ==
'365_days' .or. &
201 (trim(calendar_in_c)) ==
'360_day' .or. (trim(calendar_in_c)) ==
'julian' .or. &
202 (trim(calendar_in_c)) ==
'no_calendar'.or. (trim(calendar_in_c)) ==
'thirty_day_months' .or. &
203 (trim(calendar_in_c)) ==
'gregorian'
205if(.not.correct_form)
then
206 call error_mesg(
'get_calendar_time',
'"'//trim(calendar_in_c)//
'"'// &
207 ' is not an acceptable calendar attribute. acceptable calendars are: '// &
208 ' noleap, 365_day, 365_days, 360_day, julian, no_calendar, thirty_day_months, gregorian',fatal)
213if(.not.permit_conversion_local)
then
214 correct_form = (trim(calendar_in_c) ==
'noleap' .and. calendar_tm_i == noleap) .or. &
215 (trim(calendar_in_c) ==
'365_day' .and. calendar_tm_i == noleap) .or. &
216 (trim(calendar_in_c) ==
'365_days' .and. calendar_tm_i == noleap) .or. &
217 (trim(calendar_in_c) ==
'360_day' .and. calendar_tm_i == thirty_day_months) .or. &
218 (trim(calendar_in_c) ==
'thirty_day_months' .and. calendar_tm_i == thirty_day_months) .or. &
219 (trim(calendar_in_c) ==
'julian' .and. calendar_tm_i == julian) .or. &
220 (trim(calendar_in_c) ==
'no_calendar' .and. calendar_tm_i == no_calendar) .or. &
221 (trim(calendar_in_c) ==
'gregorian' .and. calendar_tm_i == gregorian)
222 if(.not.correct_form)
then
223 call error_mesg(
'get_calendar_time',
'calendar not consistent with calendar type in use by time_manager.'// &
224 ' calendar='//trim(calendar_in_c)//
'. Type in use by time_manager='// &
229if (permit_conversion_local)
then
230 select case (trim(calendar_in_c))
232 calendar_in_i = noleap
234 calendar_in_i = noleap
236 calendar_in_i = noleap
238 calendar_in_i = thirty_day_months
239 case (
'thirty_day_months')
240 calendar_in_i = thirty_day_months
242 calendar_in_i = julian
244 calendar_in_i = no_calendar
246 calendar_in_i = gregorian
248 call error_mesg(
'get_calendar_time', &
249 trim(calendar_in_c)//
' is an invalid calendar type (specified in call to get_calendar_time)',fatal)
252 calendar_in_i = calendar_tm_i
255correct_form = lowercase(units(1:10)) ==
'days since' .or. &
256 lowercase(units(1:11)) ==
'hours since' .or. &
257 lowercase(units(1:13)) ==
'minutes since' .or. &
258 lowercase(units(1:13)) ==
'seconds since'
260if(calendar_in_i /= no_calendar)
then
261 correct_form = correct_form .or. &
262 lowercase(units(1:11)) ==
'years since' .or. &
263 lowercase(units(1:12)) ==
'months since'
266if(.not.correct_form)
then
267 call error_mesg(
'get_calendar_time',trim(units)//
' is an invalid string for units.' // &
268 ' units must begin with a time unit then the word "since"' // &
269 ' Valid time units are: "seconds" "minutes", "hours", "days", and, ' // &
270 ' except when NO_CALENDAR is in effect, "months" and "years"',fatal)
273if(calendar_in_i /= calendar_tm_i)
then
287i1 = index(units,
'since') + 5
288if(calendar_in_i == no_calendar)
then
289 base_time =
set_time(units(i1:len_trim(units)))
291 base_time =
set_date(units(i1:len_trim(units)))
294if(lowercase(units(1:10)) ==
'days since')
then
295 increment_days = floor(time_increment)
296 increment_seconds = int(spd_real*(time_increment - real(increment_days, r8_kind)))
297else if(lowercase(units(1:11)) ==
'hours since')
then
298 increment_days = floor(time_increment/24.0_r8_kind)
299 increment_seconds = int(spd_real*(time_increment/24.0_r8_kind - real(increment_days, r8_kind)))
300else if(lowercase(units(1:13)) ==
'minutes since')
then
301 increment_days = floor(time_increment/1440.0_r8_kind)
302 increment_seconds = int(spd_real*(time_increment/1440.0_r8_kind - real(increment_days, r8_kind)))
303else if(lowercase(units(1:13)) ==
'seconds since')
then
304 increment_days = floor(time_increment/spd_real)
305 increment_seconds = int(spd_real*(time_increment/spd_real - real(increment_days, r8_kind)))
306else if(lowercase(units(1:11)) ==
'years since')
then
310 call get_date(base_time, year,month,day,hour,minute,second)
311 base_time =
set_date(year+floor(time_increment) ,month,day,hour,minute,second)
312 base_time_plus_one_yr =
set_date(year+floor(time_increment)+1,month,day,hour,minute,second)
313 call get_time(base_time_plus_one_yr - base_time, second, day)
314 dt = real(day*spd_int+second, r8_kind)*(time_increment-real(floor(time_increment), r8_kind))
315 increment_days = floor(dt/spd_real)
316 increment_seconds = int(dt - real(increment_days*spd_int, r8_kind))
317else if(lowercase(units(1:12)) ==
'months since')
then
318 month_fraction = time_increment - real(floor(time_increment), r8_kind)
319 increment_years = floor(time_increment/12.0_r8_kind)
320 increment_months = floor(time_increment) - 12*increment_years
321 call get_date(base_time, year,month,day,hour,minute,second)
322 base_time =
set_date(year+increment_years,month+increment_months ,day,hour,minute,second)
323 dt = real( spd_int*
days_in_month(base_time), r8_kind) * month_fraction
324 increment_days = floor(dt/spd_real)
325 increment_seconds = int(dt - real(increment_days, r8_kind)*spd_real)
327 call error_mesg(
'get_calendar_time',
'"'//trim(units)//
'" is not an acceptable units attribute of time.'// &
328 &
' It must begin with: "years since", "months since", "days since", "hours since", "minutes since",'// &
329 &
' or "seconds since"',fatal)
332if (calendar_in_i /= calendar_tm_i)
then
333 if(calendar_in_i == no_calendar .or. calendar_tm_i == no_calendar)
then
334 call error_mesg(
'get_calendar_time',
'Cannot do calendar conversion because input calendar is '// &
337 ' Conversion cannot be done if either is NO_CALENDAR',fatal)
339 call get_date(base_time,year, month, day, hour, minute, second)
344 if(err_msg /=
'')
then
345 call error_mesg(
'get_calendar_time',
'Error in function get_calendar_time: '//trim(err_msg)// &
346 ' Note that the time_manager is using the '//trim(
valid_calendar_types(calendar_tm_i))//
' calendar '// &
347 'while the calendar type passed to function get_calendar_time is '//calendar_in_c,fatal)