4

The standard two line element (TLE) format contains times as 2-digit year plus decimal days, so 16012.375 would be January 12, 2016 at 09:00. Using python's time or datatime modules, how can I convert this to seconds after epoch? I think I should use structured time but I am not sure how. seconds_of is a fictitious function - need to replace with something real.

EDIT: It will be most helpful if the answer is long (verbose) - like one step per line or so, so I can understand what is happening.

EDIT 2: After seeing the comments from @J.F.Sebastian I looked at the link for TLE and found it nowhere states "UTC". So I should point out the initial information and final information are UTC. There is no reference to local time, time zone, or system time.

e.g.

tim = "16012.375"

year = 2000 + int(tim[0:2])
decimal_days = float(tim[2:])

print year, decimal_days

2016, 12.375

# seconds_of is a fictitious function - need to replace with something real
seconds_after_epoch = seconds_of(2016,1,1) + (3600. * 24.) * decimal_days
uhoh
  • 3,713
  • 6
  • 42
  • 95

2 Answers2

3

You could try something like this [EDIT according to the comments].

import datetime
import time
# get year 2 digit and floating seconds days 
y_d, nbs = "16012.375".split('.') 

# parse to datetime (since midnight and add the seconds) %j Day of the year as a zero-padded decimal number.
d = datetime.datetime.strptime(y_d, "%y%j") + datetime.timedelta(seconds=float("." + nbs) * 24 * 60 * 60)
# 1.0 => 1 day
# from time tuple get epoch time. 
time.mktime(d.timetuple())

#1481896800.0
Ali SAID OMAR
  • 6,404
  • 8
  • 39
  • 56
  • Fantastic! Thank you for adding the explanations as well. – uhoh Jan 18 '16 at 08:57
  • Right idea, but shouldn't it be `strptime(y_d, "%y%j")`? According to the docs (https://docs.python.org/2/library/datetime.html?highlight=datetime#strftime-and-strptime-behavior) `%j` represents day of the year as a 0-padded decimal. For the `timedelta`, shouldn't it be `seconds = float("."+nbs)*24*60*60`? – mtrw Jan 18 '16 at 10:09
  • OK I'm at a real computer now. Indeed @mtrw, `print d` returns `datetime.datetime(2016, 12, 16, 15, 0)` which is not right. It's most helpful to me if we do this one step at a time per line - also helps debugging. – uhoh Jan 18 '16 at 11:19
  • float("."nbs) is exactly the same than float("." + "375") – Ali SAID OMAR Jan 18 '16 at 13:45
  • fyi I've just asked a [follow up question](http://stackoverflow.com/q/35238827/3904031) – uhoh Feb 06 '16 at 08:10
2

It is easy to get datetime object given year and decimal_days:

>>> from datetime import datetime, timedelta
>>> year = 2016
>>> decimal_days = 12.375
>>> datetime(year, 1, 1) + timedelta(decimal_days - 1)
datetime.datetime(2016, 1, 12, 9, 0)

How to convert the datetime object into "seconds since epoch" depends on the timezone (local, utc, etc). See Converting datetime.date to UTC timestamp in Python e.g., if your input is in UTC then it is simple to get "seconds since the Epoch":

>>> utc_time = datetime(2016, 1, 12, 9, 0)
>>> (utc_time - datetime(1970, 1, 1)).total_seconds()
1452589200.0
Community
  • 1
  • 1
jfs
  • 399,953
  • 195
  • 994
  • 1,670
  • Thanks! I've just seen this now. In this case I'm only converting the format of a UTC value, so I can use `time.mktime(timetuple)` I've just asked a [follow up question](http://stackoverflow.com/q/35238827/3904031) – uhoh Feb 06 '16 at 08:12
  • @uhoh the post linked in my answer says explicitly that you should NOT use `mktime()` with UTC time. Follow the link. – jfs Feb 06 '16 at 09:08
  • Thanks again. Could you narrow down to which of the seven answers you are referring? That will be helpful to future readers of this question also. – uhoh Feb 06 '16 at 09:52
  • @uhoh : I'm referring to the accepted most-upvoted answer at the very top with my name on it. – jfs Feb 06 '16 at 10:02
  • OK, [that answer](http://stackoverflow.com/a/8778548/3904031) doesn't seem to be accepted anymore. Honestly it is way too long and complicated for me to understand that explanation of why not to use `mktime()` in my situation (UTC -> UTC). It has a bug? Would you consider telling me how TO do this then (see title of my question above)? – uhoh Feb 06 '16 at 10:07
  • See EDIT 2 - I'm surprised to see that the link *does not make it clear* that the TLE is UTC. I've made that clear in my other question but not here. – uhoh Feb 06 '16 at 10:19
  • 1
    @uhoh: I've added the explicit formula on how to get "seconds since the Epoch" from UTC time. It is not a bug in `mktime()`. `mktime()` accepts **local** time (and therefore you should not use it with **UTC** time unless your local timezone is UTC). [@Ali SAID OMAR's answer](http://stackoverflow.com/a/34850037/4279) is wrong because it uses `mktime()`. – jfs Feb 06 '16 at 20:43
  • Ah - I like that! Yes indeed that also *looks* right. Thank you for your persistence and help. I will delete the follow-up question, since your solution preserves the microseconds. For example with `tim = "16012.1111111"` as input, your solution gives `1452566399.99904` – uhoh Feb 07 '16 at 03:31