"""
Several date/time helper functions.
"""
import argparse
import datetime
from time import strptime
import numpy as np
def _from_matlab_to_python_num_days(x):
# Matlab epoch time start at the year 0, python at the 1-1-0001.
# Both formats differ 366 days.
# So to convert the matlab format to the python format, convert it here
return (
datetime.datetime.fromordinal(int(x))
+ datetime.timedelta(days=x % 1)
- datetime.timedelta(days=366)
)
_from_matlab_to_python_num_days_vectorized = np.vectorize(
_from_matlab_to_python_num_days
)
[docs]
def matlabnum2date(x):
"""Convert a Matlab numerical date/time representation into a Python datetime object
Parameters
----------
Parameters
----------
x : float or ndarrray
Matlab numerical date/time representation giving the number of days since
0000 00 00:00:00
Returns
-------
number_of_days : ndarray or scalar of the type datetime`
Date/time corresponding to the float value `x`
Notes
-----
* In Matlab, the numerical date/time representation gives the number of days since
Jan 00 0000 00:00:00
* In Python, the numerical date/time representation gives the number of days since
Jan 01 0001 00:00:00
* To convert from matlab to python, 366 days need to be subtracted from the matlab
numerical date/time representation to get the Python numerical data/time
representation (note that matlab starts at Jan 0th!)
Examples
--------
The following two dates in numerical representation are obtained using the Matlab
`datenum` function
* 2012-12-21T12:12:12 -> 7.352245084722222e+05 # days since 0000 00 00:00:00
* 1973-11-12T09:15:43 -> 7.209403859143519e+05 # days since 0000 00 00:00:00
>>> num_date_matlab = np.array([7.352245084722222222222222e+05,
... 7.209403859143519e+05])
>>> matlabnum2date(num_date_matlab)
array([datetime.datetime(2012, 12, 21, 12, 12, 12, 3),
datetime.datetime(1973, 11, 12, 9, 15, 43, 5)], dtype=object)
"""
try:
number_of_days = _from_matlab_to_python_num_days(x)
except TypeError:
x = np.asarray(x)
if not x.size:
raise
number_of_days = _from_matlab_to_python_num_days_vectorized(x)
return number_of_days
[docs]
def valid_date(s):
"""Check if supplied data *s* is a valid date for the format Year-Month-Day
Parameters
----------
s : str
A valid date in the form of YYYY-MM-DD, so first the year, then the month, then
the day
Returns
-------
datetime
Date object with the year, month, day obtained from the valid string
representation
Raises
------
argparse.ArgumentTypeError:
Notes
-----
This is a helper function for the argument parser module argparse which allows you
to check if the argument passed on the command line is a valid date.
Examples
--------
This is the direct usage of `valid_date` to see if the date supplied is of format
YYYY-MM-DD
>>> try:
... date = valid_date("1973-11-12")
... except argparse.ArgumentTypeError:
... print("This date is invalid")
... else:
... print("This date is valid")
This date is valid
In case an invalid date is supplied
>>> try:
... date = valid_date("1973-15-12")
... except argparse.ArgumentTypeError:
... print("This date is invalid")
... else:
... print("This date is valid")
This date is invalid
Here it is demonstrated how to add a '--startdate' command line option to the
argparse parser which checks if a valid date is supplied
>>> parser = argparse.ArgumentParser()
>>> p = parser.add_argument("--startdate",
... help="The Start Date - format YYYY-MM-DD ",
... required=True,
... type=valid_date)
References
----------
https://stackoverflow.com/questions/25470844/
specify-format-for-input-arguments-argparse-python
"""
try:
return strptime(s, "%Y-%m-%d")
except ValueError:
msg = f"Not a valid date: '{s}'.\nSupply date as YYYY-MM-DD"
raise argparse.ArgumentTypeError(msg)