A software package that provides a set of simple interfaces for modelers to perform computations related to time and dates.
constants_mod
fms_mod
| Name | Type | Value | Units | Description |
|---|---|---|---|---|
| time_type | derived type | --- | --- | Derived-type data variable used to store time and date quantities. It contains three PRIVATE variables: days, seconds and ticks. |
1. set_time (seconds, days, ticks, err_msg)
2. set_time (time_string, err_msg, allow_rounding)
| seconds |
A number of seconds.
[integer, dimension(scalar)] |
| days |
A number of days.
[integer, dimension(scalar)] |
| ticks |
A number of ticks.
[integer, optional, dimension(scalar)] |
| time_string |
Contains days and seconds separated by a single blank.
days must be integer, seconds may be integer or real.
Examples: '100 43200' '100 43200.50'
[character] |
| allow_rounding |
When .true., any fractions of a second will be rounded off to the nearest tick.
When .false., it is a fatal error if the second fraction cannot be exactly
represented by a number of ticks.
[logical, optional] [Default: .true.] |
| err_msg |
When present, and when non-blank, a fatal error condition as been detected.
The string itself is an error message.
It is recommended that, when err_msg is present in the call
to this routine, the next line of code should be something
similar to this:
if(err_msg /= '') call error_mesg('my_routine','additional info: '//trim(err_msg),FATAL)
[character, optional, dimension(scalar)] |
| set_time |
A time interval corresponding to this number of days and seconds.
[, dimension] [Default: ] |
get_time (time, seconds, days, ticks, err_msg)
| time |
A time interval.
[time_type] |
| seconds |
A number of seconds.
[integer, dimension(scalar)] |
| days |
A number of days.
[integer, dimension(scalar)] |
| ticks |
A number of ticks.
[integer, optional, dimension(scalar)] |
| err_msg |
When present, and when non-blank, a fatal error condition as been detected.
The string itself is an error message.
It is recommended that, when err_msg is present in the call
to this routine, the next line of code should be something
similar to this:
if(err_msg /= '') call error_mesg('my_routine','additional info: '//trim(err_msg),FATAL)
[character, optional, dimension(scalar)] |
increment_time (time, seconds, days, ticks, err_msg, allow_neg_inc)
| time |
A time interval.
[time_type, dimension(scalar)] |
| seconds |
Increment of seconds.
[integer, dimension(scalar)] |
| days |
Increment of days.
[integer, optional, dimension(scalar)] |
| ticks |
Increment of ticks.
[integer, optional, dimension(scalar)] |
| allow_neg_inc |
When .false., it is a fatal error if any of the input time increments are negative.
This mimics the behavior of lima and earlier revisions.
[logical, optional, dimension(scalar)] [Default: .true.] |
| increment_time |
A time that adds this increment to the input time.
A negative result is a fatal error.
[time_type, dimension(scalar)] |
| err_msg |
When present, and when non-blank, a fatal error condition as been detected.
The string itself is an error message.
It is recommended that, when err_msg is present in the call
to this routine, the next line of code should be something
similar to this:
if(err_msg /= '') call error_mesg('my_routine','additional info: '//trim(err_msg),FATAL)
[character, optional, dimension(scalar)] |
decrement_time (time, seconds, days, ticks, err_msg, allow_neg_inc)
| time |
A time interval.
[time_type, dimension(scalar)] |
| seconds |
Decrement of seconds.
[integer, dimension(scalar)] |
| days |
Decrement of days.
[integer, optional, dimension(scalar)] |
| ticks |
Decrement of ticks.
[integer, optional, dimension(scalar)] |
| allow_neg_inc |
When .false., it is a fatal error if any of the input time increments are negative.
This mimics the behavior of lima and earlier revisions.
[logical, optional, dimension(scalar)] [Default: .true.] |
| decrement_time |
A time that subtracts this decrement from an input time.
A negative result is a fatal error.
[time_type] |
| err_msg |
When present, and when non-blank, a fatal error condition as been detected.
The string itself is an error message.
It is recommended that, when err_msg is present in the call
to this routine, the next line of code should be something
similar to this:
if(err_msg /= '') call error_mesg('my_routine','additional info: '//trim(err_msg),FATAL)
[character, optional, dimension(scalar)] |
time_gt operator(>)
| time1 |
A time interval.
[time_type, dimension] |
| time2 |
A time interval.
[time_type, dimension] |
|
Returns true if time1 > time2
[logical, dimension] [Default: ] |
time_ge; operator(>=)
| time1 |
A time interval.
[time_type, dimension] |
| time2 |
A time interval.
[time_type, dimension] |
|
Returns true if time1 >= time2
[logical, dimension] [Default: ] |
time_lt; operator(<)
| time1 |
A time interval.
[time_type, dimension] |
| time2 |
A time interval.
[time_type, dimension] |
|
Returns true if time1 < time2
[logical, dimension] [Default: ] |
time_le; operator(<=)
| time1 |
A time interval.
[time_type, dimension] |
| time2 |
A time interval.
[time_type, dimension] |
|
Returns true if time1 <= time2
[logical, dimension] [Default: ] |
time_eq; operator(==)
| time1 |
A time interval.
[time_type, dimension] |
| time2 |
A time interval.
[time_type, dimension] |
|
Returns true if time1 == time2
[logical, dimension] [Default: ] |
time_ne; operator(/=)
| time1 |
A time interval.
[time_type, dimension] |
| time2 |
A time interval.
[time_type, dimension] |
|
Returns true if time1 /= time2
[logical, dimension] [Default: ] |
time_plus; operator(+)
| time1 |
A time interval.
[time_type, dimension] |
| time2 |
A time interval.
[time_type, dimension] |
|
Returns sum of two time_types.
[time_type, dimension] [Default: ] |
time_minus; operator(-)
time_minus; operator(-)
| time1 |
A time interval.
[time_type, dimension] |
| time2 |
A time interval.
[time_type, dimension] |
|
Returns difference of two time_types.
[time_type, dimension] [Default: ] |
time_scalar_mult; operator(*)
| time |
A time interval.
[time_type, dimension] |
| n |
A time interval.
[integer, dimension] |
|
Returns time multiplied by integer factor n.
[time_type, dimension] [Default: ] |
scalar_time_mult; operator(*)
| time | A time interval. [time_type, dimension] |
| n | An integer. [integer, dimension] |
|
Returns time multiplied by integer factor n.
[time_type, dimension] [Default: ] |
time_divide; operator(/)
| time1 |
A time interval.
[time_type, dimension] |
| time2 |
A time interval.
[time_type, dimension] |
|
Returns the largest integer, n, for which time1 >= time2 * n.
[integer, dimension] [Default: ] |
time_real_divide; operator(//)
| time1 |
A time interval.
[time_type, dimension] |
| time2 |
A time interval.
[time_type, dimension] |
|
Returns the double precision quotient of two times
[integer, dimensiondouble precision] [Default: ] |
time_assignment; assignment(=)
| time2 |
A time type variable.
[time_type, dimension] |
| time1 |
A time type variable.
[time_type, dimension] |
time_type_to_real (time)
| time |
A time interval.
[time_type, dimension] |
real_to_time_type (x, err_msg)
| x |
A real number of seconds
[real, dimension] |
| err_msg |
When present, and when non-blank, a fatal error condition as been detected.
The string itself is an error message.
It is recommended that, when err_msg is present in the call
to this routine, the next line of code should be something
similar to this:
if(err_msg /= '') call error_mesg('my_routine','additional info: '//trim(err_msg),FATAL)
[character, optional, dimension(scalar)] |
| real_to_time_type |
[time_type] |
time_scalar_divide; operator(/)
| time |
A time interval.
[time_type, dimension] |
| n |
An integer factor.
[integer, dimension] |
|
Returns the largest time, t, for which n * t <= time.
[integer, dimensiondouble precision] [Default: ] |
interval_alarm (time, time_interval, alarm, alarm_interval)
| time | Current time. [time_type] |
| time_interval | A time interval. [time_type] |
| alarm_interval | A time interval. [time_type] |
| alarm |
An alarm time, which is incremented by the alarm_interval
if the function is true.
[time_type] |
| interval_alarm |
Returns either True or false.
[logical] |
repeat_alarm (time, alarm_frequency, alarm_length)
| time | Current time. [time_type] |
| alarm_frequency |
A time interval for alarm_frequency.
[time_type] |
| alarm_length |
A time interval for alarm_length.
[time_type] |
| repeat_alarm |
Returns either True or false.
[logical] |
set_calendar_type (type, err_msg)
| type |
A constant number for setting the calendar type.
[integer, dimension(scalar)] [Default: NO_CALENDAR] |
| err_msg |
When present, and when non-blank, a fatal error condition as been detected.
The string itself is an error message.
It is recommended that, when err_msg is present in the call
to this routine, the next line of code should be something
similar to this:
if(err_msg /= '') call error_mesg('my_routine','additional info: '//trim(err_msg),FATAL)
[character, optional, dimension(scalar)] |
get_calendar_type ()
call set_ticks_per_second (ticks_per_second)
| type |
[integer, dimension(scalar)] [Default: 1] |
ticks_per_second = get_ticks_per_second ()
get_date (time, year, month, day, hour, minute, second, tick, err_msg)
| time | A time interval. [time_type] |
| year |
[integer] |
| month |
[integer] |
| day |
[integer] |
| hour |
[integer] |
| minute |
[integer] |
| second |
[integer] |
| tick |
[integer, optional] |
| err_msg |
When present, and when non-blank, a fatal error condition as been detected.
The string itself is an error message.
It is recommended that, when err_msg is present in the call
to this routine, the next line of code should be something
similar to this:
if(err_msg /= '') call error_mesg('my_routine','additional info: '//trim(err_msg),FATAL)
[character, optional, dimension(scalar)] |
1. set_date (year, month, day, hours, minute, second, tick, err_msg)
2. set_date _c(time_string, zero_year_warning, err_msg, allow_rounding) time_string is a character string containing a date formatted according to CF conventions. e.g. '1980-12-31 23:59:59.9'
| time | A time interval. [time_type] |
| year |
[integer] |
| month |
[integer] |
| day |
[integer] |
| hour |
[integer] |
| minute |
[integer] |
| second |
[integer] |
| tick |
[integer] |
| zero_year_warning |
If the year number is zero, it will be silently changed to one,
unless zero_year_warning=.true., in which case a WARNING message
will also be issued.
[logical] |
| allow_rounding |
When .true., any fractions of a second will be rounded off to the nearest tick.
When .false., it is a fatal error if the second fraction cannot be exactly
represented by a number of ticks.
[logical, optional] [Default: .true.] |
| err_msg |
When present, and when non-blank, a fatal error condition as been detected.
The string itself is an error message.
It is recommended that, when err_msg is present in the call
to this routine, the next line of code should be something
similar to this:
if(err_msg /= '') call error_mesg('my_routine','additional info: '//trim(err_msg),FATAL)
[character, optional, dimension(scalar)] |
| set_date | A time interval. [time_type] |
increment_date (time, years, months, days, hours, minutes, seconds, ticks, err_msg)
| time | A time interval. [time_type] |
| years | An increment of years. [integer] |
| months | An increment of months. [integer] |
| days | An increment of days. [integer] |
| hours | An increment of hours. [integer] |
| minutes | An increment of minutes. [integer] |
| seconds | An increment of seconds. [integer] |
| ticks | An increment of ticks. [integer] |
| allow_neg_inc |
When .false., it is a fatal error if any of the input time increments are negative.
This mimics the behavior of lima and earlier revisions.
[logical, optional, dimension(scalar)] [Default: .true.] |
| err_msg |
When present, and when non-blank, a fatal error condition as been detected.
The string itself is an error message.
It is recommended that, when err_msg is present in the call
to this routine, the next line of code should be something
similar to this:
if(err_msg /= '') call error_mesg('my_routine','additional info: '//trim(err_msg),FATAL)
[character, optional, dimension(scalar)] |
| increment_date | A new time based on the input
time interval and the calendar type.
[time_type] |
decrement_date (time, years, months, days, hours, minutes, seconds, ticks, err_msg))
| time | A time interval. [time_type] |
| years | An decrement of years. [integer] |
| months | An decrement of months. [integer] |
| days | An decrement of days. [integer] |
| hours | An decrement of hours. [integer] |
| minutes | An decrement of minutes. [integer] |
| seconds | An decrement of seconds. [integer] |
| ticks | An decrement of ticks. [integer] |
| allow_neg_inc |
When .false., it is a fatal error if any of the input time increments are negative.
This mimics the behavior of lima and earlier revisions.
[logical, optional, dimension(scalar)] [Default: .true.] |
| err_msg |
When present, and when non-blank, a fatal error condition as been detected.
The string itself is an error message.
It is recommended that, when err_msg is present in the call
to this routine, the next line of code should be something
similar to this:
if(err_msg /= '') call error_mesg('my_routine','additional info: '//trim(err_msg),FATAL)
[character, optional, dimension(scalar)] |
| decrement_date | A new time based on the input
time interval and the calendar type.
[time_type] |
days_in_month (time)
| time | A time interval. [time_type, dimension] |
| days_in_month |
The number of days in the month given the selected time
mapping algorithm.
[integer, dimension] [Default: ] |
leap_year (time)
| time | A time interval. [time_type, dimension] |
| leap_year |
true if the year corresponding to the input time is a leap year.
[calendar_type, dimension] [Default: ] |
length_of_year ()
days_in_year (Time)
| Time | A time interval. [time_type] |
| The number of days in this year for the default calendar type. |
month_name (n)
| n | Month number. [integer] |
| month_name |
The character string associated with a month.
All calendars have 12 months and return full
month names, not abreviations.
[character(len=9)] |
time_manager_init ()
print_time (time,str,unit)
| time | Time that will be printed. [time_type] |
| str |
Character string that precedes the printed time or date.
[character (len=*)] [Default: TIME: or DATE:] |
| unit |
Unit number for printed output. The default unit is stdout.
[integer] |
print_date (time,str,unit)
| time | Time that will be printed. [time_type] |
| str |
Character string that precedes the printed time or date.
[character (len=*)] [Default: TIME: or DATE:] |
| unit |
Unit number for printed output. The default unit is stdout.
[integer] |
| ncal |
An integer corresponding to a valid calendar type.
[integer] |
| err_msg |
When present, and when non-blank, a fatal error condition as been detected.
The string itself is an error message.
It is recommended that, when err_msg is present in the call
to this routine, the next line of code should be something
similar to this:
if(err_msg /= '') call error_mesg('my_routine','additional info: '//trim(err_msg),FATAL)
[character, optional, dimension(scalar)] |
| valid_calendar_types |
A character string describing the calendar type.
[character(len=24)] |
use time_manager_mod
implicit none
type(time_type) :: dt, init_date, astro_base_date, time, final_date
type(time_type) :: next_rad_time, mid_date
type(time_type) :: repeat_alarm_freq, repeat_alarm_length
integer :: num_steps, i, days, months, years, seconds, minutes, hours
integer :: months2, length
real :: astro_days
Set calendar type
call set_calendar_type(THIRTY_DAY_MONTHS)
call set_calendar_type(JULIAN)
call set_calendar_type(NOLEAP)
Set timestep
dt = set_time(1100, 0)
Set initial date
init_date = set_date(1992, 1, 1)
Set date for astronomy delta calculation
astro_base_date = set_date(1970, 1, 1, 12, 0, 0)
Copy initial time to model current time
time = init_date
Determine how many steps to do to run one year
final_date = increment_date(init_date, years = 1)
num_steps = (final_date - init_date) / dt
write(*, *) 'Number of steps is' , num_steps
Want to compute radiation at initial step, then every two hours
next_rad_time = time + set_time(7200, 0)
Test repeat alarm
repeat_alarm_freq = set_time(0, 1)
repeat_alarm_length = set_time(7200, 0)
Loop through a year
do i = 1, num_steps
Increment time
time = time + dt
Test repeat alarm
if(repeat_alarm(time, repeat_alarm_freq, repeat_alarm_length)) &
write(*, *) 'REPEAT ALARM IS TRUE'
Should radiation be computed? Three possible tests.
First test assumes exact interval; just ask if times are equal
if(time == next_rad_time) then
Second test computes rad on last time step that is <= radiation time
if((next_rad_time - time) < dt .and. time < next_rad) then
Third test computes rad on time step closest to radiation time
if(interval_alarm(time, dt, next_rad_time, set_time(7200, 0))) then
call get_date(time, years, months, days, hours, minutes, seconds)
write(*, *) days, month_name(months), years, hours, minutes, seconds
Need to compute real number of days between current time and astro_base
call get_time(time - astro_base_date, seconds, days)
astro_days = days + seconds / 86400.
write(*, *) 'astro offset ', astro_days
end if
Can compute daily, monthly, yearly, hourly, etc. diagnostics as for rad
Example: do diagnostics on last time step of this month
call get_date(time + dt, years, months2, days, hours, minutes, seconds)
call get_date(time, years, months, days, hours, minutes, seconds)
if(months /= months2) then
write(*, *) 'last timestep of month'
write(*, *) days, months, years, hours, minutes, seconds
endif
Example: mid-month diagnostics; inefficient to make things clear
length = days_in_month(time)
call get_date(time, years, months, days, hours, minutes, seconds)
mid_date = set_date(years, months, 1) + set_time(0, length) / 2
if(time < mid_date .and. (mid_date - time) < dt) then
write(*, *) 'mid-month time'
write(*, *) days, months, years, hours, minutes, seconds
endif
end do
end program time_main2