Skip to content

Commit

Permalink
[reassembler] improve timestamp handling with timezones
Browse files Browse the repository at this point in the history
  • Loading branch information
Sec42 committed Apr 20, 2024
1 parent 053ad57 commit 47377de
Show file tree
Hide file tree
Showing 8 changed files with 69 additions and 18 deletions.
10 changes: 6 additions & 4 deletions iridiumtk/reassembler/id_sat_map.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

import sys
import datetime
from util import dt

from .base import *
from .ira import ReassembleIRA
Expand Down Expand Up @@ -81,8 +82,7 @@ def find_closest_satellite(self, t, xyz, satlist):
return closest_satellite, closest_distance

def process(self,q):
time = datetime.datetime.utcfromtimestamp(q.time)
time = time.replace(tzinfo=utc)
time = dt.epoch(q.time)
t = self.ts.utc(time)
if self.first:
self.first=False
Expand All @@ -106,8 +106,10 @@ def process(self,q):

def consume(self,q):
if config.verbose:
# print("%s: sat %02d beam %02d [%d %4.2f %4.2f %s] matched %-20s @ %5.2f°"%( datetime.datetime.utcfromtimestamp(q.time), q.sat,q.beam,q.time,q.lat,q.lon,q.alt,q.name,q.sep))
print("%s: sat %02d beam %02d [%d %8.4f %8.4f %s] matched %-20s @ %5fkm"%( datetime.datetime.utcfromtimestamp(q.time), q.sat,q.beam,q.time,q.lat,q.lon,q.alt,q.name,q.sep))
#print("%s: sat %02d beam %02d [%d %8.2f %8.2f %s] matched %-20s @ %5.2f°" %
print("%s: sat %02d beam %02d [%d %8.4f %8.4f %s] matched %-20s @ %5fkm" %
(dt.epoch(q.time), q.sat, q.beam, q.time, q.lat, q.lon, q.alt, q.name, q.sep))

if q.sep > self.MAX_DIST:
q.name="NONE"
if not q.sat in self.sats:
Expand Down
3 changes: 2 additions & 1 deletion iridiumtk/reassembler/ira.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

import sys
import re
from util import dt

from .base import *
from ..config import config, outfile
Expand Down Expand Up @@ -35,7 +36,7 @@ def filter(self,line):
return q
def process(self,q):
q.enrich()
strtime=datetime.datetime.fromtimestamp(q.time,tz=Z).strftime("%Y-%m-%dT%H:%M:%S.{:02.0f}Z".format(int((q.time%1)*100)))
strtime = dt.epoch(q.time).isoformat(timespec='centiseconds')
for x in q.pages:
return ["%s %03d %02d %6.2f %6.2f %03d : %s %s"%(strtime, q.sat,q.beam,q.lat,q.lon,q.alt,x[0],x[1])]
def consume(self,q):
Expand Down
4 changes: 3 additions & 1 deletion iridiumtk/reassembler/iratime.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,13 @@
import sys
import re
import collections
from util import dt

from .base import *
from ..config import config, outfile

class ReassembleIRATime(Reassemble):
"""Check if there are IRA for the same beam quicker than 4.2 seconds"""
def __init__(self):
pass
def filter(self,line):
Expand All @@ -32,7 +34,7 @@ def filter(self,line):
def process(self,q):
if q.beam in self.buf[q.sat]:
if q.time-self.buf[q.sat][q.beam] < 4.2:
strtime=datetime.datetime.fromtimestamp(q.time,tz=Z).strftime("%Y-%m-%dT%H:%M:%S")
strtime = dt.epoch(q.time).isoformat(timespec='seconds')
print("%3d %3d: %s %f"%(q.beam,q.sat,strtime,q.time-self.buf[q.sat][q.beam]))

self.buf[q.sat][q.beam]=q.time
Expand Down
4 changes: 2 additions & 2 deletions iridiumtk/reassembler/msg.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
import sys
import datetime
import re
from util import to_ascii, slice_extra
from util import to_ascii, slice_extra, dt

from .base import *
from ..config import config, outfile
Expand Down Expand Up @@ -179,7 +179,7 @@ def consume(self, msg):
if not msg.correct:
return

date= datetime.datetime.fromtimestamp(msg.time).strftime("%Y-%m-%dT%H:%M:%S")
date = dt.epoch_local(msg.time).isoformat(timespec='seconds')
str="Message %07d %02d @%s (len:%d)"%(msg.ric, msg.seq, date, msg.pcnt)
txt= msg.content
if 'noburst' in config.args:
Expand Down
5 changes: 3 additions & 2 deletions iridiumtk/reassembler/pktstats.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import sys
import datetime
from copy import deepcopy
from util import dt

from .base import *
from ..config import config, outfile, state
Expand Down Expand Up @@ -81,9 +82,9 @@ def printstats(self, timeslot, stats, skip=False):
comment=''
if skip:
comment='#!'
print("#!@ %s L:"%(datetime.datetime.fromtimestamp(ts)), file=sys.stderr)
print("#!@ %s L:"%(dt.epoch_local(ts)), file=sys.stderr)
else:
print("# @ %s L:"%(datetime.datetime.fromtimestamp(ts)), file=sys.stderr)
print("# @ %s L:"%(dt.epoch_local(ts)), file=sys.stderr)
for k in stats:
for t in stats[k]:
print("%siridium.parsed.%s.%s %7d %8d"%(comment,k,t,stats[k][t],ts))
Expand Down
10 changes: 5 additions & 5 deletions iridiumtk/reassembler/ppm.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
import os
import socket
from copy import deepcopy
from util import fmt_iritime, to_ascii, slice_extra
from util import fmt_iritime, to_ascii, slice_extra, dt

