How to get a time interval between two strings? - python

I have 2 times stored in separate strings in the form of H:M I need to get the difference between these two and be able to tell how much minutes it equals to. I was trying datetime and timedelta, but I'm only a beginner and I don't really understand how that works. I'm getting attribute errors everytime.
So I have a and b times, and I have to get their difference in minutes.
E.G. if a = 14:08 and b= 14:50 the difference should be 42
How do I do that in python in the simplest way possible? also, in what formats do I need to use for each step?

I assume the difference is 42, not 4 (since there are 42 minutes between 14:08 and 14:50).
If the times always contains of a 5 character length string, than it's reasonably easy.
time1 = '14:08'
time2 = '15:03'
hours = int(time2[:2]) - int(time1[:2])
mins = int(time2[3:]) - int(time1[3:])
print(hours)
print(mins)
print(hours * 60 + mins)
Prints:
1
-5
55
hours will be the integer value of the left two digits [:1] subtraction of the second and first time
minutes will be the integer value of the right two digits [3:] subtraction of the second and first time
This prints 55 ... with your values it prints out 42 (the above example is to show it also works when moving over a whole hour.

You can use datetime.strptime
also the difference is 42 not 4 50-8==42 I assume that was a typo
from datetime import datetime
a,b = "14:08", "14:50"
#convert to datetime
time_a = datetime.strptime(a, "%H:%M")
time_b = datetime.strptime(b, "%H:%M")
#get timedelta from the difference of the two datetimes
delta = time_b - time_a
#get the minutes elapsed
minutes = (delta.seconds//60)%60
print(minutes)
#42

You can get the difference between the datetime.timedelta objects created from the given time strings a and b by subtracting the former from the latter, and use the total_seconds method to obtain the time interval in seconds, with which you can convert to minutes by dividing it by 60:
from datetime import timedelta
from operator import sub
sub(*(timedelta(**dict(zip(('hours', 'minutes'), map(int, t.split(':'))))) for t in (b, a))).total_seconds() // 60
So that given a = '29:50' and b = '30:08', this returns:
18.0

Related

Trying to find the difference between 2 datetime objects and getting only Hours, Minutes, and Seconds [duplicate]

This question already has answers here:
Convert timedelta to total seconds
(4 answers)
Closed 27 days ago.
I am pulling an ending time from a json api response. Then I am trying to calculate the time remaining, before the end time, to call a function after it ends.
end_time_string = data['endTime'] # Get the end time in a string in weird format
date_format = "%Y%m%dT%H%M%S.%fZ" # Specify the date format for the datetime parser
end_time = datetime.strptime(end_time_string, date_format) # turn the date time string into datetime object
current_time = datetime.utcnow() # Get current time in UTC time zone, which is what CoC uses.
time_remaining = end_time - current_time # Get the time remaining till end of war
My end_time is a datetime object. My current_time is a datetime object. But time_remaining is a timedelta object. I am able to pull the hours, minutes and seconds from the object using:
hours, minutes, seconds = map(float, str(time_remaining).split(':'))
But the problem is that sometimes the time_remaining has days in it, and sometimes it doesn't.
1 day, 4:55:22.761359
-1 days, 23:59:08.45766
When there are days involved, specifically when the timedelta object goes negative, my script fails.
What is the best find the amount of time between my two datetime objects in ONLY hours, minutes, and seconds, without days included?
timedelta is an object. One of its methods is total_seconds() so dividing by 3600 gives hours. Also dividing by another timedelta gives a float result of the ratio, so divide by timedelta(hours=1) to get the time in hours:
>>> import datetime as dt
>>> x = dt.timedelta(days=1, seconds=5000)
>>> x.total_seconds() / 3600
25.38888888888889
>>> x / dt.timedelta(hours=1)
25.38888888888889
or in hours, minutes, seconds:
>>> hours, remaining_seconds = divmod(x.total_seconds(), 3600)
>>> minutes, seconds = divmod(remaining_seconds, 60)
>>> hours, minutes, seconds
(25.0, 23.0, 20.0)
So, a timedelta object has days, seconds and microseconds. Multiply the days by 24 to convert it into hours, and then some nice math with modulo (%) and the usefull // operator, for which I will quote something:
//: Divides the number on its left by the number on its right, rounds
down the answer, and returns a whole number.
combining everything you get a nice f-string with padding for the zeros:
f"{td.seconds//3600 + td.days*24:02}:{(td.seconds//60)%60:02}:{td.seconds%60:02}:{td.microseconds:06}"
To put this into code:
from datetime import datetime, timedelta
# 3670 seconds is 1h1m10s
tomorrow = datetime.utcnow() + timedelta(1, 3670, 123)
current_time = datetime.utcnow()
td = tomorrow - current_time
print(td)
print(td.days)
print(td.seconds)
print(td.microseconds)
print(f"{td.seconds//3600 + td.days*24:02}:{(td.seconds//60)%60:02}:{td.seconds%60:02}:{td.microseconds:06}")
Which generates the following output:
1 day, 1:01:10.000123
1
3670
123
25:01:10:000123

How to find the difference between two times

I'm trying to figure out a way to take two times from the same day and figure out the difference between them. So far shown in the code below I have converted both of the given times into Int Vars and split the strings to retrieve the information. This works well but when the clock in values minute is higher than the clock out value it proceeds to give a negative value in minute slot of the output.
My current code is:
from datetime import datetime
now = datetime.now()
clocked_in = now.strftime("%H:%M")
clocked_out = '18:10'
def calc_total_hours(clockedin, clockedout):
in_hh, in_mm = map(int, clockedin.split(':'))
out_hh, out_mm = map(int, clockedout.split(':'))
hours = out_hh - in_hh
mins = out_mm - in_mm
return f"{hours}:{mins}"
print(calc_total_hours(clocked_in, clocked_out))
if the clocked in value is 12:30 and the clocked out value is 18:10
the output is:
6:-20
the output needs to be converted back into a stand time format when everything is done H:M:S
Thanks for you assistance and sorry for the lack of quality code. Im still learning! :D
First, in order to fix your code, you need to convert both time to minutes, compute the difference and then convert it back to hours and minutes:
clocked_in = '12:30'
clocked_out = '18:10'
def calc_total_hours(clockedin, clockedout):
in_hh, in_mm = map(int, clockedin.split(':'))
out_hh, out_mm = map(int, clockedout.split(':'))
diff = (in_hh * 60 + in_mm) - (out_hh * 60 + out_mm)
hours, mins = divmod(abs(diff) ,60)
return f"{hours}:{mins}"
print(calc_total_hours(clocked_in, clocked_out))
# 5: 40
Better way to implement the time difference:
import time
import datetime
t1 = datetime.datetime.now()
time.sleep(5)
t2 = datetime.datetime.now()
diff = t2 - t1
print(str(diff))
Output:
#h:mm:ss
0:00:05.013823
Probably the most reliable way is to represent the times a datetime objects, and then take one from the other which will give you a timedelta.
from datetime import datetime
clock_in = datetime.now()
clock_out = clock_in.replace(hour=18, minute=10)
seconds_diff = abs((clock_out - clock_in).total_seconds())
hours, minutes = seconds_diff // 3600, (seconds_diff // 60) % 60
print(f"{hours}:{minutes}")

Why is the diff of two datetime objects so?

datetime1 = '2020-08-19 10:13:19'
datetime2 = '2020-08-19 19:00:00'
diff = datetime1 - datetime2
The diff is a timedelta object, with:
diff.days = -1
diff.seconds = 54766 = 15.22 hours
There are only about 9 hours diff between the two datetimes. Why does it show the number of days is '1' and 15.22 hours? How to understand the diff of two datetimes?
If you subtract the earlier datetime from the later datetime, you get a positive timedelta, as one would expect.
The other way around, you get a negative timedelata in the unusual format.
But when you calculate -1 day + 15 hours = -24 hours + 15 hours = -9 hours, the result is correct.
Of course, doing this calculation manually is not what we want.
So, either avoid subtracting a later datetime from an earlier datetime:
# to get an absolute timedelta
if datetime2 > datetime1:
print(datetime2 - datetime1)
else:
print(datetime1 - datetime2)
Or use .total_seconds():
print((datetime1 - datetime2).total_seconds())
-31601.0
print((datetime2 - datetime1).total_seconds())
31601.0
In this example, the difference between two datetime objects has a negative number of days, and a positive number of hours.
import datetime
datetime1 = datetime.datetime.fromisoformat('2020-08-19 10:13:19')
datetime2 = datetime.datetime.fromisoformat('2020-08-19 19:00:00')
print(datetime1 - datetime2)
-1 day, 15:13:19
# divide by timedelta() (with argument of hours, minutes, seconds, etc.
print((datetime1 - datetime2) / datetime.timedelta(hours=1)) # in hours
-8.778055555555556
Here is an interesting interview with the core developer who maintains date / time in CPython: https://talkpython.fm/episodes/show/271/unlock-the-mysteries-of-time-pythons-datetime-that-is
UPDATE
You can calculate time difference in minutes, or days, or other units, by supplying a different parameter to .timedelta():
print((datetime1 - datetime2) / datetime.timedelta(minutes=1)) # in minutes
-526.68
print((datetime1 - datetime2) / datetime.timedelta(days=1)) # in days
-0.3658

How to read minute values greater than 60 and avoid ValueError: time data '60:01' does not match format '%M:%S'

I've a script that reads a corrupt .CUE file that has no INDEX 00 and retreives the minutes and seconds value of each track entry. When the values are found the script subtracts 02 seconds of each track (thus creating a pregap and correcting the .CUE file) and creates a new correct .CUE file. The script worked like a charm till it encountered .CUE files containing minute values greater than 60. The following error occured:
ValueError: time data '60:01' does not match format '%M:%S'
I used datetime because i couldn't just simply subtract the 02 secondes of each track entry as an integer. When an entry has an 'INDEX 01' seconds value of 01 seconds it will also affect the minute value when 02 seconds are subtracted since this means that the minute value will be reduced by 01.
This is part of the code that does the formatting and subtraction. This worked fine till it encountered a minute value than 60:
from datetime import datetime
WrongIndex = '60:01'
NewIndex = '00:02'
format = '%M:%S'
time = datetime.strptime(WrongIndex, format) - datetime.strptime(NewIndex, format)
The expected returned value in this case should be '59:59'.
I'd like to know if there are other ways to use minute values greater than 60 since the max length of these files can go up to 79.8 minutes.
I don't think a datetime object is really an appropriate data structure for your problem. That type expects to be referencing a real clock time, not just an arbitrary number of minutes and seconds. If you were sticking with datetime, a more appropriate type would probably be timedelta, which represents a period of time, unmoored from any specific clock or calendar. But there's no equivalent to strptime for timedeltas.
And without the parsing, you don't get much from datetime at all. So I suggest just doing the parsing yourself. It's not very difficult:
minutes, seconds = map(int, WrongIndex.split(':'))
This just splits your input string (e.g. '60:01') into a list with two values (['60', '01']). It then converts the string values into integers. Then it assigns the two integers to the variables minutes and seconds.
To make doing math easy, you can then combine the two values into a single integer, a count of seconds:
seconds += minutes * 60
Then you can subtract your two-second offset and convert the number of seconds back to a time string:
seconds -= 2 # or parse the offset string if you don't want to hard code two seconds
result = "{:02}:{:02}".format(*divmod(seconds, 60))
In the formatting step, I'm using the divmod function which computes the a floor division, and a modulus in one step (it returns both in a tuple).
You need to do some converting. I would convert your values to integers. If minutes is greater than 59, we will add it to hours. After that we can create a datetime object which we use to subtract. To get minutes, we take our deltas in seconds and divided it with 60
from datetime import datetime
def to_time(value):
"Takes in values as '%M:%S' and return datetime object"
# value casting to integers
minutes, seconds = [int(i) for i in value.split(':')]
# if minutes is greater than 59 pass it to hour
hour = 0
if minutes > 59:
hour = minutes//60
minutes = minutes%60
return datetime.strptime(f'{hour}:{minutes}:{seconds}', '%H:%M:%S')
# now our calculations
wrong_index = '60:01'
new_index = '00:02'
time_ = to_time(wrong_index) - to_time(new_index)
print(time_.seconds/60)
How about this:
import datetime
WrongIndex = '60:01'
NewIndex = '00:02'
wrong_time = WrongIndex.split(':')
new_index = NewIndex.split(':')
old_seconds = int(wrong_time[0])*60 + int(wrong_time[1])
new_seconds = int(new_index[0])*60 + int(new_index[1])
time = datetime.timedelta(seconds=old_seconds-new_seconds)
print(time)

Python: date time difference giving incorrect result

I have written a simple code to check if the time difference between 2 date timestamps is more than 7 days, which comes to 604,800 seconds.
If the time in seconds is more than 604,800 then it should print "Relax you have time!!!"
Please find my code below:
import time, datetime, sys, os
start_time = time.time()
from datetime import datetime, timedelta, date
from dateutil.parser import *
datetime1="2018-07-13 03:30:00"
datetime2="2018-07-20 04:30:00"
datetime2=datetime.strptime(datetime2, "%Y-%m-%d %H:%M:%S").date() # this is to convert it into a datetime object
datetime1=datetime.strptime(datetime1, "%Y-%m-%d %H:%M:%S").date() # this is to convert it into a datetime object
difference1 =(datetime2-datetime1).total_seconds()
print("the difference in seconds is "+str(difference1))
if difference1 > 604800: #if the difference is more than 7 days, relax , else start preparing
print("Relax you have time!!!")
else:
print("You need to start preparing!!!!!")
Problem:
The code somehow calculates the time in seconds to be more than 604800 only if I change the "datetime2" to "2018-07-21" which means that it is calculating the difference in rounded-off days and not seconds and then simply converting the rounded-off days into seconds, giving the incorrect answer.
For example, in the above code, since "datetime2" is in reality away from "datetime1" by more than 604,800 seconds(to be precise it is 608,400 seconds away), the output should be "Relax you have time!!!", but we get a different output.
What have I done to solve this?
Till now I have looked at similar questions:
How do I check the difference, in seconds, between two dates? (did not work for me as I got TypeError: an integer is required (got type datetime.date))
and
Time difference in seconds (as a floating point) (this caters to only very tiny time differences and does not capture a scenario when user enters timestamps himself)
and
How to calculate the time interval between two time strings (this is what I have done in my code, but it does not work as expected)
Can you please suggest the problem in my code?
UPDATE: Thanks to #Tim Peters for pointing out that .date() discards the hours,mins and seconds.
I only needed to discard .date() for it to work correctly.
In this case the issue is that you create two datetime.datetime objects with strptime and immediately truncate them to datetime.date objects, which don't have the time components (hours, minutes, seconds, microseconds, tzinfo), so you get two calendar dates which are exactly 7 days apart.
You can fix your original code like this:
from datetime import datetime, timedelta
datetime1 = "2018-07-13 03:30:00"
datetime2 = "2018-07-20 04:30:00"
# The following creates two datetime.datetime objects
datetime2 = datetime.strptime(datetime2, "%Y-%m-%d %H:%M:%S")
datetime1 = datetime.strptime(datetime1, "%Y-%m-%d %H:%M:%S")
difference1 =(datetime2-datetime1).total_seconds()
print("the difference in seconds is "+str(difference1))
# if the difference is more than 7 days, relax , else start preparing
if difference1 > 604800:
print("Relax you have time!!!")
else:
print("You need to start preparing!!!!!")
But one additional thing to note is that datetime.timedelta objects can be directly compared, so you do not need to calculate the number of seconds, so you can change that part to avoid the "number of seconds" calculation (and your intention is clearer):
difference1 = datetime2 - datetime1
# if the difference is more than 7 days, relax , else start preparing
if difference1 > timedelta(days=7):
I imagine that in reality you are not constructing the datetime.datetime objects from string literals as you have in this example, but in case you are, I would also note that you can directly construct those literals as well, so with that refactoring in place, here's how I would have written your example:
from datetime import datetime, timedelta
# The following creates two datetime.datetime objects
datetime1 = datetime(2018, 7, 13, 3, 30)
datetime2 = datetime(2018, 7, 20, 4, 30)
difference1 = datetime2 - datetime1
# if the difference is more than 7 days, relax , else start preparing
if difference1 > timedelta(days=7):
print("Relax you have time!!!")
else:
print("You need to start preparing!!!!!")

Categories

Resources