Calculating time in Python output format - python

In this thread we have a good solution
How to calculate the time interval between two time strings
But how I can edit the output format?
From H:MM:SS to HH:MM, like 00:40 instead of 0:40:00
from datetime import datetime
from datetime import timedelta
T1 = input()
T2 = input()
format = '%H:%M'
tdiff = datetime.strptime(T1, format) - datetime.strptime(T2, format)
if tdiff.days < 0:
tdiff = timedelta(days = 0,
seconds = tdiff.seconds, microseconds = tdiff.microseconds)
print(tdiff)
EDIT: Thank you. This code below quite works, but the only problem is 7:45 instead of 07:45 for example. The code below removes the problem of seconds at the end. Now I only don't know how to force 0 is front of <10 hours format.
from datetime import datetime
from datetime import timedelta
T1 = input()
T2 = input()
format = '%H:%M'
tdiff = datetime.strptime(T1, format) - datetime.strptime(T2, format)
if tdiff.days < 0:
tdiff = timedelta(days = 0,
seconds = tdiff.seconds, microseconds = tdiff.microseconds)
print(str(tdiff).rstrip("0").rstrip(":"))

You're contradicting yourself by saying from H:MM:SS to HH:MM but you give an example of where you remove hours not seconds. Anyway, I'm guessing what you mean is that you want to remove any leading zeroes if they're empty (remove hours)?
In that case, there's two options. Either build the string yourself like so:
from datetime import datetime
from datetime import timedelta
T1 = '00:50'
T2 = '00:40'
format = '%H:%M'
tdiff = datetime.strptime(T1, format) - datetime.strptime(T2, format)
if tdiff.days < 0:
tdiff = timedelta(days = 0, seconds = tdiff.seconds, microseconds = tdiff.microseconds)
print(':'.join([block for block in str(tdiff).split(':') if block != '0']))
Where you skip single-digit zeroes (hours) but leave double-digit zeroes (seconds etc) intact.
Or you could do:
print(str(tdiff).lstrip("0").lstrip(":"))
Which simply strips the beginning. replace with .rstrip() if you need to strip the end.
And if you want to make sure there's always a two-digit representation in the first example, you could do:
print(':'.join(['{:02}'.format(int(block)) for block in str(tdiff).split(':') if block != '0']))
At this point, you're monkey-patching a problem that most likely could be solved in a neater and more efficient way, and your original problem description is not really in line with what you're asking/trying to fix. But this is one way of doing it.
If you want to remove seconds but keep hours intact, do something like:
print(':'.join(['{:02}'.format(int(block)) for block in str(tdiff).split(':')[:-1]]))

Related

How to remove date from datetime object

I have a method that converts a string to a datetime object using strptime("%I:%M %p"), I only want the hours in 24 and minutes without any dates, because I will get the difference between this time and another time. The problem is that when I try to get the difference with total_seconds(), it gets difference in negative because the date in the strptime is "1900-01-01". Does any one have any ideas how to solve this?
My Code:
fTime = datetime.strptime(time, "%I:%M %p")
if 0 < (fTime - datetime.now()).total_seconds() <= 3600:
return True
You can take one of two approaches: strip the date out of now, or add the current date to fTime. The first approach makes little sense, since you can't compare time objects like that anyway.
To convert fTime to a proper datetime, datetime.combine it with date.today():
fDate = datetime.combine(date.today(), fTime.time())
return 0 < (fDate - datetime.now()).total_seconds() <= 3600
Alternatively, you can replace the date portion:
today = date.today()
fDate = fTime.replace(year=today.year, month=today.month, day=today.day)
Personally, I would go with combine because it's less awkward code.

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

Python - Is current time within two datetime values

