PUBLIC INTERFACE ~ PUBLIC DATA ~ PUBLIC ROUTINES ~ NAMELIST ~ DIAGNOSTIC FIELDS ~ ERROR MESSAGES ~ REFERENCES ~ NOTES

Module time_manager_mod

Contact:  fms
Reviewers: 
Change History: WebCVS Log


OVERVIEW

A software package that provides a set of simple interfaces for modelers to perform computations related to time and dates.

The changes between the lima revision and this revision are more extensive that all those between antwerp and lima. A brief description of these changes follows.

1) Added option to set the smallest time increment to something less than one second. This is controlled by calling the pubic subroutine set_ticks_per_second.

2) Gregorian calendar fixed.

3) Optional error flag added to calling arguments of public routines. This allows the using routine to terminate the program. It is likely that more diagnostic information is available from the user than from time_manager alone. If the error flag is present then it is the responsibility of the using routine to test it and add additional information to the error message.

4) Removed the restriction that time increments be positive in routines that increment or decrement time and date. The option to prohibit negative increments can be turned on via optional argument.

5) subroutine set_date_c modified to handle strings that include only hours or only hours and minutes. This complies with CF convensions.

6) Made calendar specific routines private. They are not used, and should not be used, by any using code.

7) Error messages made more informative.

The module defines a type that can be used to represent discrete times (accurate to one second) and to map these times into dates using a variety of calendars. A time is mapped to a date by representing the time with respect to an arbitrary base date (refer to NOTES section for the base date setting).

The time_manager provides a single defined type, time_type, which is used to store time and date quantities. A time_type is a positive definite quantity that represents an interval of time. It can be most easily thought of as representing the number of seconds in some time interval. A time interval can be mapped to a date under a given calendar definition by using it to represent the time that has passed since some base date. A number of interfaces are provided to operate on time_type variables and their associated calendars. Time intervals can be as large as n days where n is the largest number represented by the default integer type on a compiler. This is typically considerably greater than 10 million years (assuming 32 bit integer representation) which is likely to be adequate for most applications. The description of the interfaces is separated into two sections. The first deals with operations on time intervals while the second deals with operations that convert time intervals to dates for a given calendar. The smallest increment of time is referred to as a tick. A tick cannot be larger than 1 second, which also is the default. The number of ticks per second is set via pubic subroutine set_ticks_per_second. For example, ticks_per_second = 1000 will set the tick to one millisecond.


OTHER MODULES USED

fms_mod

PUBLIC INTERFACE

