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
Related
Example:
9:43 - 17:27 - how many hours and minutes elapsed between those times ?
Here is one approach to get the number of total minutes:
from datetime import datetime
s = '9:30 - 14:00 ; 14:30 - 16:30'
sum(((b-a).total_seconds()/60 for x in s.split(' ; ')
for a,b in [list(map(lambda t: datetime.strptime(t, '%H:%M'), x.split(' - ')))]))
Output: 390.0
If you know that the time periods will never span midnight, then you could simply split the time strings with time.split(":") and do the math yourself with the hours and minutes.
However, the correct solution would be to import the datetime module and calculate the timedelta.
This example could be condensed. I intentionally made it verbose without knowing exactly how you're getting your inputs:
from datetime import datetime
times = [
"9:30",
"14:00",
"14:30",
"16:30"
]
#Just using today's date to fill in the values with assumption all times are on the same day.
year = 2022
month = 6
day = 9
date_times = []
for time in times:
split_time = time.split(":")
hour = split_time[0]
minutes = split_time[1]
timestamp = datetime.datetime.today(year=year, month=month, day=day, hour=hour, min=minutes)
date_times.append(timestamp)
total_seconds = 0
for i in range(1, len(date_times), 2):
delta = date_times[i] - date_times[i-1] # The timedelta object returned will have days, seconds, milliseconds
total_seconds += delta.days * 86400 + delta.seconds
hours = total_seconds // 3600 # Integer division
minutes = round((total_seconds % 3600) / 60) # Change depending on if you want to round to nearest, or always up or down.
My expertise lack when it comes to understanding this time format. I am guessing the ,XXX is XXX/1000 of a second?
Nevertheless I am trying to add a text files that contains time stamp like these and sum up the total.
Below is an example,
00:03:33,950
00:03:34,590
This is what I have so far but I'm not sure how to add up the last part
Hours = s.split(":")[0]
Minutes = s.split(":")[1]
Seconds = (s.split(":")[2]).split(",")[0]
Total_seconds = (Hours * 3600) + (Minutes * 60) + (Seconds)
Total_Time = str(datetime.timedelta(seconds=Total_seconds))
Reed this documentation about time.strftime() format
For example
from time import gmtime, strftime
strftime("%a, %d %b %Y %H:%M:%S +0000", gmtime())
--'Thu, 28 Jun 2001 14:17:15 +0000'--
Actually, you're halfway there.
All you have to do is to to convert your strs into int and pass them as parameters to the appropriate timedelta keywords.
from datetime import timedelta
Hours = int(s.split(":")[0])
Minutes = int(s.split(":")[1])
Seconds = int((s.split(":")[2]).split(",")[0])
Milliseconds = int((s.split(":")[2]).split(",")[1])
duration = timedelta(hours=Hours, minutes=Minutes, seconds=Seconds, milliseconds=Milliseconds)
After adding all the durations you need, str() the final timedelta object.
>>> durations_1 = timedelta(hours=2,milliseconds=750)
>>> durations_2 = timedelta(milliseconds=251)
>>> durations_sum = durations_1 + durations_2
>>> str(durations_sum)
'2:00:01.001000'
>>> str(durations_sum).replace('.',',')
'2:00:01,001000'
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 want to calculate difference between two time in hours using django in sql db the time are stored in timefield.
I tried this:
def DesigInfo(request): # attendance summary
emplist = models.staff.objects.values('empId', 'name')
fDate = request.POST.get('fromDate')
tDate = request.POST.get('toDate')
if request.GET.get('empId_id'):
sel = attendance.objects.filter(empId_id=request.GET.get('empId_id'),)
for i in sel:
# print i.
# print i.outTime
# print i.inTime.hour,i.inTime.minute,i.inTime.second - i.outTime.hour,i.outTime.minute,i.outTime.second
ss = i.inTime.hour
ss1 = 12 - ss
mm = i.outTime.hour
mm1 = (12 + mm) - 12
print ss1 + mm1
Since i.inTime and i.outTime are time objects you cannot simply subtract them. A good approach is to convert them to datetime adding the date part (use today() but it is irrelevant to the difference), then subtract obtaining a timedelta object.
delta = datetime.combine(date.today(), i.outTime) - datetime.combine(date.today(), i.inTime)
(Look here: subtract two times in python)
Then if you want to express delta in hours:
delta_hours = delta.days * 24 + delta.seconds / 3600.0
A timedelta object has 3 properties representing 3 different resolutions for time differences (days, seconds and microseconds). In the last expression I avoided to add the microseconds but I suppose it is not relevant in your case. If it is also add delta.microseconds / 3600000000.0
Note that simply dividing seconds by 3600 would have returned only the integer part of hours avoiding fractions. It depends on your business rules how to round it up (round, floor, ceil or leave the fractional part as I did)
Using datetime objects: https://docs.python.org/2/library/datetime.html
A good stack overflow post on the topic How to get current time in Python
from datetime import datetime
now = datetime.now()
# wait some time
then = ... some time
# diff is a datetime.timedelta instance
diff = then - now
diff_hours = diff.seconds / 3600
You might want to play with this codes:
from datetime import datetime
#set the date and time format
date_format = "%m-%d-%Y %H:%M:%S"
#convert string to actual date and time
time1 = datetime.strptime('8-01-2008 00:00:00', date_format)
time2 = datetime.strptime('8-02-2008 01:30:00', date_format)
#find the difference between two dates
diff = time2 - time1
''' days and overall hours between two dates '''
print ('Days & Overall hours from the above two dates')
#print days
days = diff.days
print (str(days) + ' day(s)')
#print overall hours
days_to_hours = days * 24
diff_btw_two_times = (diff.seconds) / 3600
overall_hours = days_to_hours + diff_btw_two_times
print (str(overall_hours) + ' hours');
''' now print only the time difference '''
''' between two times (date is ignored) '''
print ('\nTime difference between two times (date is not considered)')
#like days there is no hours in python
#but it has seconds, finding hours from seconds is easy
#just divide it by 3600
hours = (diff.seconds) / 3600
print (str(hours) + ' Hours')
#same for minutes just divide the seconds by 60
minutes = (diff.seconds) / 60
print (str(minutes) + ' Minutes')
#to print seconds, you know already ;)
print (str(diff.seconds) + ' secs')
The easiest way through I achieve is the comment of Zac given above. I was using relativedelta like this
from dateutil import relativedelta
difference = relativedelta.relativedelta( date1, date2)
no_of_hours = difference.hours
but it did not give me correct result when the days changes. So, I used the approach expressed above:
no_of_hours = (difference.days * 24) + (difference.seconds / 3600)
Please note that you will be getting negative value if date2 is greater than date1. So, you need to swipe the position of date variables in relativedelta.
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'