Convert TLE times (decimal days) to seconds after epoch - python

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

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

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

Related

conditional python; Time format newer than 30 minutes

I have a variable that has a stored created date as:
2022-09-01T19:40:17.268980742Z
In python, if i wanted to look at that time and say if 'created' is within than the last 30 minutes, do X.
EDIT
I have another command I can use (working within Palo XSOAR), that will give me the current date time in ISO.
So really want I'm trying to do is say:
if created is within the last 30 minutes:
do X
Assume I have to capture current time as ISO variable (can do)
Set a variable less than 30 minutes of the current time (not sure)
then if create time is between those two values do X (not sure)
Any help is appreciated -
Thanks,
You can use datetime.now() to get the current datetime. We can then coerce your datetime string into a datetime object, too. Then, we can look at the difference and apply some logic.
import datetime
some_string = '2022-09-01T19:40:17.268980742Z'
some_string = some_string.split('.')[0]
timestamp = datetime.datetime.fromisoformat(some_string)
current_time = datetime.datetime.now()
if (current_time - timestamp) < timedelta(minutes=30):
print('x')
else:
print('y')
Here are how the variables look:
>>> print(timestamp)
datetime.datetime(2022, 9, 1, 19, 40, 17)
>>> print(current_time)
datetime.datetime(2022, 9, 5, 4, 26, 14, 345147)
>>> print(current_time - timestamp)
datetime.timedelta(days=3, seconds=31557, microseconds=345147)
Note, I wasn't able to convert the provided timestamp of 2022-09-01T19:40:17.268980742Z to a datetime object using the fromisoformat. Trimming down the microseconds six decimal places worked fine, but seven throws an error. This is expected for datetime objects as the permissable resolution is Between 0 and 999999 inclusive (src: https://docs.python.org/3/library/datetime.html).
This is why I split the string.
Works:
some_string = '2022-09-01T19:40:17.268980'
timestamp = datetime.datetime.fromisoformat(some_string)
Error:
some_string = '2022-09-01T19:40:17.2689801'
timestamp = datetime.datetime.fromisoformat(some_string)

how to convert datetime-like string into milliseconds

I have a user-defined function (return_times) that takes json file and returns two datetime-like strings.
time_1, time_2= return_times("file.json")
print(time_1, time_2) # outputs: 00:00:11.352 00:01:51.936
By datetime-like string I mean 00:00:11.352 which suits '%H:%M:%S.%f' formatting. However, when I try to convert them into milliseconds, I get negative values.
from datetime import datetime
dt_obj_1 = datetime.strptime(time_1, '%H:%M:%S.%f')
start_ms = dt_obj_1.timestamp() * 1000
dt_obj_2 = datetime.strptime(time_2, '%H:%M:%S.%f')
end_ms = dt_obj_2.timestamp() * 1000
print(start_ms, end_ms ) # outputs: -2209019260648.0 -2209019160064.0
If I success I would like to trim a video with the following command:
from moviepy.video.io.ffmpeg_tools import ffmpeg_extract_subclip
ffmpeg_extract_subclip("long_video.mp4", start_ms, end_ms, targetname="video_trimmed.mp4"), so just delete ` * 1000` part.
Note that ffmpeg_extract_subclip requires its t1 and t2 parameters to be in seconds, not in milliseconds as I initially thought.
Because of those negative integers I am not able to successfully run the trimming process.
I searched the web that mainly discusses several formats for the year, month and day, but not '%H:%M:%S.%f'.
What may I be overlooking?
What may I be overlooking?
time.strptime docs
The default values used to fill in any missing data when more accurate
values cannot be inferred are (1900, 1, 1, 0, 0, 0, 0, 1, -1).
whilst start of epoch is 1970. You might get what you want by computing delta between what you parsed and default strptime as follows:
import datetime
time1 = "00:00:11.352"
delta = datetime.datetime.strptime(time1, "%H:%M:%S.%f") - datetime.datetime.strptime("", "")
time_s = delta.total_seconds()
print(time_s)
output
11.352
You need to add the year date (year, month, day) to datetime, else this will default to 1 January 1900.
What you do is this:
from datetime import datetime
s = "00:00:11.352"
f = '%H:%M:%S.%f'
datetime.strptime(s, f) # datetime.datetime(1900, 1, 1, 0, 0, 11, 352000)
One way to do this is to append the date-string to the time-string you receive from return_times
From https://stackoverflow.com/a/59200108/2681662
The year 1900 was before the beginning of the UNIX epoch, which
was in 1970, so the number of seconds returned by timestamp must be
negative.
What to do?
It's better to use a time object instead of a datetime object.
from datetime import time
time_1 = "00:00:11.352"
hours, minutes, seconds = time_1.split(":")
print(time(hour=int(hours), minute=int(minutes), second=int(float(seconds)),
microsecond=int(float(seconds) % 1 * 1000000)))
You can split the time string into hours, minutes, seconds and miliseconds and with some simple math calculations, you get the whole time in miliseconds

How to subtract datenow from time string?

