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