Python subtracting with time format - python

I have a df that looks like this:
Time_Start CODE time
0 2018-01-31 16:45:04.263 B76 2018-01-31 16:48:06
1 2018-01-31 16:10:26.000 974 2018-01-31 16:50:06
I am subtracting time from Time_Start. For the second one I get 39:49 which is the expected output but for the first one I get a number like 2.737000 (not what I want).
Time_Start is datetime64[ns] and time is object. This is how I am doing the conversion and subtracting:
waiting['time'] = pd.to_datetime(waiting['time'])
waiting['Duration'] = waiting['time'] - waiting['Time_Start']
waiting['Duration'] = waiting['Duration'].apply(lambda x: str(x)[-8:])
I am rather new to python so can someone tell me what am I doing wrong and why I am getting the 2 different outputs?
I am using python 2.x.
Full code:
query that returns the dataframe
.......
end_time = np_server_date.ix[0]['data'] """current time"""
end_time = end_time.strftime('%Y-%m-%d %H:%M:%S')
waiting['time'] = end_time """it's now the current time"""
waiting['time'] = pd.to_datetime(waiting['time'])
waiting['Duration'] = waiting['time'] - waiting['Time_Start']
waiting['Duration'] = waiting['Duration'].apply(lambda x: str(x)[-8:])

Alright so I think I have enough info to answer your question now.
Right of the bat, you'll need to create a connection with pyodbc.
Then, you'll want loop through your result set and then create datetime objects either through the constructor or using strptime() out of your two times.
Then, you'll subtract the datetime objects to get a difference between the times as a timedelta object.
Then, depending on what you need to do with that information, you can convert it to your format by doing some math.
import datetime
import pyodbc
#create connection
with pyodbc.connect(db, password) as cnxn:
#create cursor
cursor = cnxn.cursor()
cursor.execute('YOUR QUERY')
#loop through results
while true:
#use fetchone generator to optimize memory usage
row = cursor.fetchone()
#create datetime objects
start_time = datetime.strptime(row[0], '%Y-%m-%d %H:%M:%S.%f')
end_time = datetime.strptime(row[2], '%Y-%m-%d %H:%M:%S')
#the following creates a timedelta object
time_diff = end_time - start_time
#a couple ways to deal with the result
#printing time_diff yields Days:Seconds:Microseconds
#the following yields the difference in seconds
#difference = time_diff.totalseconds()
#alternatively, you can get days, seconds, microseconds.
#either way you have to do some math to convert to hours and
#minutes if desired
#difference = time_diff.days + ":" + time_diff.seconds + ":"
# + time_diff.microseconds
#TODO your division to format the seconds how you'd like
#using divmod, you can get hours, min, second
m, s = divmod(time_diff.seconds, 60)
h, m = divmod(m, 60)
print "%d:%d:%02d:%02d" % (time_diff.days, h, m, s)
#TODO whatever you need to do with this information
if not row:
break

Related

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}")

Python subsetting data by hour and minute, ignoring date

I have a list of image timestamps in the format '20121002_1639' ('%Y%m%d_%H%M')
I want to create a function that takes in a list of these timestamps and excludes images taken between
1500(3:00pm) and 1700 (5:00pm). However When I try to just parse the %H%M portion of the string, it automatically assigns those datetimes to the date 19000101_1500 and 19000101_1700. So I need to create objects which contain just hours and minutes but are not associated with a date.
The pseudo code would be something like this:
import datetime as dt
# example datetime string
datestrings = ['20121002_1639', '20111101_1229', '20160424_1502', '20170328_1100']
Start_time = dt.datetime.strptime('1500', '%H%M')
End_time = dt.datetime.strptime('1700', '%H%M')
good_times = []
for time in datestrings:
if dt.datetime.strptime(time[9:13], '%H%M') is between(Start_time, End_time):
continue
else:
good_times.append(time)
You may use only the time part from the datetime object, for that use the .time() method. So you don't need to parse only a part of the given string, parse all and then take it's time part too
datestrings = ['20121002_1639', '20111101_1229', '20160424_1502', '20170328_1100']
Start_time = dt.datetime.strptime('1500', '%H%M').time()
End_time = dt.datetime.strptime('1700', '%H%M').time()
good_times = []
for time in datestrings:
if not (Start_time <= dt.datetime.strptime(time, '%Y%m%d_%H%M').time() < End_time):
good_times.append(time)
print(good_times) # ['20111101_1229', '20170328_1100']
In fact you coud even do it with basic int comparisons
Start_time = 1500
End_time = 1700
for time in datestrings:
if not (Start_time <= int(time.split("_")[-1]) < End_time):
good_times.append(time)

Python comparing to different time values to get time delta in minutes

