I am exporting a list of timedeltas to csv and the days really messes up the format. I tried this:
while time_list[count] > datetime.timedelta(days = 1):
time_list[count] = (time_list[count] - datetime.timedelta(days = 1)) + datetime.timedelta(hours = 24)
But it's instantly converted back into days and creates an infinite loop.
By default the str() conversion of a timedelta will always include the days portion. Internally, the value is always normalised as a number of days, seconds and microseconds, there is no point in trying to 'convert' days to hours because no separate hour component is tracked.
If you want to format a timedelta() object differently, you can easily do so manually:
def format_timedelta(td):
minutes, seconds = divmod(td.seconds + td.days * 86400, 60)
hours, minutes = divmod(minutes, 60)
return '{:d}:{:02d}:{:02d}'.format(hours, minutes, seconds)
This ignores any microseconds portion, but that is trivially added:
return '{:d}:{:02d}:{:02d}.{:06d}'.format(hours, minutes, seconds, td.microseconds)
Demo:
>>> format_timedelta(timedelta(days=2, hours=10, minutes=20, seconds=3))
'58:20:03'
>>> format_timedelta(timedelta(hours=10, minutes=20, seconds=3))
'10:20:03'
If you are ignoring the days in the count, you can convert the timedelta directly.
def timedelta_to_time(initial_time: timedelta) -> time:
hour = initial_time.seconds//3600
minute = (initial_time.seconds//60) % 60
second = initial_time.seconds - (hour*3600 + minute*60)
return str(datetime.strptime(
f"{hour}:{minute}:{second}", "%H:%M:%S"
).time())
Example:
timedelta_to_time(timedelta(days=2, hours=10, minutes=20, seconds=3))
>> '10:20:03'
timedelta_to_time(timedelta(hours=10, minutes=20, seconds=3))
>> '10:20:03'
Related
How would I go about converting a float like 3.65 into 4 mins 5 seconds.
I have tried using:
print(datetime.datetime.strptime('3.35','%M%-S'))
However, I get this back:
ValueError: '-' is a bad directive in format '%-M:%-S'
Take a look at the following script, you can figure out how to make it work for days years, etc, this only works if we assume the format is "hours.minutes"
import datetime
# Assuming the 3 represents the hours and the 0.65 the minutes
number = 3.65
# First, we need to split the numbero into its whole decimal part
# and its decimal part
whole_decimal_part = hours = int(number) # 3
decimal_part = number % whole_decimal_part # 0.6499999
# Now, we need to know how many extra hours are in the decimal part
extra_hours = round((decimal_part * 100) / 60) # 1
minutes = round((decimal_part * 100) % 60) # 5
hours += extra_hours # 4
time_str = "%(hours)s:%(minutes)s" % {
"hours": hours,
"minutes": minutes
} # 4:5
final_time = datetime.datetime.strptime(time_str, "%H:%M").time()
print(final_time) # 04:05:00
First, you should complain to whoever is giving you time data expressed like that.
If you need to process minutes and seconds as a standalone value, then the datetime object may not your best choice either.
If you still need to convert "3.65" into a datetime object corresponding to "4-05" you could adjust it to be a valid time representation before passing it to strptime()
m,s = map(int,"3.65".split("."))
m,s = (m+s)//60,s%60
dt = datetime.datetime.strptime(f"{m}-{s}","%M%-S")
Split your time into minute and seconds
If seconds is 60 or more, then add extra minutes (//) ; second is the modulo (%)
t="3.65"
m, s = [int(i) for i in t.split('.')]
if s >= 60:
m += s//60
s = s % 60
print(f'{m} mins {s} seconds') # -> 4 mins 5 seconds
while 65 seconds cannot be parsed correctly so you have to manipulate by yourself to clean the data first before parsing.
NOTE: assuming seconds is not a very very big number which can make minutes>60
import datetime
time= '3.65'
split_time = time.split(".")
minute =int(split_time[0])
seconds = int(split_time[1])
minute_offset, seconds = divmod(seconds, 60);
minute = int(split_time[0]) + minute_offset
print(datetime.datetime.strptime('{}.{}'.format(minute,seconds),'%M.%S')) #1900-01-01 00:04:05
You can alternatively use .time() on datetime object to extract the time
print(datetime.datetime.strptime('{}.{}'.format(minute,seconds),'%M.%S').time()) #00:04:05
A much cleaner and safer solution is (to consider hour as well). Convert everything into seconds and then convert back to hours, minutes, seconds
def convert(seconds):
min, sec = divmod(seconds, 60)
hour, min = divmod(min, 60)
return "%d:%02d:%02d" % (hour, min, sec)
time='59.65'
split_time = time.split(".")
minute =int(split_time[0])
seconds = int(split_time[1])
new_seconds = minute*60 +65
datetime.datetime.strptime(convert(new_seconds),'%H:%M:%S').time()
I am exporting a list of timedeltas to csv and the days really messes up the format. I tried this:
while time_list[count] > datetime.timedelta(days = 1):
time_list[count] = (time_list[count] - datetime.timedelta(days = 1)) + datetime.timedelta(hours = 24)
But it's instantly converted back into days and creates an infinite loop.
By default the str() conversion of a timedelta will always include the days portion. Internally, the value is always normalised as a number of days, seconds and microseconds, there is no point in trying to 'convert' days to hours because no separate hour component is tracked.
If you want to format a timedelta() object differently, you can easily do so manually:
def format_timedelta(td):
minutes, seconds = divmod(td.seconds + td.days * 86400, 60)
hours, minutes = divmod(minutes, 60)
return '{:d}:{:02d}:{:02d}'.format(hours, minutes, seconds)
This ignores any microseconds portion, but that is trivially added:
return '{:d}:{:02d}:{:02d}.{:06d}'.format(hours, minutes, seconds, td.microseconds)
Demo:
>>> format_timedelta(timedelta(days=2, hours=10, minutes=20, seconds=3))
'58:20:03'
>>> format_timedelta(timedelta(hours=10, minutes=20, seconds=3))
'10:20:03'
If you are ignoring the days in the count, you can convert the timedelta directly.
def timedelta_to_time(initial_time: timedelta) -> time:
hour = initial_time.seconds//3600
minute = (initial_time.seconds//60) % 60
second = initial_time.seconds - (hour*3600 + minute*60)
return str(datetime.strptime(
f"{hour}:{minute}:{second}", "%H:%M:%S"
).time())
Example:
timedelta_to_time(timedelta(days=2, hours=10, minutes=20, seconds=3))
>> '10:20:03'
timedelta_to_time(timedelta(hours=10, minutes=20, seconds=3))
>> '10:20:03'
How can I parse the time 004:32:55 into a datetime object? This:
datetime.strptime("004:32:55", "%H:%M:%S")
doesn't work becaush %H expects two digits. Any way to add the third digit?
Three options :
s = "004:32:55"
from datetime import datetime
datetime.strptime(s[1:], "%H:%M:%S") # from second 0 to the end
datetime.strptime(s, "0%H:%M:%S") # add 0 in formatting
from dateutil import parser # use dateutil
parser.parse(s)
There are 24 hours in a day so you can divide and get the modulus to figure out how many days and hours are in the time, then subtract the days, this needs some tweaking will get you started.
s = "04:32:55"
s = s.split(":",1)
hours, days = divmod(int(s[0]),24)
new_time = "{}:{}".format(hours,s[1])
past = datetime.now() - timedelta(days=days)
final = "{} {}".format(past.date().isoformat(),new_time)
print datetime.strptime(final,"%Y-%m-%d %H:%M:%S")
I chose a more pragmatic approach in the end and converted the time stamp to seconds:
hours = (0 if time_string.split(":")[0] == "000" else int(time_string.split(":")[0].lstrip("0")) * 3600)
mins = (0 if time_string.split(":")[1] == "00" else int(time_string.split(":")[1].lstrip("0")) * 60)
secs = (0 if time_string.split(":")[2] == "00" else int(time_string.split(":")[2].lstrip("0")))
return hours + mins + secs
Converting back to hours, minutes, and seconds is easy with datetime.timedelta(seconds=123).
EDIT:
A better solution (thanks to Ben):
hours = int(time_string.split(":")[0]) * 3600
mins = int(time_string.split(":")[1]) * 60
secs = int(time_string.split(":")[2])
return hours + mins + secs
I need to get time in format: hour:minutes:seconds. But if I use:
time.strftime('%H:%M:%S', time.gmtime(my_time))) #my_time is float
hour have a 24-hour clock (00 to 23). And when I have for example 25 hour and 2 minutes, it writes 1:02:00, but I need 25:02:00. How can I solve it? Thank you.
Don't use time.strftime() to format elapsed time. You can only format a time of day value with that; the two types of values are related but not the same thing.
You'll need to use custom formatting instead.
If my_time is elapsed time in seconds, you can use the following function to format it to a hours:minutes:seconds format:
def format_elapsed_time(seconds):
seconds = int(seconds + 0.5) # round to nearest second
minutes, seconds = divmod(seconds, 60)
hours, minutes = divmod(minutes, 60)
return '{:02d}:{:02d}:{:02d}'.format(hours, minutes, seconds)
Demo:
>>> def format_elapsed_time(seconds):
... seconds = int(seconds + 0.5) # round to nearest second
... minutes, seconds = divmod(seconds, 60)
... hours, minutes = divmod(minutes, 60)
... return '{:02d}:{:02d}:{:02d}'.format(hours, minutes, seconds)
...
>>> format_elapsed_time(90381.33)
'25:06:21'
I have a timedelta object which is 3457 hours
timedelta(hours=3457)
I want to represent it in "HH:MM" format, which is "3457:00"
I do:
from datetime import datetime
hours = timedelta(hours=3457)
hours_string = time.strftime("%H:%M", time.gmtime(hours.seconds))
print hours_string
"01:00"
How can I get "3457:00"?
Please note that 3457:00 is a nonsensical format. The "hour-colon-minutes" format is used in dates and times, and the hour then can't reasonably be any higher than 23. A more reasonable format is: 3457h 0m.
You can get it like this:
from datetime import timedelta
delta = timedelta(hours=3457)
minutes, seconds = divmod(delta.seconds, 60)
hours, minutes = divmod(minutes, 60)
hours += delta.days * 24
print '%sh %sm' % (hours, minutes)
Of course, an easier way is this:
from datetime import timedelta
delta = timedelta(hours=3457)
print delta
But that will give you "144 days, 1:00:00", which is a sane format, but not what you want.
As the timedelta documentation notes, only days, seconds and microseconds are stored internally -- which means you'll have to manually convert them to the units you want (hours and minutes). Here's one way to do that:
from datetime import timedelta
d = timedelta(hours=3457, minutes=42)
wholehours, seconds = divmod(d.seconds, 60*60)
wholeminutes = seconds//60
deltahours = d.days*24 + wholehours
print('{:d}:{:02d}'.format(deltahours, wholeminutes))
# 3457:42
Here's a simpler alternative that produces the same result:
def deltatime_hours_mins(dt, sep=':'):
secs = int(dt.total_seconds())
return '{:d}{}{:02d}'.format(secs//3600, sep, secs//60 % 60)
print(deltatime_hours_mins(d))