diff --git a/peregrine/gps_time.py b/peregrine/gps_time.py index 9649fa0..7aac347 100644 --- a/peregrine/gps_time.py +++ b/peregrine/gps_time.py @@ -1,5 +1,78 @@ import datetime +# NTP timestamps are in units of seconds since the NTP epoch +# See leap-seconds.list for further details. +NTP_EPOCH = datetime.datetime(1900,1,1,0,0,0) + +def sec_since_NTP_epoch(dt): + """Return the number of seconds since the NTP epoch.""" + return (dt-NTP_EPOCH).total_seconds() + +def load_leapsecond_table(f="/usr/share/zoneinfo/leap-seconds.list"): + """" + Loads leap second table from system. + + The default file location is appropriate for Ubuntu and is provided by + the tzdata package. Refer to the leap-seconds.list file for formatting + information. + + Parameters + ---------- + f : string + Path to a leap-seconds.list file + + Returns: List of tuples in chronological order each containing an + epoch start time and number of leap seconds applicable for that epoch. + """ + + # Check the expiration date in the file + with open(f,'r') as fp: + for line in fp: + if line[0:2] != "#@": + continue + + expiration_time = int(line.split('\t')[-1]) + now = sec_since_NTP_epoch(datetime.datetime.now()) + + if expiration_time=epoch_start: + ls = leapseconds + + # Raise warning if specified time is after expiry date of leap second table + if ls==None: + raise UserWarning("Specified datetime is after expiry time of leap second table.") + + # GPS leap seconds relative to a Jan 1 1980, where TAI-UTC was 19 seconds. + gps_leap_seconds = ls - 19 + + return datetime.timedelta(seconds = gps_leap_seconds) + def datetime_to_tow(t, mod1024 = True): """ Convert a Python datetime object to GPS Week and Time Of Week. @@ -39,12 +112,7 @@ def gpst_to_utc(t_gpst): ------- t_utc : datetime """ - t_utc = t_gpst - datetime.timedelta(seconds = 16) - if t_utc <= datetime.datetime(2012, 7, 1) or \ - t_utc >= datetime.datetime(2015, 7, 1): - raise ValueError("Don't know how many leap seconds to use. " + - "Please implement something better in gpst_to_utc()") - return t_utc + return t_gpst - get_gpst_leap_seconds(t_gpst) def utc_to_gpst(t_utc): """ @@ -59,9 +127,7 @@ def utc_to_gpst(t_utc): ------- t_gpst : datetime """ - t_gpst = t_utc + datetime.timedelta(seconds = 16) - if t_utc <= datetime.datetime(2012, 7, 1) or \ - t_utc >= datetime.datetime(2015, 7, 1): - raise ValueError("Don't know how many leap seconds to use. " + - "Please implement something better in utc_to_gpst()") - return t_gpst + # TODO: there may be an unhandled corner case here for conversions + # where the GPST-to-UTCT interval spans a leap second. + + return t_utc + get_gpst_leap_seconds(t_utc)