Subtracting times taken from a .csv in python - python

elif row[inc3].startswith('LIGHT ON'):
onstr = row[inc3 + 1]
onlst.append(onstr)
elif row[inc4].startswith('LIGHT OFF'):
offstr = row[inc4 + 1]
offlst.append(offstr)
for idx, val in enumerate(onlst):
tdifflst.append(float(offlst[idx]) - float(onlst[idx]))
Here I pulled out the code from a script that extracts data from an EXCEL spreadsheet and analyzes it. The two types of values are the time a light turned on and the time a light turned off. For instance light on at 0500 and light off at 2300.
I want to subtract the on time from the off time but I obviously can't treat these as true floats because of the 60 minutes to an hour thing. How do I treat these "floats" like the times they are?

You could do something like this:
>>> from datetime import datetime
>>> light_on = datetime.strptime('0500', '%H%M')
>>> light_off = datetime.strptime('2300', '%H%M')
>>> print light_off - light_on
18:00:00
light_on and light_off are datetime objects and the difference is a timedelta object.

I think that you are at least implying that the time will always be reported in the form hhmm
therefore it is trivial to modify your code
elif row[inc3].startswith('LIGHT ON'):
raw_time = row[inc3 + 1]
hour = raw_time[0:2]
minute = raw_time[2:]
minute_hour_fraction = int(minute)/60.
str_time = ''.join([hour,str(minute_hour_fraction)[1:]])
float_time = float(str_time)
onlst.append(float_time)
elif row[inc4].startswith('LIGHT OFF'):
same as above

Another way:
import datetime
hh, mm = int(offstr[0:2]), int(offstr[2:4])
# a dummy date 101/1/1
toff = datetime.datetime(101, 1, 1, hh, mm)
hh, mm = int(onstr[0:2]), int(onstr[2:4])
tdiff = toff - datetime.timedelta(hours=hh, minutes=mm)
tdiff.hour
tdiff.minute
Also you can add the whole date (year, month, day) to the datetime objects, so you can get the result for difference greater than 24 hours.

Related

scaling current time to a range in python

I want to scale the current time in a range. Like my start time is 08:00 hours and end time is 19:00 hours which is a 11 hr period. scaled value of my start time should be 0 and scaled value of my end time should be 11. Times like 10:00 and 10:30 should be scaled as 1 and 1.5 respectively.My code
from datetime import datetime
now = datetime.now()
current_time = now.strftime("%H:%M")
start_time = '08:00'
end_time = '19:00'
The above code is reading the variable as strings and I'm not able to perform calculations on them. Can some one help me achieving the scaling.
Thanks
Change now.strftime("%H:%M") to now.strftime("%H%M")
This way you can convert it to an integer, so you have 1000 instead of 10:00 and you can use addition and subtraction
You can extract hours and minutes from your time using datetime.hour and datetime.minute.
To get the scaled value you want, for the range you specified (08:00 to 19:00), you can have :
from datetime import datetime
now = datetime.now()
if(8 <= now.hour <= 19):
scaled_time = now.hour - 8
scaled_time += now.minute / 60
Hope it's help.
Edit: you can change 8 and 19 to variables that contain your start and end time, so you can easily modify them
You can divide timedelta objects obtained from subtracting two datetime objects.
>>> from datetime import datetime
>>> start = datetime(2019, 12, day=19, hour=8, minute=0)
>>> end = datetime(2019, 12, day=19, hour=19, minute=0)
>>> now = datetime.now()
>>> print((now - start) / (end - start))
0.7824158481565656
8 to 19 is exactly 11 hours, so you don't need to scale it just use current time minus to 8 o'clock. so problem is down to change string to hours in decimal.
from datetime import datetime
now = datetime.now()
current_time = now.strftime("%H:%M")
start_time = '08:00'
end_time = '19:00'
def conv(s):
l = s.split(':')
h = int(l[0])
m = int(l[1])
return h+m/60
st = conv(start_time)
# et = conv(end_time)
n = conv(current_time)
scaled = n-st
print(scaled)

Calculating time in Python output format

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]]))

calculate difference between two time in hour

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.

Working with time values greater than 24 hours

How does one work with time periods greater than 24 hours in python? I looked at the datetime.time object but this seems to be for handling the time of a day, not time in general.
datetime.time has the requirement of 0 <= hour < 24 which makes it useless if you want to record a time of more than 24 hours unless I am missing something?
Say for example I wanted to calculate the total time worked by someone. I know the time they've taken to complete tasks individually. What class should I be using to safely calculate that total time.
My input data would look something like this:
# The times in HH:MM:SS
times = ["16:35:21", "8:23:14"]
total_time = ? # 24:58:35
Unfortunately there is not a builtin way to construct timedeltas from strings (like strptime() for datetime objects) so we have to build a parser:
>>> from datetime import timedelta
>>> import re
>>> def interval(s):
"Converts a string to a timedelta"
d = re.match(r'((?P<days>\d+) days, )?(?P<hours>\d+):'
r'(?P<minutes>\d+):(?P<seconds>\d+)', str(s)).groupdict(0)
return timedelta(**dict(((key, int(value)) for key, value in d.items())))
>>> times = ["16:35:21", "8:23:14"]
>>> print sum([interval(time) for time in times])
1 day, 0:58:35
EDIT: Old wrong answer (where I misread the question):
If you substract datetimes you get a timedelta object:
>>> import datetime as dt
>>> times = ["16:35:21", "8:23:14"]
>>> fmt = '%H:%M:%S'
>>> start = dt.datetime.strptime(times[1], fmt )
>>> end = dt.datetime.strptime(times[0], fmt)
>>> diff = (end - start)
>>> diff.total_seconds()
29527.0
>>> (diff.days, diff.seconds, diff.microseconds)
(0, 29527, 0)
>>> print diff
8:12:07
As I understand, you want a sum of all times and not difference. So you can convert your time to timedelta and then sum it:
>>> from datetime import timedelta
# get hours, minutes and seconds
>>> tm1 = [map(int, x.split(':')) for x in times]
# convert to timedelta
>>> tm2 = [timedelta(hours=x[0], minutes=x[1], seconds=x[2]) for x in tm1]
# sum
>>> print sum(tm2, timedelta())
1 day, 0:58:35

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