I have a problem that seems really easy but I can't figure it out.
I want to achieve the following:
Time_as_string - time_now = minutes left until time as string.
I scrape a time from a website as a string, for example: '15:30'.
I want to subtract the current time from this to show how many minutes
are left untill the scraped time string.
I tried many things like strftime(), converting to unix timestamp, googling solutions etc.
I can make a time object from the string through strftime() but I can't subtract it from the current time.
What is the best way to achieve this?
from datetime import datetime
s = "15:30"
t1 = datetime.strptime(s,"%H:%M")
diff = t1 - datetime.strptime(datetime.now().strftime("%H:%M"),"%H:%M")
print(diff.total_seconds() / 60)
94.0
If '15:30' belongs to today:
#!/usr/bin/env python3
from datetime import datetime, timedelta
now = datetime.now()
then = datetime.combine(now, datetime.strptime('15:30', '%H:%M').time())
minutes = (then - now) // timedelta(minutes=1)
If there could be midnight between now and then i.e., if then is tomorrow; you could consider a negative difference (if then appears to be in the past relative to now) to be an indicator of that:
while then < now:
then += timedelta(days=1)
minutes = (then - now) // timedelta(minutes=1)
On older Python version, (then - now) // timedelta(minutes=1) doesn't work and you could use (then - now).total_seconds() // 60 instead.
The code assumes that the utc offset for the local timezone is the same now and then. See more details on how to find the difference in the presence of different utc offsets in this answer.
The easiest way is probably to subtract two datetimes from each other and use total_seconds():
>>> d1 = datetime.datetime(2000, 1, 1, 20, 00)
>>> d2 = datetime.datetime(2000, 1, 1, 16, 30)
>>> (d1 - d2).total_seconds()
12600.0
Note that this won't work if the times are in different timezones (I just picked January 1, 2000 to make it a datetime). Otherwise, construct two datetimes in the same timezones (or UTC), subtract those and use total_seconds() again to get the difference (time left) in seconds.

Subtracting Dates With Python

I'm working on a simple program to tell an individual how long they have been alive.
I know how to get the current date, and get their birthday. The only problem is I have no way of subtracting the two, I know a way of subtracting two dates, but unfortunately it does not include hours, minutes, or seconds.
I am looking for a method that can subtract two dates and return the difference down to the second, not merely the day.
from datetime import datetime
birthday = datetime(1988, 2, 19, 12, 0, 0)
diff = datetime.now() - birthday
print diff
# 8954 days, 7:03:45.765329
Use UTC time otherwise age in seconds can go backwards during DST transition:
from datetime import datetime
born = datetime(1981, 12, 2) # provide UTC time
age = datetime.utcnow() - born
print(age.total_seconds())
You also can't use local time if your program runs on a computer that is in a different place (timezone) from where a person was born or if the time rules had changed in this place since birthday. It might introduce several hours error.
If you want to take into account leap seconds then the task becomes almost impossible.
When substracting two datetime objects you will get a new datetime.timedelta object.
from datetime import datetime
x = datetime.now()
y = datetime.now()
delta = y - x
It will give you the time difference with resolution to microsencods.
For more information take a look at the official documentation.
Create a datetime.datetime from your date:
datetime.datetime.combine(birthdate, datetime.time())
Now you can subtract it from datetime.datetime.now().
>>> from datetime import date, datetime, time
>>> bday = date(1973, 4, 1)
>>> datetime.now() - datetime.combine(bday, time())
datetime.timedelta(14392, 4021, 789383)
>>> print datetime.now() - datetime.combine(bday, time())
14392 days, 1:08:13.593813
import datetime
born = datetime.date(2002, 10, 31)
today = datetime.date.today()
age = today - born
print(age.total_seconds())
Output: 463363200.0
Since DateTime.DateTime is an immutable type method like these always produce a new object the difference of two DateTime object produces a DateTime.timedelta type:
from datetime import date,datetime,time,timedelta
dt=datetime.now()
print(dt)
dt2=datetime(1997,7,7,22,30)
print(dt2)
delta=dt-dt2
print(delta)
print(int(delta.days)//365)
print(abs(12-(dt2.month-dt.month)))
print(abs(dt.day))
The output timedelta(8747,23:48:42.94) or what ever will be days when u test the code indicates that the time delta encodes an offset of 8747 days and 23hour and 48 minute ...
The Output
2021-06-19 22:27:36.383761
1997-07-07 22:30:00
8747 days, 23:57:36.383761
23 Year
11 Month
19 Day

python: convert year/month/day/hour/min/second to # seconds since Jan 1 1970

I know how to do it in C and Java, but I don't know a quick way of converting year/month/day/hour/min/second to the # of seconds since the Jan 1 1970 epoch.
Can someone help me?
So far I've figured out how to create a datetime object but I can't seem to get the elapsed # seconds since the epoch.
(edit: my question is the inverse of this other one: Python: Seconds since epoch to relative date)
Use timetuple or utctimetuple method to get time tuple and convert it to timestamp using time.mktime
>>> import datetime
>>> dt = datetime.datetime(2011, 12, 13, 10, 23)
>>> import time
>>> time.mktime(dt.timetuple())
1323793380.0
There is a nice bug related to it http://bugs.python.org/issue2736, this is interesting read and anybody trying to convert to timestamp should read this. According to that thread correct way is
timestamp = (dt - datetime(1970, 1, 1)) / timedelta(seconds=1)
You can use datetime.datetime(1970, 1, 1) as a reference and get the total amount of seconds from a datetime.timedelta object as follows:
from datetime import datetime
delta = your_date - datetime(1970, 1, 1)
delta.total_seconds()
import calendar
calendar.timegm(datetime_object.utctimetuple())
These lines can return a float number representing seconds since epoch.
import time
time.time()
To convert a datetime object (broken-downtime time: year/month/day/hour/min/second) to seconds since the Epoch (POSIX time):
seconds_since_epoch = datetime_object.timestamp()
Note: POSIX Epoch is "00:00:00 GMT, January 1, 1970".
If datetime_object has no timezone info then .timestamp() method uses a local timezone.
datetime.timestamp() method is introduced in Python 3.3; for code that works on older Python versions, see Converting datetime.date to UTC timestamp in Python.

Categories