Reorganize Timekeeping¶
Xylar Asay-Davis
date: 2017/02/06
Summary
Currently, the `Date` class is used to parse a date object from a date string (e.g. '0001-01-01_00:00:00') taken from MPAS namelists, streams files or time variables (e.g. `xtime`). However, this class assumes a 365-day calendar and cannot easily be adapted to the Gregorian calendar also supported by MPAS components (`config_calendar_type = 'gregorian'`). Furthermore, existing routines exist to handle most of the capabilites of the `Date` class. The proposed reorganization would eliminate the `Date` class in favor of a numer of helper functions that can be used to convert between various date formats: date strings, days since a reference date, `datetime.datetime` objects and `relativedelta` objects (see below). The success of this reorganization will be demonstrated when the existing analysis can be performed successfully with the new utility functions with both MPAS calendars, the `'gregorian_noleap'` (365-day) calendar used by most existing ACME and MPAS runs and the `'gregorian'` calendar also supported in MPAS components.Requirements
Requirement: Date string parsing supports both MPAS calendars
Date last modified: 2017/02/06
Contributors: Xylar Asay-Davis
There must be a way to parse dates from MPAS that is aware of the appropriate calendar
stored in the config_calendar_type
namelist option, either 'gregorian'
or
'gregorian_noleap'
.
Requirement: Capability of incrementing dates by a number of years and/or months
Date last modified: 2017/02/06
Contributors: Xylar Asay-Davis
The analysis requires a way of incrementing a given date by an interval specified in
not only days, hours, minutes and seconds but also months and years. The standard
datetime.timedelta
does not support increments by years and months because they are
not fixed periods of time. The existing Date
class in MPAS-Analysis supports
increments in months and years, but only for the 'gregorian_noleap'
(365-day) calendar.
A method must exist to increment dates on either calendar by a given number of years
and/or months (in addition to days, hours, etc.).
Design and Implementation
Implementation: Date string parsing supports both MPAS calendars
Date last modified: 2017/02/06
Contributors: Xylar Asay-Davis
The implementation is on the branch: https://github.com/xylar/MPAS-Analysis/tree/timekeeping_reorg and in PR #102
The function for converting a date string to a datetime.datetime
is documented as follows:
def stringToDatetime(dateString):
"""
Given a date string and a calendar, returns a `datetime.datetime`
Parameters
----------
dateString : string
A date and time in one of the following formats:
- YYYY-MM-DD hh:mm:ss
- YYYY-MM-DD hh.mm.ss
- YYYY-MM-DD SSSSS
- DDD hh:mm:ss
- DDD hh.mm.ss
- DDD SSSSS
- hh.mm.ss
- hh:mm:ss
- YYYY-MM-DD
- YYYY-MM
- SSSSS
Note: either underscores or spaces can be used to separate the date
from the time portion of the string.
Returns
-------
datetime : A `datetime.datetime` object
Raises
------
ValueError
If an invalid `dateString` is supplied.
Author
------
Xylar Asay-Davis
Last modified
-------------
02/04/2017
"""
As long as relativedelta
objects rather than datetime.timedelta
objects are used to increment
datetime.datetime
objects, datetime.datetime
can be used to represent dates on either the Gregorian
or the 365-day calendar.
Implementation: Capability of incrementing dates by a number of years and/or months
Date last modified: 2017/02/09
Contributors: Xylar Asay-Davis
The implementation is on the branch: https://github.com/xylar/MPAS-Analysis/tree/timekeeping_reorg and in PR #102
The proposed implementation adds a new class MpasRelativeDelta derived from
dateutil.relativedelta.relativedelta
to compute the expected
increments in years and months (as well as days, hours, minutes and seconds, as needed).
The class is documented as follows
class MpasRelativeDelta(relativedelta):
"""
MpasRelativeDelta is a subclass of dateutil.relativedelta for relative time
intervals with different MPAS calendars.
Only relative intervals (years, months, etc.) are supported and not the
absolute date specifications (year, month, etc.). Addition/subtraction
of datetime.datetime objects (but not other MpasRelativeDelta,
datetime.timedelta or other related objects) is supported.
Author
------
Xylar Asay-Davis
Last Modified
-------------
02/09/2017
The function for converting a date string to a MpasRelativeDelta
is documented as follows:
from dateutil.relativedelta import relativedelta
...
def stringToRelativedelta(dateString, calendar='gregorian'):
"""
Given a date string and a calendar, returns an instance of
`MpasRelativeDelta`
Parameters
----------
dateString : string
A date and time in one of the following formats:
- YYYY-MM-DD hh:mm:ss
- YYYY-MM-DD hh.mm.ss
- YYYY-MM-DD SSSSS
- DDD hh:mm:ss
- DDD hh.mm.ss
- DDD SSSSS
- hh.mm.ss
- hh:mm:ss
- YYYY-MM-DD
- YYYY-MM
- SSSSS
Note: either underscores or spaces can be used to separate the date
from the time portion of the string.
calendar: {'gregorian', 'gregorian_noleap'}, optional
The name of one of the calendars supported by MPAS cores
Returns
-------
relativedelta : An `MpasRelativeDelta` object
Raises
------
ValueError
If an invalid `dateString` is supplied.
Author
------
Xylar Asay-Davis
Last modified
-------------
02/04/2017
"""
Testing
Testing and Validation: Date string parsing supports both MPAS calendars
Date last modified: 2017/02/08
Contributors: Xylar Asay-Davis
Analysis will be run on Edison with all available configurations found in `configs/edison`. As there
are currently no plans to run with the `gregorian` calendar option, we do not have test runs that use this
calendar. If this situation changes in the future, we'll test at that time.
Regression tests previously for `Date` has been modified to test the new utility functions. New tests
have been added to test that dates with both `gregorian` and `gregorian_noleap` calendars behave as
expected, particularly around the leap day.
Testing
Testing and Validation: Capability of incrementing dates by a number of years and/or months
Date last modified: 2017/02/06
Contributors: Xylar Asay-Davis
Same as above.