I've looked around here for a while trying all different kinds of accepted answers, but they are too irrelevant for my own needs and 90% require static typing of the current date which is something I don't want to do
Context
Quite simple.
Get the current time in Spain.
Have a variable already set up which is an agreed start time.
Have a variable already set up which is an agreed end time.
If the current time in Spain is between the start-end time, proceed with saving logs
Threads checked for solution to my problem
All useless, downvoted, or irrelevant due to static typing of datetime
Python current time
Compare dates Python
Convert string into datetime
Compare date and datetime
Check if time is between two days
Convert string into datetime
Compare if datetime.timedelta is between two values
Code so far
now_time_uk = datetime.datetime.now()
current_time_spain = now_time + datetime.timedelta(hours=1)
start = datetime.time(10, 50)
end = datetime.time(16, 00)
if current_time_spain >= start or current_time_spain <= end:
print('Start logging')
else:
print('No need to log')
The code above was extracted from a thread on S.O which was an accepted answer, when I ran this, it gives a TypeError
TypeError: can't compare datetime.datetime to datetime.time
Accepted Answer Code
now_time_uk = datetime.datetime.now()
print(now_time_uk)
current_time_spain = now_time_uk + datetime.timedelta(hours=1)
start = datetime.time(10, 50)
end = datetime.time(17, 00)
print(current_time_spain.time())
if current_time_spain.time() >= start and current_time_spain.time() <= end:
print('Start logging')
else:
print('No need to log')
Like the error says you are trying to compare datetime objects with time objects which isn't possible... luckily the datetime object has a builtin method for converting to a time object, and that is .time(). So you can replace:
if current_time_spain >= start or current_time_spain <= end:
With
if current_time_spain.time() >= start or current_time_spain.time() <= end:
And it should work. Another way of doing it is setting current_time_spain from the beginning as a time object or another option is to set the start and end times to be datetime objects instead of time
You're comparing datetime object with date & time with only time , as mentioned in error
datetime.datetime.now() this returns datetime whereas datetime.time(10, 50) returns time.
If you want to only compare time then why you don't simply compare hours and minutes from now()
You can’t compare a date time within a time but you could continue to use a TimeDelta in order to create a start and end date to compare. With this solution your code could become:
now_time_uk = date time.datetime.now()
current_time_spain = now_time + datetime.timedelta(hours=1)
start_hours = 10
start_minutes = 50
end_hours = 16
end_minutes = 0
time_spain_start = current_time_spain + datetime.timedelta(hours=start_hours, minutes=start_minutes)
time_spain_end = current_time_spain + datetime.timedelta(hours=end_hours, minutes=end_minutes)
if current_time_spain >= time_spain_start or current_time_spain <= spain_time_end:
print “Start logging”
else:
print “No need to log”
In this way you can also add a variable for each parameter of the TimeDelta object in order to have different time for the end date even if the day is the next or whatever you want or need. We can imagine to have all variable days, hours, minutes, and seconds initialized to the 0 value, so you need to change only the value you need.

Convert timestamps of "yyyy-MM-dd'T'HH:mm:ss.SSSZ" format in Python

I have a log file with timestamps like "2012-05-12T13:04:35.347-07:00". I want to convert each timestamp into a number so that I sort them by ascending order based on time.
How can I do this in Python? In Java I found out that I can convert timestamps for such format with SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ") but for Python I couldn't find anything.
As py2.x has issues with the %z directive you've to do something like this:
from datetime import timedelta,datetime
strs = "2012-05-12T13:04:35.347-07:00"
#replace the last ':' with an empty string, as python UTC offset format is +HHMM
strs = strs[::-1].replace(':','',1)[::-1]
As datetime.striptime doesn't supports %z(UTC offset)(at least not in py2.x), so you need a work around:
#Snippet taken from http://stackoverflow.com/a/526450/846892
try:
offset = int(strs[-5:])
except:
print "Error"
delta = timedelta(hours = offset / 100)
Now apply formatting to : '2012-05-12T13:04:35.347'
time = datetime.strptime(strs[:-5], "%Y-%m-%dT%H:%M:%S.%f")
time -= delta #reduce the delta from this time object
print time
#2012-05-12 20:04:35.347000

How to calculate the time interval between two time strings

