From f575359292df91feb7011e415186a370ff17e920 Mon Sep 17 00:00:00 2001
From: Bruce Flynn <brucef@ssec.wisc.edu>
Date: Fri, 22 Dec 2017 10:40:15 -0600
Subject: [PATCH] changes to timecode helpers

---
 edosl0util/headers.py  | 43 ++++++++++++++++++++----------------------
 edosl0util/timecode.py | 26 ++++++++++++-------------
 setup.py               |  1 +
 3 files changed, 34 insertions(+), 36 deletions(-)

diff --git a/edosl0util/headers.py b/edosl0util/headers.py
index e145e58..4a467b0 100644
--- a/edosl0util/headers.py
+++ b/edosl0util/headers.py
@@ -13,13 +13,10 @@ See:
 """
 __copyright__ = "Copyright (C) 2015 University of Wisconsin SSEC. All rights reserved."
 
-
 import ctypes as c
 from datetime import datetime, timedelta
 
-
-from edosl0util.timecode import cds_stamp, cds_to_timestamp
-
+from edosl0util.timecode import cds_to_dt
 
 GROUP_FIRST = 0b01
 GROUP_LAST = 0b10
@@ -63,12 +60,10 @@ class Timecode(BaseStruct):
     """
     Secondary header timecode baseclass.
     """
+
     def __repr__(self):
         return str(self.asdatetime())
 
-    def astimestamp(self):
-        raise NotImplementedError()
-
     def asdatetime(self):
         raise NotImplementedError()
 
@@ -98,20 +93,16 @@ class AquaCucTimecode(Timecode):
     EPOCH_SECS = (EPOCH - datetime(1970, 1, 1)).total_seconds()
     SUB_SECOND_UNITS = 15.2
 
-    def astimestamp(self):
-        tc = self.timecode
-        return cds_to_timestamp(tc.days, tc.milliseconds, tc.microseconds, self.EPOCH_SECS)
-
     def asdatetime(self):
         """
         Return converted to UTC where leap seconds are as defined in `leap_seconds`.
-
-        FIXME: Verify this conversion is correct, specfically the use of
-               SUB_SECOND_UNIT.
         """
-        seconds = self.seconds + self.leap_seconds
         micros = self.SUB_SECOND_UNITS * self.sub_seconds
-        return self.EPOCH + timedelta(seconds=seconds, microseconds=micros)
+        seconds = self.seconds + self.leap_seconds
+        return cds_to_dt(
+            (seconds - self.leap_seconds) // 86400,
+            micros // 1e3,
+            micros % 1e3)
 
 
 class DaySegmentedTimecode(Timecode):
@@ -125,14 +116,8 @@ class DaySegmentedTimecode(Timecode):
         ('microseconds', c.c_uint16)
     ]
 
-    EPOCH = datetime(1958, 1, 1)
-    EPOCH_SECS = (EPOCH - datetime(1970, 1, 1)).total_seconds()
-
-    def astimestamp(self):
-        return cds_to_timestamp(self.days, self.milliseconds, self.microseconds, self.EPOCH_SECS)
-
     def asdatetime(self):
-        return cds_stamp(self.days, self.milliseconds, self.microseconds)
+        return cds_to_dt(self.days, self.milliseconds, self.microseconds)
 
 
 class AquaGirdSecondaryHeader(BaseStruct):
@@ -178,12 +163,22 @@ class JpssFirstSecondaryHeader(BaseStruct):
     ]
 
 
+class ViirsPacketId(BaseStruct):
+    _pack_ = 1
+    _fields_ = [
+        ('scan_number', c.c_uint32),
+        ('packet_time', DaySegmentedTimecode),
+    ]
+
+
 _jpss_headers = {
     GROUP_FIRST: JpssFirstSecondaryHeader,
     GROUP_CONTINUING: None,
     GROUP_LAST: None,
     GROUP_STANDALONE: JpssSecondaryHeader,
 }
+
+
 def jpss_header_lookup(primary_header):
     return _jpss_headers.get(primary_header.sequence_grouping)
 
@@ -269,4 +264,6 @@ def aqua_header_lookup(primary_header):
     apid = primary_header.apid
     grouping = primary_header.sequence_grouping
     return _aqua_headers.get((apid, grouping))
+
+
 _aqua_headers = aqua_headers()
diff --git a/edosl0util/timecode.py b/edosl0util/timecode.py
index a505e6c..048e6ae 100644
--- a/edosl0util/timecode.py
+++ b/edosl0util/timecode.py
@@ -1,31 +1,31 @@
 # encoding: utf-8
 __copyright__ = "Copyright (C) 2015 University of Wisconsin SSEC. All rights reserved."
 
-from datetime import datetime, timedelta
+from astropy.time import Time, TimeDelta
 
-JPSS_EPOCH = datetime(1958, 1, 1)
-UNIX_EPOCH = datetime(1970, 1, 1)
+IET_EPOCH = Time('1958-01-01', scale='tai')
+UNIX_EPOCH = Time('1970-01-01', scale='utc')
 
 
 def unixtime(dt):
     """
     Datetime to Unix timestamp.
     """
-    if dt > UNIX_EPOCH:
-        return (dt - UNIX_EPOCH).total_seconds()
-    return (UNIX_EPOCH - dt).total_seconds()
+    return (dt - UNIX_EPOCH).total_seconds()
 
 
-def cds_to_timestamp(days, millis, microseconds, epoch):
+def cds_to_dt(days, millis, microseconds):
     """
-    CDS to unix timestamp seconds.
+    CCSDS Day Segmented timecode to UTC datetime.
     """
-    return epoch + (86400 * days) + (millis / 1000.) + (microseconds / 1000000.)
+    iet = cds_to_iet(days, millis, microseconds)
+    return (IET_EPOCH + TimeDelta(iet, format='sec')).utc.datetime
 
 
-def cds_stamp(days, millis, microseconds, epoch=JPSS_EPOCH):
+def cds_to_iet(days, ms, us):
     """
-    CCSDS Day Segmented timecode to UTC datetime.
+    CCSDS Day Segmented timecode parts to IET
     """
-    return epoch + timedelta(days=days,
-                             seconds=millis / 1000.0 + (microseconds / 1000000.))
+    ccsds_epoch = Time('1958-01-01', scale='tai')
+    day = Time(ccsds_epoch.jd + days, scale='utc', format='jd') - IET_EPOCH
+    return int(day.sec * 1e6 + ms * 1e3 + us)
diff --git a/setup.py b/setup.py
index 1711520..d63918f 100644
--- a/setup.py
+++ b/setup.py
@@ -14,6 +14,7 @@ setup(
     ],
     install_requires=[
         'h5py',
+        'astropy',
     ],
     extras_require={
         'testing': [
-- 
GitLab