Source code for mhkit.dolfyn.time

from datetime import datetime, timedelta, timezone
import numpy as np
from .tools.misc import fillgaps


def _fullyear(year):
    if year > 100:
        return year
    year += 1900 + 100 * (year < 90)
    return year


[docs] def epoch2dt64(ep_time): """ Convert from epoch time (seconds since 1/1/1970 00:00:00) to numpy.datetime64 array Parameters ---------- ep_time : xarray.DataArray Time coordinate data-array or single time element Returns ------- time : numpy.datetime64 The converted datetime64 array """ # assumes t0=1970-01-01 00:00:00 out = np.array(ep_time.astype("int")).astype("datetime64[s]") out = out + ((ep_time % 1) * 1e9).astype("timedelta64[ns]") return out
[docs] def dt642epoch(dt64): """ Convert numpy.datetime64 array to epoch time (seconds since 1/1/1970 00:00:00) Parameters ---------- dt64 : numpy.datetime64 Single or array of datetime64 object(s) Returns ------- time : float Epoch time (seconds since 1/1/1970 00:00:00) """ return dt64.astype("datetime64[ns]").astype("float") / 1e9
[docs] def date2dt64(dt): """ Convert numpy.datetime64 array to list of datetime objects Parameters ---------- time : datetime.datetime The converted datetime object Returns ------- dt64 : numpy.datetime64 Single or array of datetime64 object(s) """ return np.array(dt).astype("datetime64[ns]")
[docs] def dt642date(dt64): """ Convert numpy.datetime64 array to list of datetime objects Parameters ---------- dt64 : numpy.datetime64 Single or array of datetime64 object(s) Returns ------- time : datetime.datetime The converted datetime object """ return epoch2date(dt642epoch(dt64))
[docs] def epoch2date(ep_time, offset_hr=0, to_str=False): """ Convert from epoch time (seconds since 1/1/1970 00:00:00) to a list of datetime objects Parameters ---------- ep_time : xarray.DataArray Time coordinate data-array or single time element offset_hr : int Number of hours to offset time by (e.g. UTC -7 hours = PDT) to_str : logical Converts datetime object to a readable string Returns ------- time : datetime.datetime The converted datetime object or list(strings) Notes ----- The specific time instance is set during deployment, usually sync'd to the deployment computer. The time seen by DOLfYN is in the timezone of the deployment computer, which is unknown to DOLfYN. """ try: ep_time = ep_time.values except AttributeError: pass if isinstance(ep_time, (np.ndarray)) and ep_time.ndim == 0: ep_time = [ep_time.item()] elif not isinstance(ep_time, (np.ndarray, list)): ep_time = [ep_time] ######### IMPORTANT ######### # Note the use of `utcfromtimestamp` here, rather than `fromtimestamp` # This is CRITICAL! See the difference between those functions here: # https://docs.python.org/3/library/datetime.html#datetime.datetime.fromtimestamp # Long story short: `fromtimestamp` used system-specific timezone # info to calculate the datetime object, but returns a # timezone-agnostic object. if offset_hr != 0: delta = timedelta(hours=offset_hr) time = [datetime.utcfromtimestamp(t) + delta for t in ep_time] else: time = [datetime.utcfromtimestamp(t) for t in ep_time] if to_str: time = date2str(time) return time
[docs] def date2str(dt, format_str=None): """ Convert list of datetime objects to legible strings Parameters ---------- dt : datetime.datetime Single or list of datetime object(s) format_str : string Timestamp string formatting. Default is '%Y-%m-%d %H:%M:%S.%f' See datetime.strftime documentation for timestamp string formatting. Returns ------- time : string Converted timestamps """ if format_str is None: format_str = "%Y-%m-%d %H:%M:%S.%f" if not isinstance(dt, list): dt = [dt] return [t.strftime(format_str) for t in dt]
[docs] def date2epoch(dt): """ Convert list of datetime objects to epoch time Parameters ---------- dt : datetime.datetime Single or list of datetime object(s) Returns ------- time : float Datetime converted to epoch time (seconds since 1/1/1970 00:00:00) """ if not isinstance(dt, list): dt = [dt] return [t.replace(tzinfo=timezone.utc).timestamp() for t in dt]
[docs] def date2matlab(dt): """ Convert list of datetime objects to MATLAB datenum Parameters ---------- dt : datetime.datetime List of datetime objects Returns ------- time : float List of timestamps in MATLAB datnum format """ time = list() for i in range(len(dt)): mdn = dt[i] + timedelta(days=366) frac_seconds = ( dt[i] - datetime(dt[i].year, dt[i].month, dt[i].day, 0, 0, 0) ).seconds / (24 * 60 * 60) frac_microseconds = dt[i].microsecond / (24 * 60 * 60 * 1000000) time.append(mdn.toordinal() + frac_seconds + frac_microseconds) return time
[docs] def matlab2date(matlab_dn): """ Convert MATLAB datenum to list of datetime objects Parameters ---------- matlab_dn : float List of timestamps in MATLAB datnum format Returns ------- dt : datetime.datetime List of datetime objects """ time = list() for i in range(len(matlab_dn)): day = datetime.fromordinal(int(matlab_dn[i])) dayfrac = timedelta(days=matlab_dn[i] % 1) - timedelta(days=366) time.append(day + dayfrac) # Datenum is precise down to 100 microseconds - add difference to round us = int(round(time[i].microsecond / 100, 0)) * 100 time[i] = time[i].replace(microsecond=time[i].microsecond) + timedelta( microseconds=us - time[i].microsecond ) return time
def _fill_time_gaps(epoch, sample_rate_hz): """ Fill gaps (NaN values) in the timeseries by simple linear interpolation. The ends are extrapolated by stepping forward/backward by 1/sample_rate_hz. """ # epoch is seconds since 1970 dt = 1.0 / sample_rate_hz epoch = fillgaps(epoch) if np.isnan(epoch[0]): i0 = np.nonzero(~np.isnan(epoch))[0][0] delta = np.arange(-i0, 0, 1) * dt epoch[:i0] = epoch[i0] + delta if np.isnan(epoch[-1]): # Search backward through the array to get the 'negative index' ie = -np.nonzero(~np.isnan(epoch[::-1]))[0][0] - 1 delta = np.arange(1, -ie, 1) * dt epoch[(ie + 1) :] = epoch[ie] + delta return epoch