I have two times, a start and a stop time, in the format of 10:33:26 (HH:MM:SS). I need the difference between the two times. I've been looking through documentation for Python and searching online and I would imagine it would have something to do with the datetime and/or time modules. I can't get it to work properly and keep finding only how to do this when a date is involved.
Ultimately, I need to calculate the averages of multiple time durations. I got the time differences to work and I'm storing them in a list. I now need to calculate the average. I'm using regular expressions to parse out the original times and then doing the differences.
For the averaging, should I convert to seconds and then average?
Yes, definitely datetime is what you need here. Specifically, the datetime.strptime() method, which parses a string into a datetime object.
from datetime import datetime
s1 = '10:33:26'
s2 = '11:15:49' # for example
FMT = '%H:%M:%S'
tdelta = datetime.strptime(s2, FMT) - datetime.strptime(s1, FMT)
That gets you a timedelta object that contains the difference between the two times. You can do whatever you want with that, e.g. converting it to seconds or adding it to another datetime.
This will return a negative result if the end time is earlier than the start time, for example s1 = 12:00:00 and s2 = 05:00:00. If you want the code to assume the interval crosses midnight in this case (i.e. it should assume the end time is never earlier than the start time), you can add the following lines to the above code:
if tdelta.days < 0:
tdelta = timedelta(
days=0,
seconds=tdelta.seconds,
microseconds=tdelta.microseconds
)
(of course you need to include from datetime import timedelta somewhere). Thanks to J.F. Sebastian for pointing out this use case.
Try this -- it's efficient for timing short-term events. If something takes more than an hour, then the final display probably will want some friendly formatting.
import time
start = time.time()
time.sleep(10) # or do something more productive
done = time.time()
elapsed = done - start
print(elapsed)
The time difference is returned as the number of elapsed seconds.
Here's a solution that supports finding the difference even if the end time is less than the start time (over midnight interval) such as 23:55:00-00:25:00 (a half an hour duration):
#!/usr/bin/env python
from datetime import datetime, time as datetime_time, timedelta
def time_diff(start, end):
if isinstance(start, datetime_time): # convert to datetime
assert isinstance(end, datetime_time)
start, end = [datetime.combine(datetime.min, t) for t in [start, end]]
if start <= end: # e.g., 10:33:26-11:15:49
return end - start
else: # end < start e.g., 23:55:00-00:25:00
end += timedelta(1) # +day
assert end > start
return end - start
for time_range in ['10:33:26-11:15:49', '23:55:00-00:25:00']:
s, e = [datetime.strptime(t, '%H:%M:%S') for t in time_range.split('-')]
print(time_diff(s, e))
assert time_diff(s, e) == time_diff(s.time(), e.time())
Output
0:42:23
0:30:00
time_diff() returns a timedelta object that you can pass (as a part of the sequence) to a mean() function directly e.g.:
#!/usr/bin/env python
from datetime import timedelta
def mean(data, start=timedelta(0)):
"""Find arithmetic average."""
return sum(data, start) / len(data)
data = [timedelta(minutes=42, seconds=23), # 0:42:23
timedelta(minutes=30)] # 0:30:00
print(repr(mean(data)))
# -> datetime.timedelta(0, 2171, 500000) # days, seconds, microseconds
The mean() result is also timedelta() object that you can convert to seconds (td.total_seconds() method (since Python 2.7)), hours (td / timedelta(hours=1) (Python 3)), etc.
This site says to try:
import datetime as dt
start="09:35:23"
end="10:23:00"
start_dt = dt.datetime.strptime(start, '%H:%M:%S')
end_dt = dt.datetime.strptime(end, '%H:%M:%S')
diff = (end_dt - start_dt)
diff.seconds/60
This forum uses time.mktime()
Structure that represent time difference in Python is called timedelta. If you have start_time and end_time as datetime types you can calculate the difference using - operator like:
diff = end_time - start_time
you should do this before converting to particualr string format (eg. before start_time.strftime(...)). In case you have already string representation you need to convert it back to time/datetime by using strptime method.
I like how this guy does it — https://amalgjose.com/2015/02/19/python-code-for-calculating-the-difference-between-two-time-stamps.
Not sure if it has some cons.
But looks neat for me :)
from datetime import datetime
from dateutil.relativedelta import relativedelta
t_a = datetime.now()
t_b = datetime.now()
def diff(t_a, t_b):
t_diff = relativedelta(t_b, t_a) # later/end time comes first!
return '{h}h {m}m {s}s'.format(h=t_diff.hours, m=t_diff.minutes, s=t_diff.seconds)
Regarding to the question you still need to use datetime.strptime() as others said earlier.
Try this
import datetime
import time
start_time = datetime.datetime.now().time().strftime('%H:%M:%S')
time.sleep(5)
end_time = datetime.datetime.now().time().strftime('%H:%M:%S')
total_time=(datetime.datetime.strptime(end_time,'%H:%M:%S') - datetime.datetime.strptime(start_time,'%H:%M:%S'))
print total_time
OUTPUT :
0:00:05
import datetime as dt
from dateutil.relativedelta import relativedelta
start = "09:35:23"
end = "10:23:00"
start_dt = dt.datetime.strptime(start, "%H:%M:%S")
end_dt = dt.datetime.strptime(end, "%H:%M:%S")
timedelta_obj = relativedelta(start_dt, end_dt)
print(
timedelta_obj.years,
timedelta_obj.months,
timedelta_obj.days,
timedelta_obj.hours,
timedelta_obj.minutes,
timedelta_obj.seconds,
)
result:
0 0 0 0 -47 -37
Both time and datetime have a date component.
Normally if you are just dealing with the time part you'd supply a default date. If you are just interested in the difference and know that both times are on the same day then construct a datetime for each with the day set to today and subtract the start from the stop time to get the interval (timedelta).
Take a look at the datetime module and the timedelta objects. You should end up constructing a datetime object for the start and stop times, and when you subtract them, you get a timedelta.
you can use pendulum:
import pendulum
t1 = pendulum.parse("10:33:26")
t2 = pendulum.parse("10:43:36")
period = t2 - t1
print(period.seconds)
would output:
610
import datetime
day = int(input("day[1,2,3,..31]: "))
month = int(input("Month[1,2,3,...12]: "))
year = int(input("year[0~2020]: "))
start_date = datetime.date(year, month, day)
day = int(input("day[1,2,3,..31]: "))
month = int(input("Month[1,2,3,...12]: "))
year = int(input("year[0~2020]: "))
end_date = datetime.date(year, month, day)
time_difference = end_date - start_date
age = time_difference.days
print("Total days: " + str(age))
Concise if you are just interested in the time elapsed that is under 24 hours. You can format the output as needed in the return statement :
import datetime
def elapsed_interval(start,end):
elapsed = end - start
min,secs=divmod(elapsed.days * 86400 + elapsed.seconds, 60)
hour, minutes = divmod(min, 60)
return '%.2d:%.2d:%.2d' % (hour,minutes,secs)
if __name__ == '__main__':
time_start=datetime.datetime.now()
""" do your process """
time_end=datetime.datetime.now()
total_time=elapsed_interval(time_start,time_end)
Usually, you have more than one case to deal with and perhaps have it in a pd.DataFrame(data) format. Then:
import pandas as pd
df['duration'] = pd.to_datetime(df['stop time']) - pd.to_datetime(df['start time'])
gives you the time difference without any manual conversion.
Taken from Convert DataFrame column type from string to datetime.
If you are lazy and do not mind the overhead of pandas, then you could do this even for just one entry.
Here is the code if the string contains days also [-1 day 32:43:02]:
print(
(int(time.replace('-', '').split(' ')[0]) * 24) * 60
+ (int(time.split(' ')[-1].split(':')[0]) * 60)
+ int(time.split(' ')[-1].split(':')[1])
)

Categories