0

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?

Lzypenguin
  • 945
  • 1
  • 7
  • 18
  • 1
    Just to clarify, if you have for example a time difference of 1 day and 1 hour, do you want it to return just 1 hour or 25 hours? – Michael Cao Jan 23 '23 at 17:59
  • Does this answer your question? [Convert timedelta to total seconds](https://stackoverflow.com/questions/5522031/convert-timedelta-to-total-seconds) Then convert the total seconds into whatever units you need – Pranav Hosangadi Jan 23 '23 at 18:55
  • I want it to return 25 hours @MichaelCao – Lzypenguin Jan 23 '23 at 19:06

2 Answers2

2

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)
Mark Tolonen
  • 166,664
  • 26
  • 169
  • 251
  • Ahhhhhh total seconds will actually be perfect for me. I am telling my program to sleep and wait that many seconds anyways, and just multiplying the hours by 3600 and the minutes by 60 then summing it all. This will help me tremendously!!! Thank you! – Lzypenguin Jan 23 '23 at 19:40
1

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
Edo Akse
  • 4,051
  • 2
  • 10
  • 21