how to display calculated timedelta as time in python - python

I'm calculating time stored in timewarrior via timew-report python library.
I'm adding up the time, which I'm able to do. And I'm trying get the total to display in just a number of hours:minutes:seconds, without days.
My script....
#!/usr/bin/python
import sys
import datetime
from datetime import timedelta
from timewreport.parser import TimeWarriorParser #https://github.com/lauft/timew-report
parser = TimeWarriorParser(sys.stdin)
total = datetime.datetime(1, 1, 1, 0, 0)
for interval in parser.get_intervals():
duration = interval.get_duration()
print(duration)
total = total + duration
print(total)
...works properly, returning:
0:01:09
0:06:03
7:00:00
0:12:52
20:00:00
0001-01-02 03:20:04
...but instead of showing 0001-01-02 03:20:04 I'd like it to say 27:20:04.
How do I get it to be formatted like that?
Am I taking the wrong approach by initializing total like datetime.datetime(1, 1, 1, 0, 0)?

On the assumption that interval.get_duration is returning a datetime.timedelta object each time, you can just add these to an existing datetime.timedelta object, and then do the arithmetic to convert to HH:MM:SS format at the end. (You will need to do your own arithmetic because the default string representation for timedelta will use days and HH:MM:SS if the value exceeds 24 hours, which you don't want.)
For example:
import datetime
total = datetime.timedelta(0)
for interval in parser.get_intervals():
duration = interval.get_duration()
total += duration
total_secs = int(total.total_seconds())
secs = total_secs % 60
mins = (total_secs // 60) % 60
hours = (total_secs // 3600)
print("{hours}:{mins:02}:{secs:02}".format(hours=hours, mins=mins, secs=secs))

For anyone interested in this timewarrior report, here's my final working code. Put this in scriptname located in timewarrior extensions directory then invoke like timew scriptname tagname to see a timereport showing annotations and total uninvoiced time for a given tag (it can also be used without a tag to display all time entries).
#!/usr/bin/python
import sys
import datetime
from datetime import timedelta
from timewreport.parser import TimeWarriorParser #https://github.com/lauft/timew-report
parser = TimeWarriorParser(sys.stdin)
total = datetime.timedelta()
tags = ''
for interval in parser.get_intervals():
tags = interval.get_tags()
# this report shows only un-invoiced time, so we ignore "invoiced" time entries
if 'invoiced' not in tags:
# hide 'client' and 'work' tags since they clutter this report
if 'clients' in tags:
tags.remove('clients')
if 'work' in tags:
tags.remove('work')
date = interval.get_start()
duration = interval.get_duration()
ant = interval.get_annotation()
sep = ', '
taglist = sep.join(tags)
output = str(date.date()) + ' - ' + str(duration) + ' - ' + taglist
if ant:
output += ' ||| ' + str(ant)
print(output)
total = total + duration
print('----------------')
# We calculate the time out like this manually because we don't want numbers of hours greater than 24 to be presented as days
total_secs = int(total.total_seconds())
secs = total_secs % 60
mins = (total_secs // 60) % 60
hours = (total_secs // 3600)
# for new versions of python 3.6 and up the following could work
# print(f"{hours}:{mins:02}:{secs:02}")
# but for older python this works...
print("total = {hours}:{mins:02}:{secs:02}".format(hours=hours, mins=mins, secs=secs))

Pass total seconds to timedelta function from datetime like below:
total = your_total.timestamp()
total_time = datetime.timedelta(seconds=total)
str(total_time)

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

How to add 24 to the %H part of the enter variable, then store it as the same variable? [duplicate]

This question already has answers here:
What is the standard way to add N seconds to datetime.time in Python?
(11 answers)
Closed 6 years ago.
from datetime import datetime
run = 1
list1 = []
for i in range(2):
while run > 0:
print("")
reg_num = input('reg num')
enter = input('time enter in the form "HH:MM:SS" in 24 hours format')
ext = input('time exit in the form "HH:MM:SS" in 24 hours format')
total_time = '%H:%M:%S'
if int(enter[0:1]) > int(ext[0:1]):
total_time = enter[0:1] + 24
t_diff = datetime.strptime(ext, total_time)- datetime.strptime(enter, total_time)
t_diff1 = str(t_diff)
print(t_diff)
t_diff2 = int(t_diff1[4:5])
t_diff3 = int(t_diff1[7:8])
time = ((t_diff2/60)+(t_diff3/60/60))
speed = run/time
print("{:.2f}".format(speed), "mph")
if speed > 70:
list1.append(reg_num)
break
for item in list1:
print(item, "is over speeding")
This is code to work out the speed of something as it enters and exits a checkpoint that is set a mile apart.
What I am trying to do here is to find the difference in time when the time entered hour is greater than time exited hour. i.e. enter = 23:59:00 and ext = 00:00:00. I know that I have to add 24 to the %H but I don’t know how to do it and when I try to run it in the shell the message is:
total_time = enter[0:1] + 24
TypeError: Can't convert 'int' object to str implicitly
The problem I think comes from this part of the code:
if int(enter[0:1]) > int(ext[0:1]):
total_time = enter[0:1] + 24
Can you help me find out a way to add 24 to the hour section and then store it into the same variable.
In the end you want the speed. This approach calculates it.
The best is to use datetime.datetime objects for all time calculations.
Therefore, convert the strings first.
You can use datetime.timedelta(hours=24) to create a timedelta object.
You can add this to a datetime.datetime object:
from __future__ import division # if you still work with Python 2
import datetime
run = 1
enter = '23:59:20'
ext = '00:00:00'
time_format = '%H:%M:%S'
enter_time = datetime.datetime.strptime(enter, time_format)
ext_time = datetime.datetime.strptime(ext, time_format)
if enter_time > ext_time:
ext_time += datetime.timedelta(hours=24)
t_diff = ext_time - enter_time
elapsed_time = t_diff.total_seconds() / 3600
speed = run / elapsed_time
print(speed)
Output:
90.0

Convert Date (YYYY MM DD HH:MM:SS) to Decimal Day (YYYY MM DD.ddddd)

I have a script built that takes a date and time of an observation at a telescope and converts it to just a date with a decimal day. This script also takes in half the exposure time and adds it to the decimal day so that I can get the most accurate astrometric calculation. This is then submitted to The Minor Planet Center that only accepts the time of observation in Year Month Day.XXXXX What is the most accurate way to 5 decimal points to do this? This is the current way I use, yes it is very messy but it does get me the decimal day. Occasionally it is off by one second in the time conversion.
expmpc = float.("10")
utcstartmpc = "05:45:19.03"
datempc = "2015-02-14"
ddexposure = expmpc/(60.0*60.0*24.0)
ddexposure = round(ddexposure, 5)
seconds = int(utcstartmpc[6:8]) / 60.0
minutes = (int(utcstartmpc[3:5]) + seconds) / 60
hours = (int(utcstartmpc[:2]) + minutes) / 24
hours = round(hours, 5)
expadd = str(hours + ddexposure)
datempc = datempc.replace("-", " ")
utcmpc = "C%s%s" % (datempc, expadd[1:])
utcmpc = utcmpc.ljust(17, "0")
As you can see this is very messy and it involves rounding a lot of data and I believe I am losing accuracy with the rounding. The finished outcome of the code leaves a time such as this:
C2015 02 14.23986
Is there a module that works better?
Thank you for the help.
Here's something that uses more of the built-in time/date modules (and I think it does what you want):
import time
import datetime
def my_date_converter(date_in):
parse_str, _ = date_in.split(".")
date_str, time_str = parse_str.split(" ")
parsed_time = time.strptime(time_str, "%H:%M:%S")
total_seconds = datetime.timedelta(hours=parsed_time.tm_hour,minutes=parsed_time.tm_min,seconds=parsed_time.tm_sec).total_seconds()
seconds_in_day = 86400.0
decimal_seconds = total_seconds / seconds_in_day
utcmpc = "C%s%s" % (date_str.replace("-", " "), str(round(decimal_seconds, 5))[1:])
utcmpc = utcmpc.ljust(17, "0")
return utcmpc
def main():
to_convert = "2015-02-14 05:45:19.03"
converted = my_date_converter(to_convert)
print "%s => %s" % (to_convert, converted)
if __name__ == '__main__':
main()
Example output: 2015-02-14 05:45:19.03 => C2015 02 14.23980
Have you tried the excellent astropy library? They have a package to deal with time and conversions: astropy.time
You could separate your problem into 2 tasks:
get datetime object that represent UTC time from the input expmpc, utcstartmpc, datempc
convert datetime object to string in the Year Month Day.XXXXX format.
Get datetime object from the input expmpc, utcstartmpc, datempc
from datetime import datetime, timedelta
expmpc = "10"
utcstartmpc = "05:45:19.03"
datempc = "2015-02-14"
dt = datetime.strptime(datempc + " " + utcstartmpc, "%Y-%m-%d %H:%M:%S.%f")
dt += timedelta(seconds=int(expmpc))
Convert datetime object to string in the Year Month Day.XXXXX format
from datetime import datetime, time, timedelta
s = dt.strftime("C%Y %m %d.")
day_fraction = dt - datetime.combine(dt, time.min)
s += ("%.0f" % (100000*day_fraction / timedelta(days=1)))
# -> C2015 02 14.23992
Note: the result is slightly different from the one in your question (92 vs. 86 at the end).
In Python 2, you need to replace td / timedelta(1) with td.total_seconds() / 86400.
Here's another way:
>>> from __future__ import division
>>> assert day_fraction.days == 0
>>> '%.0f' % ((day_fraction.seconds*10**6 + day_fraction.microseconds) / 864000)
'23992'
All arithmetic operations before the true division are performed with infinite precision.
Yet another way also produces 92:
>>> from datetime import timezone
>>> ('%.5f' % ((dt.replace(tzinfo=timezone.utc).timestamp() % 86400) / 86400))[2:]
'23992'

Subtract or add time to web-scraped times

I'm working on a one-off script for myself to get sunset times for Friday and Saturday, in order to determine when Shabbat and Havdalah start. Now, I was able to scrape the times from timeanddate.com -- using BeautifulSoup -- and store them in a list. Unfortunately, I'm stuck with those times; what I would like to do is be able to subtract or add time to them. As Shabbat candle-lighting time is 18 minutes before sunset, I'd like to be able to take the given sunset time for Friday and subtract 18 minutes from it. Here is the code I have thus far:
import datetime
import requests
from BeautifulSoup import BeautifulSoup
# declare all the things here...
day = datetime.date.today().day
month = datetime.date.today().month
year = datetime.date.today().year
soup = BeautifulSoup(requests.get('http://www.timeanddate.com/worldclock/astronomy.html?n=43').text)
# worry not.
times = []
for row in soup('table',{'class':'spad'})[0].tbody('tr'):
tds = row('td')
times.append(tds[1].string)
#end for
shabbat_sunset = times[0]
havdalah_time = times[1]
So far, I'm stuck. The objects in times[] are shown to be BeautifulSoup NavigatableStrings, which I can't modify into ints (for obvious reasons). Any help would be appreciated, and thank you sososososo much.
EDIT
So, I used the suggestion of using mktime and making BeautifulSoup's string into a regular string. Now I'm getting an OverflowError: mktime out of range when I call mktime on shabbat...
for row in soup('table',{'class':'spad'})[0].tbody('tr'):
tds = row('td')
sunsetStr = "%s" % tds[2].text
sunsetTime = strptime(sunsetStr,"%H:%M")
shabbat = mktime(sunsetTime)
candlelighting = mktime(sunsetTime) - 18 * 60
havdalah = mktime(sunsetTime) + delta * 60
You should use the datetime.timedelta() function.
In example:
time_you_want = datetime.datetime.now() + datetime.timedelta(minutes = 18)
Also see here:
Python Create unix timestamp five minutes in the future
Shalom Shabbat
The approach I'd take is to parse the complete time into a normal representation - in Python world, this representation is the number of seconds since the Unix epoch, 1 Jan 1970 midnight. To do this, you also need to look at column 0. (Incidentally, tds[1] is the sunrise time, not what I think you want.)
See below:
#!/usr/bin/env python
import requests
from BeautifulSoup import BeautifulSoup
from time import mktime, strptime, asctime, localtime
soup = BeautifulSoup(requests.get('http://www.timeanddate.com/worldclock/astronomy.html?n=43').text)
# worry not.
(shabbat, havdalah) = (None, None)
for row in soup('table',{'class':'spad'})[0].tbody('tr'):
tds = row('td')
sunsetStr = "%s %s" % (tds[0].text, tds[2].text)
sunsetTime = strptime(sunsetStr, "%b %d, %Y %I:%M %p")
if sunsetTime.tm_wday == 4: # Friday
shabbat = mktime(sunsetTime) - 18 * 60
elif sunsetTime.tm_wday == 5: # Saturday
havdalah = mktime(sunsetTime)
print "Shabbat - 18 Minutes: %s" % asctime(localtime(shabbat))
print "Havdalah %s" % asctime(localtime(havdalah))
Second, help to help yourself: The 'tds' list is a list of BeautifulSoup.Tag. To get documentation on this object, open a Python terminal, type
import BeautifulSoup
help(BeautifulSoup.Tag)

Categories

Resources