set_time:
Given some number of seconds and days, returns the corresponding time_type.
get_time:
Given a time interval, returns the corresponding seconds and days.
increment_time:
Given a time and an increment of days and seconds, returns a time that adds this increment to an input time.
decrement_time:
Given a time and a decrement of days and seconds, returns a time that subtracts this decrement from an input time.
time_gt operator(>):
Returns true if time1 > time2.
time_ge; operator(>=):
Returns true if time1 >= time2.
time_lt; operator(<):
Returns true if time1 < time2.
time_le; operator(<=):
Returns true if time1 <= time2.
time_eq; operator(==):
Returns true if time1 == time2.
time_ne; operator(/=):
Returns true if time1 /= time2.
time_plus; operator(+):
Returns sum of two time_types.
time_minus; operator(-):
Returns difference of two time_types.
time_scalar_mult; operator(*):
Returns time multiplied by integer factor n.
scalar_time_mult; operator(*):
Returns time multiplied by integer factor n.
time_divide; operator(/):
Returns the largest integer, n, for which time1 >= time2 * n.
time_real_divide; operator(//):
Returns the double precision quotient of two times.
time_type_to_real:
Converts time to seconds and returns it as a real number
real_to_time_type:
Converts a real number of seconds to a time_type variable
time_scalar_divide; operator(/):
Returns the largest time, t, for which n * t <= time.
interval_alarm:
Given a time, and a time interval, this function returns true if this is the closest time step to the alarm time.
repeat_alarm:
Repeat_alarm supports an alarm that goes off with alarm_frequency and lasts for alarm_length.
set_calendar_type:
Sets the default calendar type for mapping time intervals to dates.
get_calendar_type:
Returns the value of the default calendar type for mapping from time to date.
set_ticks_per_second:
Sets the number of ticks per second.
get_ticks_per_second:
Returns the number of ticks per second.
get_date:
Given a time_interval, returns the corresponding date under the selected calendar.
set_date:
Given an input date in year, month, days, etc., creates a time_type that represents this time interval from the internally defined base date.
increment_date:
Increments the date represented by a time interval and the default calendar type by a number of seconds, etc.
decrement_date:
Decrements the date represented by a time interval and the default calendar type by a number of seconds, etc.
days_in_month:
Given a time interval, gives the number of days in the month corresponding to the default calendar.
leap_year:
Returns true if the year corresponding to the input time is a leap year. Always returns false for THIRTY_DAY_MONTHS and NOLEAP.
length_of_year:
Returns the mean length of the year in the default calendar setting.
days_in_year:
Returns the number of days in the calendar year corresponding to the date represented by time for the default calendar.
month_name:
Returns a character string containing the name of the month corresponding to month number n.
time_manager_init:
Writes the version information to the log file
print_time:
Prints the given time_type argument as a time (using days, seconds and ticks)
print_date:
prints the time to standard output (or optional unit) as a date.
valid_calendar_types:
Returns a character string that describes the calendar type corresponding to the input integer.


PUBLIC DATA

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.


PUBLIC ROUTINES

  1. set_time

    1. set_time (seconds, days, ticks, err_msg)
    2. set_time (time_string, err_msg, allow_rounding)
    DESCRIPTION
    Given some number of seconds and days, returns the corresponding time_type. set_time has two forms; one accepts integer input, the other a character string. For the first form, there are no restrictions on the range of the inputs, except that the result must be positive time. e.g. days=-1, seconds=86401 is acceptable. For the second form, days and seconds must both be positive.


    INPUT
    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]

    OUTPUT
    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]

  2. get_time

     
    get_time (time, seconds, days, ticks, err_msg)
    DESCRIPTION
    Given a time interval, returns the corresponding seconds and days.


    INPUT
    time    A time interval.
       [time_type]

    OUTPUT
    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)]

  3. increment_time

     
    increment_time (time, seconds, days, ticks, err_msg, allow_neg_inc)
    DESCRIPTION
    Given a time and an increment of days and seconds, returns a time that adds this increment to an input time. Increments a time by seconds and days.


    INPUT
    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)]

    OUTPUT
    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)]

  4. decrement_time

     
    decrement_time (time, seconds, days, ticks, err_msg, allow_neg_inc)
    DESCRIPTION
    Decrements a time by seconds and days.


    INPUT
    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)]

    OUTPUT
    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)]

  5. time_gt operator(>)

     
    time_gt  operator(>) 
    
    DESCRIPTION
    Returns true if time1 > time2.


    INPUT
    time1    A time interval.
       [time_type, dimension]
    time2    A time interval.
       [time_type, dimension]

    OUTPUT
        Returns true if time1 > time2
       [logical, dimension]

  6. time_ge; operator(>=)

     
    time_ge; operator(>=) 
    
    DESCRIPTION
    Returns true if time1 >= time2.


    INPUT
    time1    A time interval.
       [time_type, dimension]
    time2    A time interval.
       [time_type, dimension]

    OUTPUT
        Returns true if time1 >= time2
       [logical, dimension]

  7. time_lt; operator(<)

     
    time_lt; operator(<) 
    
    DESCRIPTION
    Returns true if time1 < time2.


    INPUT
    time1    A time interval.
       [time_type, dimension]
    time2    A time interval.
       [time_type, dimension]

    OUTPUT
        Returns true if time1 < time2
       [logical, dimension]

  8. time_le; operator(<=)

     
    time_le; operator(<=) 
    
    DESCRIPTION
    Returns true if time1 <= time2.


    INPUT
    time1    A time interval.
       [time_type, dimension]
    time2    A time interval.
       [time_type, dimension]

    OUTPUT
        Returns true if time1 <= time2
       [logical, dimension]

  9. time_eq; operator(==)

     
    time_eq; operator(==) 
    
    DESCRIPTION
    Returns true if time1 == time2.


    INPUT
    time1    A time interval.
       [time_type, dimension]
    time2    A time interval.
       [time_type, dimension]

    OUTPUT
        Returns true if time1 == time2
       [logical, dimension]

  10. time_ne; operator(/=)

     
    time_ne; operator(/=) 
    
    DESCRIPTION
    Returns true if time1 /= time2.


    INPUT
    time1    A time interval.
       [time_type, dimension]
    time2    A time interval.
       [time_type, dimension]

    OUTPUT
        Returns true if time1 /= time2
       [logical, dimension]

  11. time_plus; operator(+)

     
    time_plus; operator(+) 
    
    DESCRIPTION
    Returns sum of two time_types.


    INPUT
    time1    A time interval.
       [time_type, dimension]
    time2    A time interval.
       [time_type, dimension]

    OUTPUT
        Returns sum of two time_types.
       [time_type, dimension]

  12. time_minus; operator(-)

     
    time_minus; operator(-) 
    
     
    time_minus; operator(-) 
    
    DESCRIPTION
    Returns difference of two time_types. WARNING: a time type is positive so by definition time1 - time2 is the same as time2 - time1.


    INPUT
    time1    A time interval.
       [time_type, dimension]
    time2    A time interval.
       [time_type, dimension]

    OUTPUT
        Returns difference of two time_types.
       [time_type, dimension]

  13. time_scalar_mult; operator(*)

     
    time_scalar_mult; operator(*) 
    
    DESCRIPTION
    Returns time multiplied by integer factor n.


    INPUT
    time    A time interval.
       [time_type, dimension]
    n    A time interval.
       [integer, dimension]

    OUTPUT
        Returns time multiplied by integer factor n.
       [time_type, dimension]

  14. scalar_time_mult; operator(*)

     
    scalar_time_mult; operator(*) 
    
    DESCRIPTION
    Returns time multiplied by integer factor n.


    INPUT
    time   A time interval.
       [time_type, dimension]
    n    An integer.
       [integer, dimension]

    OUTPUT
        Returns time multiplied by integer factor n.
       [time_type, dimension]

  15. time_divide; operator(/)

     
    time_divide; operator(/) 
    
    DESCRIPTION
    Returns the largest integer, n, for which time1 >= time2 * n.


    INPUT
    time1    A time interval.
       [time_type, dimension]
    time2    A time interval.
       [time_type, dimension]

    OUTPUT
        Returns the largest integer, n, for which time1 >= time2 * n.
       [integer, dimension]

  16. time_real_divide; operator(//)

     
    time_real_divide; operator(//) 
    
    DESCRIPTION
    Returns the double precision quotient of two times.


    INPUT
    time1    A time interval.
       [time_type, dimension]
    time2    A time interval.
       [time_type, dimension]

    OUTPUT
        Returns the double precision quotient of two times
       [integer, dimensiondouble precision]

  17. time_type_to_real

     
    time_type_to_real (time)
    DESCRIPTION
    Converts time to seconds and returns it as a real number


    INPUT
    time    A time interval.
       [time_type, dimension]

  18. real_to_time_type

     
    real_to_time_type (x, err_msg)
    DESCRIPTION
    Converts a real number of seconds to a time_type variable


    INPUT
    x    A real number of seconds
       [real, dimension]

    OUTPUT
    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]

  19. time_scalar_divide; operator(/)

     
    time_scalar_divide; operator(/) 
    
    DESCRIPTION
    Returns the largest time, t, for which n * t <= time.


    INPUT
    time    A time interval.
       [time_type, dimension]
    n    An integer factor.
       [integer, dimension]

    OUTPUT
        Returns the largest time, t, for which n * t <= time.
       [integer, dimensiondouble precision]

  20. interval_alarm

     
    interval_alarm (time, time_interval, alarm, alarm_interval)
    DESCRIPTION
    This is a specialized operation that is frequently performed in models. Given a time, and a time interval, this function is true if this is the closest time step to the alarm time. The actual computation is:

    if((alarm_time - time) <= (time_interval / 2))

    If the function is true, the alarm time is incremented by the alarm_interval; WARNING, this is a featured side effect. Otherwise, the function is false and there are no other effects. CAUTION: if the alarm_interval is smaller than the time_interval, the alarm may fail to return true ever again. Watch for problems if the new alarm time is less than time + time_interval


    INPUT
    time    Current time.
       [time_type]
    time_interval    A time interval.
       [time_type]
    alarm_interval    A time interval.
       [time_type]

    INPUT/OUTPUT
    alarm    An alarm time, which is incremented by the alarm_interval if the function is true.
       [time_type]

    OUTPUT
    interval_alarm    Returns either True or false.
       [logical]

  21. repeat_alarm

     
    repeat_alarm (time, alarm_frequency, alarm_length)
    DESCRIPTION
    Repeat_alarm supports an alarm that goes off with alarm_frequency and lasts for alarm_length. If the nearest occurence of an alarm time is less than half an alarm_length from the input time, repeat_alarm is true. For instance, if the alarm_frequency is 1 day, and the alarm_length is 2 hours, then repeat_alarm is true from time 2300 on day n to time 0100 on day n + 1 for all n.


    INPUT
    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]

    OUTPUT
    repeat_alarm    Returns either True or false.
       [logical]

  22. set_calendar_type

     
    set_calendar_type (type, err_msg)
    DESCRIPTION
    A constant number for setting the calendar type.


    INPUT
    type    A constant number for setting the calendar type.
       [integer, dimension(scalar)]

    OUTPUT
    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)]

  23. get_calendar_type

     
    get_calendar_type ()
    DESCRIPTION
    There are no arguments in this function. It returns the value of the default calendar type for mapping from time to date.


  24. set_ticks_per_second

    call set_ticks_per_second (ticks_per_second)
    DESCRIPTION
    Sets the number of ticks per second.


    INPUT
    type   
       [integer, dimension(scalar)]

  25. get_ticks_per_second

    ticks_per_second = get_ticks_per_second ()
    DESCRIPTION
    Returns the number of ticks per second.


  26. get_date

     
    get_date (time, year, month, day, hour, minute, second, tick, err_msg)
    DESCRIPTION
    Given a time_interval, returns the corresponding date under the selected calendar.


    INPUT
    time    A time interval.
       [time_type]

    OUTPUT
    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)]

  27. set_date

    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'
    DESCRIPTION
    Given a date, computes the corresponding time given the selected date time mapping algorithm. Note that it is possible to specify any number of illegal dates; these should be checked for and generate errors as appropriate.


    INPUT
    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]

    OUTPUT
    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]

  28. increment_date

     
    increment_date (time, years, months, days, hours, minutes, seconds, ticks, err_msg)
    DESCRIPTION
    Given a time and some date increment, computes a new time. Depending on the mapping algorithm from date to time, it may be possible to specify undefined increments (i.e. if one increments by 68 days and 3 months in a Julian calendar, it matters which order these operations are done and we don't want to deal with stuff like that, make it an error).


    INPUT
    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)]

    OUTPUT
    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]

    NOTE
    For all but the thirty_day_months calendar, increments to months and years must be made separately from other units because of the non-associative nature of addition. If the result is a negative time (i.e. date before the base date) it is considered a fatal error.


  29. decrement_date

     
    decrement_date (time, years, months, days, hours, minutes, seconds, ticks, err_msg))
    DESCRIPTION
    Given a time and some date decrement, computes a new time. Depending on the mapping algorithm from date to time, it may be possible to specify undefined decrements (i.e. if one decrements by 68 days and 3 months in a Julian calendar, it matters which order these operations are done and we don't want to deal with stuff like that, make it an error).


    INPUT
    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)]

    OUTPUT
    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]

    NOTE
    For all but the thirty_day_months calendar, decrements to months and years must be made separately from other units because of the non-associative nature of addition. If the result is a negative time (i.e. date before the base date) it is considered a fatal error.


  30. days_in_month

     
    days_in_month (time)
    DESCRIPTION
    Given a time, computes the corresponding date given the selected date time mapping algorithm.


    INPUT
    time   A time interval.
       [time_type, dimension]

    OUTPUT
    days_in_month    The number of days in the month given the selected time mapping algorithm.
       [integer, dimension]

  31. leap_year

     
    leap_year (time)
    DESCRIPTION
    Returns true if the year corresponding to the input time is a leap year. Always returns false for THIRTY_DAY_MONTHS and NOLEAP.


    INPUT
    time   A time interval.
       [time_type, dimension]

    OUTPUT
    leap_year    true if the year corresponding to the input time is a leap year.
       [calendar_type, dimension]

  32. length_of_year

     
    length_of_year ()
    DESCRIPTION
    There are no arguments in this function. It returns the mean length of the year in the default calendar setting.


  33. days_in_year

     
    days_in_year (Time)
    DESCRIPTION
    Returns the number of days in the calendar year corresponding to the date represented by time for the default calendar.


    INPUT
    Time   A time interval.
       [time_type]

    OUTPUT
        The number of days in this year for the default calendar type.

  34. month_name

     
    month_name (n)
    DESCRIPTION
    Returns a character string containing the name of the month corresponding to month number n. Definition is the same for all calendar types.


    INPUT
    n   Month number.
       [integer]

    OUTPUT
    month_name    The character string associated with a month. All calendars have 12 months and return full month names, not abreviations.
       [character(len=9)]

  35. time_manager_init

     
    time_manager_init ()
    DESCRIPTION
    Initialization routine. Writes the version information to the log file


  36. print_time

     
    print_time (time,str,unit)
    DESCRIPTION
    Prints the given time_type argument as a time (using days, seconds and ticks) NOTE: there is no check for PE number.


    INPUT
    time    Time that will be printed.
       [time_type]
    str    Character string that precedes the printed time or date.
       [character (len=*)]
    unit    Unit number for printed output. The default unit is stdout.
       [integer]

  37. print_date

     
    print_date (time,str,unit)
    DESCRIPTION
    Prints the given time_type argument as a date (using year, month, day, hour, minutes, seconds and ticks). NOTE: there is no check for PE number.


    INPUT
    time    Time that will be printed.
       [time_type]
    str    Character string that precedes the printed time or date.
       [character (len=*)]
    unit    Unit number for printed output. The default unit is stdout.
       [integer]

  38. valid_calendar_types

    DESCRIPTION
    Returns a character string that describes the calendar type corresponding to the input integer.


    INPUT
    ncal    An integer corresponding to a valid calendar type.
       [integer]

    OUTPUT
    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)]


DATA SETS

None.


ERROR MESSAGES

None.


REFERENCES

None.


COMPILER SPECIFICS

None.


PRECOMPILER OPTIONS

None.


LOADER OPTIONS

None.


TEST PROGRAM

time_main2
        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


KNOWN BUGS

None.


NOTES

The <a name="base date">base date</a> is implicitly defined so users don't need to be concerned with it. For the curious, the base date is defined as 0 seconds, 0 minutes, 0 hours, day 1, month 1, year 1

Please note that a time is a positive definite quantity.

See the Test Program for a simple program that shows some of the capabilities of the time manager.


FUTURE PLANS

None.


top