from .base import *
from ..config import config, outfile
Expand Down Expand Up @@ -40,13 +40,13 @@ def filter(self,line):
m=self.r2.match(q.data)
if not m: return
if m.group(2):
q.itime = datetime.datetime.strptime(m.group(1), '%Y-%m-%dT%H:%M:%S.%f')
q.itime = dt.strptime(m.group(1), '%Y-%m-%dT%H:%M:%S.%f').replace(tzinfo=datetime.timezone.utc)
else:
q.itime = datetime.datetime.strptime(m.group(1), '%Y-%m-%dT%H:%M:%S')
q.itime = dt.strptime(m.group(1), '%Y-%m-%dT%H:%M:%S').replace(tzinfo=datetime.timezone.utc)
return q

def process(self,q):
q.uxtime=datetime.datetime.utcfromtimestamp(q.time)
q.uxtime = dt.epoch(q.time)

# correct for slot:
# 1st vs. 4th slot is 3 * (downlink + guard)
Expand Down Expand Up @@ -93,7 +93,7 @@ def consume(self, data):
if (data[1]-self.cur[1]).total_seconds() > 600:
(irun,toff,ppm)=self.onedelta(self.cur,data, verbose=False)
if 'grafana' in config.args:
print("iridium.live.ppm %.5f %d"%(ppm,(data[1]-datetime.datetime.fromtimestamp(0)).total_seconds()))
print("iridium.live.ppm %.5f %d" % (ppm, data[1].timestamp()))
sys.stdout.flush()
else:
print("@ %s: ppm: % 6.3f ds: % 8.5f "%(data[1],ppm,(data[1]-data[0]).total_seconds()))
Expand Down
6 changes: 3 additions & 3 deletions iridiumtk/reassembler/sbd.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
import sys
import datetime
import re
from util import to_ascii
from util import to_ascii, dt

from .base import *
from .ida import ReassembleIDA
Expand Down Expand Up @@ -210,11 +210,11 @@ def consume_l2(self,q):

if len(q.data)>0:
print("%s %-99s %s | %s"%(
datetime.datetime.fromtimestamp(q.time).strftime("%Y-%m-%dT%H:%M:%S"),
dt.epoch_local(int(q.time)).isoformat(),
hdr,q.data.hex(" "),to_ascii(q.data, dot=True)), file=outfile)
else:
print("%s %s"%(
datetime.datetime.fromtimestamp(q.time).strftime("%Y-%m-%dT%H:%M:%S"),
dt.epoch_local(int(q.time)).isoformat(),
hdr), file=outfile)

acars_labels={ # ref. http://www.hoka.it/oldweb/tech_info/systems/acarslabel.htm
Expand Down
45 changes: 45 additions & 0 deletions util.py
Original file line number Diff line number Diff line change
Expand Up @@ -189,3 +189,48 @@ def parse_channel(fstr):
else:
frequency=int(fstr)
return int(frequency)

class dt(datetime.datetime):
def isoformat(self, sep='T', timespec='auto'):
"""Return the time formatted according to ISO.
The full format looks like 'YYYY-MM-DD HH:MM:SS.mmmmmm'.
By default, the fractional part is omitted if self.microsecond == 0
or shortened to 'YYYY-MM-DD HH:MM:SS.mmm' if possible.
If self.tzinfo is not None, the UTC offset is also attached, giving
giving a full format of 'YYYY-MM-DD HH:MM:SS.mmmmmm+HHMM'.
if the UTC offset is 0, a 'Z' will be used, so the format is
shortened to 'YYYY-MM-DD HH:MM:SS.mmmmmmZ'.
Optional arguments exist for compability but should not be used.
"""

if self.microsecond != 0 and self.microsecond % 1000 == 0 and timespec == 'auto':
timespec = 'milliseconds'

trunc = False
if timespec == 'centiseconds':
timespec = 'milliseconds'
trunc = True

_iso = super().isoformat(sep, timespec)

if trunc and _iso[-6] == '+' and _iso[-10] == '.':
_iso = _iso[:-7] + _iso[-6:]
if _iso[-6:] == '+00:00':
_iso = _iso[:-6] + 'Z'
if (_iso[-6] == '+' or _iso[-6] == '-') and _iso[-3] == ':':
_iso = _iso[:-3] + _iso[-2:]
return _iso

@classmethod
def epoch(cls, t):
"""Construct a correct UTC datetime from a POSIX timestamp."""
return cls.fromtimestamp(t, datetime.timezone.utc)

@classmethod
def epoch_local(cls, t):
"""Construct a datetime from a POSIX timestamp in the local timezone."""
return cls.fromtimestamp(t, datetime.timezone.utc).astimezone()

0 comments on commit 47377de

Please sign in to comment.