I am trying to get get the time delta i minutes from two different time values.
time1 = 2020-11-28T10:31:12Z
time2 = 2020-11-28T09:10:23.203+0000
Then i will make i condition: if time difference is bigger then x minutes, run code...
Anyone have a solution for that.
I have tried using datetime.datetime.strptime() but cant get them on same format.
Thanks
Using date parser to let it figure out the date format
Code
from dateutil.parser import parse
def time_difference(time1, time2):
# Parse strings into datetime objects
dt1 = parse(time1)
dt2 = parse(time2)
# Get timedelta object
c = dt1 - dt2
# Difference in minutes
return (c.total_seconds()/60)
Test
time1 = "2020-11-28T10:31:12Z"
time2 = "2020-11-28T09:10:23.203+0000"
print(time_difference(time1, time2))
# Output: 80.81328333333333
well assuming you don't need split seconds you could do something like that:
time1 = '2020-11-28T10:31:12Z'
time2 = '2020-11-28T09:10:23.203+0000'
import time
import datetime
def get_timestamp(time_str):
time_splited = time_str.split('T')
time_str_formatted = ' '.join([time_splited[0],time_splited[1][:8]])
return time.mktime(datetime.datetime.strptime(time_str_formatted,"%Y-%m-%d %H:%M:%S").timetuple())
print(get_timestamp(time1))
print(get_timestamp(time2))
reformatting both times to the same time format.
then your condition would look like:
if abs(get_timestamp(time1) -get_timestamp(time2) ) > x*60:
do_something(....)
The times are not uniform so you will have to make them the same to use strptime. For accuracy I prefer to convert to seconds then you can also at a later stage compare seconds, minutes or hours if you needed to.
import datetime
time1 = '2020-11-28T10:31:12Z'
time2 = '2020-11-28T09:10:23.203+0000'
def minutes_diff():
#Make the times uniform so you can then use strptime
date_time1 = datetime.datetime.strptime(time1[:-1], "%Y-%m-%dT%H:%M:%S")
date_time2 = datetime.datetime.strptime(time2[:-9], "%Y-%m-%dT%H:%M:%S")
#Convert to seconds for accuracy
a_timedelta = date_time1 - datetime.datetime(1900, 1, 1)
b_timedelta = date_time2 - datetime.datetime(1900, 1, 1)
seconds_time_a = a_timedelta.total_seconds()
seconds_time_b = b_timedelta.total_seconds()
#Take one from each other for minutes
time_in_minutes = (seconds_time_a - seconds_time_b) / 60
#Then decide what to do with it
if time_in_minutes < 60: # 1 hour
print('Less than an hours do something')
else:
print('More than an hour do nothing')
minutes_diff()
DARRYL, JOHNNY and MARCIN, thanks for your solutions, problem solved!!
Andy

Python - difference between time

Looking for easiest way to calculate the difference between 2 python times and display the millisecond delta
I have 2 times
startTime = datetime.datetime.now().time()
do some stuff...
endTime= datetime.datetime.now().time()
This works fine and when I log the times out and I get something like this in my logs...
RequestStartTime = 08:56:19.188999
ResponseTime = 08:56:19.905999
When I try to simply subtract them like this
delta = endTime - startTime
I get the following error
unsupported operand type(s) for -: 'time' and 'time'
All I want to do is show the difference in microseconds and I can't figure it out
I want to show is 717000 ms
If you just use the result of now(), and don't convert them to times, you can take the difference & extract the bits you want in the form you want; for example:
startTime = datetime.datetime.now()
endTime= datetime.datetime.now()
delta = endTime - startTime
print str(delta).split(":")[2]
Try this:
from datetime import datetime, date
datetime.combine(date.today(), endTime) - datetime.combine(date.today(), startTime)
Hope this Helps.
To measure the difference manually, you should use time.monotonic() instead.
If you don't care about leap seconds (~1s error once per year and a half) and you need to display the local time:
#!/usr/bin/env python3
from datetime import datetime, timedelta, timezone
start = datetime.now(timezone.utc).astimezone() # current local time
# print("RequestStartTime = %s" % start.time())
end = datetime.now(timezone.utc).astimezone()
diff_milliseconds = (end - start) / timedelta(milliseconds=1)
print("%.0f ms" % diff_milliseconds)
The code works fine around/during DST transitions.
Note: it is different from the code that uses just .now(). If you use .now() (no argument) then you get a naive datetime object that represents local time and in that case if a DST transition happens between start and end times then end - start returns a completely wrong result i.e., the code may be wrong by an hour approximately couple of times per year in some timezones.
the reason why you are getting an error is because class time does not support subtraction. You must turn time into miliseconds (int format) to subtract from one another.
instead of using datetime, use time
import time
def timenow():
return int(round(time.time() * 1000))
startTime = timenow()
time.sleep(1)
endTime = timenow()
delta = endTime - startTime
print delta
The simplest solution would be to convert the datetime objects to timestamps and subtract those. If you use Python 3.3 or later you can simply do something along these lines
startTime = datetime.datetime.now(timezone.utc).timestamp()
...
endTime = datetime.datetime.now(timezone.utc).timestamp()
Then you can just subtract those.
In Python 2 you do not have the timestamp method available. One way around would be to use a timedelta object:
startTime = datetime.datetime.now(timezone.utc)
...
endTime = datetime.datetime.now(timezone.utc)
dt = (endTime - startTime).total_seconds()
A third option is to simply use raw timestamps with time.time() and subtract them to get the time interval in seconds and fraction of seconds.
To be extra safe you could use time.monotonic() as #Sebastian mentions.
This is the best answer for this problem:
https://stackoverflow.com/a/39651061/2686243
from datetime import datetime, date
duration = datetime.combine(date.min, end) - datetime.combine(date.min, beginning)

Python: format datetime efficiently whilst leaving it as a datetime object

I want to be able to format a datetime object, while leaving it as an object. I have worked a way to do it, but it doesn't seem very efficient.
My specific aim is to limit the extra digits on the seconds to 2. This is how I am currently doing it:
now = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')
now_frmt = datetime.datetime.strptime(now, '%Y-%m-%d %H:%M:%S')
Cheers,
JJ
You could do this to subtract off the microseconds:
now = datetime.datetime.now()
now_frmt = now - datetime.timedelta(microseconds=now.microsecond)
To round to the nearest second you can do the following:
now = datetime.datetime.now()
delta = (0 if now.microsecond < 500000 else 1000000) - now.microsecond
now_frmt = now + datetime.timedelta(microseconds=delta)

Categories

Resources