Source code for utide._time_conversion
"""
Utility for allowing flexible time input.
"""
import numpy as np
# to be added to get 1 on 1st January of year 1 from unix epoch '1970-01-01'
_DAY_TO_GREGORIAN_EPOCH = 719163
# millisecond in a day
_MS_PER_DAY = 1000 * 86400
def _date2num(date, epoch="1970-01-01 00:00:00.000"):
"""
Numpy based date to datenum calculator.
`date` and `epoch` can be anything parsable by np.datetime64 - string, datetime, datetime64,
pandas datetime.
Default `epoch` is the unix epoch 1970-01-01 00:00:00.
"""
date = np.asarray(date)
try:
date = date.astype("datetime64[ms]")
except ValueError as err:
raise ValueError(
f"Cannot convert date argument ({date}) to scalar or array of numpy datetime64 dtype.",
) from err
try:
epoch = np.datetime64(epoch, "ms")
except ValueError as err:
raise ValueError(
f"Cannot convert epoch argument ({epoch}) to numpy datetime64 dtype.",
) from err
# datenum calculation
datenum = (date - epoch).astype(float) / _MS_PER_DAY
return datenum
def _python_gregorian_datenum(date):
"""
Number of days since 0000-12-31.
Python gregorian time is 1 on 1st day of 1st year. Essentially, it means,
the epoch for python gregorian time is 0000-12-31. With _date2num() defined
above, this amounts to 719163 days from the unix-epoch 1970-01-01 00:00:00.
To avoid repetitive calculation, this is defined as _DAY_TO_GREGORIAN_EPOCH.
"""
return _date2num(date) + _DAY_TO_GREGORIAN_EPOCH
[docs]
def _normalize_time(t, epoch=None):
"""
Convert datetime or datenum array to proper input datenum array with an
epoch from '0000-12-31' - 1st Jan of 1st year is 1.
`t` input time or datenum array
`epoch` either 'python', 'matlab', or np.datetime64 compatible value
"""
t = np.asarray(t)
if epoch is None:
# default datetime, datetime64, or datetime array
return _python_gregorian_datenum(t)
if t.dtype.kind in ("if"):
if epoch == "python":
return t
elif epoch == "matlab":
return t - 366
else:
try:
ofs = _python_gregorian_datenum(epoch)
except ValueError as err:
raise ValueError(
"Cannot parse epoch as string or date or datetime",
) from err
else:
return t + ofs
else:
raise ValueError("Can not process time array as timestamp or datenum.")