enter image description here
I need to write a piece of code that calculates the distance between 2 dates, as shown in the screenshot above^
This is what I put:
def dist2dates(date1,date2):
result= date2[0:2]-date1[0:2],"/",date2[3:]-date1[3:]
return result
res2=dist2dates(1116,1129)
print(res2)
This produces an error that says:
TypeError: 'int' object is not subscriptable
I am not too sure what I am doing wrong. Also, I am not too clear on how to put a date such as "08/16" in the argument? Can someone help me define such a function?
This is the best I could come up with:
import re
def dist2dates(date1,date2):
if re.match(r'^\d{2}\/\d{2}$', date1) and re.match(r'^\d{2}\/\d{2}$', date2):
diff1 = abs(((int(date2[0:2])-int(date1[0:2]))))
diff2 = abs((int(date2[3:])-int(date1[3:])))
result= ("%02d/%02d") %(diff1, diff2)
return result
else:
return "Incorrect format"
res2=dist2dates("11/16","11/29")
print(res2)
Output:
00/13
It always returns the absolute value abs(), so you wont get negative numbers. It also checks if the date string is formatted correctly using RegEx.
=================== Before edit =================
Try this:
def dist2dates(date1,date2):
result= ("%02d/%02d") %(int(date2[0:2])-int(date1[0:2]) ,int(date2[3:])-int(date1[3:]))
return result
res2=dist2dates("10/16","11/29")
print(res2)
Output:
01/13
The inputs to the dist2dates function should be strings not integers.
Cast the strings into integers so you can subtract the numbers.
The nature of this problem is sort of strange since now your year has 360 days, but this structure handles both if the first date is larger or smaller, it works by evaluating the difference in days based on 30 day months then converts them to days and uses zfill to print the output.
def dist2dates(a, b):
a = list(map(int, a.split('/')))
b = list(map(int, b.split('/')))
if b[0] < a[0]:
days = 360 - 30*(a[0] - b[0]) - (a[1] - b[1])
else:
days = 30*((b[0]- 1) - a[0]) + (30 - a[1]) + b[1]
print(days)
tup = divmod(days,30)
mm, dd = tup[0], tup[1]
return f'{str(mm).zfill(2)}/{str(dd).zfill(2)}'
print(dist2dates('03/20', '01/10')) # => 09/20
print(dist2dates('01/12', '05/20')) # => 04/08
why not use datetime module to calculate the timedelta & use the strptime/strftime for formatting?
from datetime import datetime, timedelta
def dist2dates(strdate1,strdate2):
'''format mm/dd, assumes month = 30 days always'''
dtfmt = '%m/%d'
date1 = datetime.strptime(strdate1, dtfmt)
date2 = datetime.strptime(strdate2, dtfmt)
delta = date2 - date1
year = date1.year
month, day = divmod(delta.days, 30)
result = datetime.strftime(datetime(year, round(month), round(day)), '%m/%d')
return result
res = dist2dates('01/16','11/29')
print(res)
# 10/13
Related
how to get the difference between _a and _b ? like the difference in hours,minutes and seconds
#client.command()
async def timestamp(ctx, id : int,id2 : int):
a = discord.utils.snowflake_time(id)
b = discord.utils.snowflake_time(id2)
_a = "{:02d} : {:02d} : {:02d}".format(a.hour, a.minute, a.second)
_b = "{:02d} : {:02d} : {:02d}".format(b.hour,b.minute,b.second)
both a and b are datetime.datetime objects, hence we can directly find the timedelta
import datetime
delta = abs(a - b) #always get the positive delta
delta = datetime.timedelta(seconds=int(delta.total_seconds())) #remove microseconds
#remove the above line if you want milliseconds
print(delta) #or str(delta)
This would print, the delta in hh:mm:ss format if the different is less than a day.
Given a timedelta in python such as:
td = datetime.timedelta(minutes=10)
if printed as a string it appears without the leading zero I want:
t_str = string(td)
print(t_str)
# result: "0:10:00"
How can I convert it to a string that retains the format of "00:10:00" (%HH:%MM:%SS)?
"{:0>8}".format(str(td))
# result: "00:10:00"
We can also use time and then format using the strftime method.
import datetime
dt = datetime.time(0, 10, 0)
dt.strftime('%H:%M:%S')
It is a bit tricky, because the behaviour for negative values as well as values longer than a day is more complicated.
def str_td(td):
s = str(td).split(", ", 1)
a = s[-1]
if a[1] == ':':
a = "0" + a
s2 = s[:-1] + [a]
return ", ".join(s2)
print(str_td(datetime.timedelta(minutes=10)))
print(str_td(datetime.timedelta(minutes=3200)))
print(str_td(datetime.timedelta(minutes=-1400)))
print(str_td(datetime.timedelta(seconds=4003.2)))
print(str_td(datetime.timedelta(seconds=86401.1)))
gives
00:10:00
2 days, 05:20:00
-1 day, 00:40:00
01:06:43.200000
1 day, 00:00:01.100000
A completely different way of doing it would be
def str_td(td):
s = str(td).split(", ", 1)
t = datetime.time(td.seconds // 3600,td.seconds // 60 % 60,td.seconds % 60, td.microseconds)
s2 = s[:-1] + [str(t)]
return ", ".join(s2)
print(str_td(datetime.timedelta(minutes=10)))
print(str_td(datetime.timedelta(minutes=3200)))
print(str_td(datetime.timedelta(minutes=-1400)))
print(str_td(datetime.timedelta(seconds=4003.2)))
print(str_td(datetime.timedelta(seconds=86401.1)))
which gives the same result as above.
Which one is more elegant is left as an exercise to the reader.
td = datetime.timedelta(minutes=10)
time = '0'+str(td)
print(time)
The output is
00:10:00
for less than 24 hours work well
print(str(datetime.timedelta(minutes=10)).zfill(8))
"00:10:00"
when you exceed 24 hours, it looks like
print(str(datetime.timedelta(minutes=1445)).zfill(8))
"1 day, 0:05:00"
I need help with the python function of comparing two dates (string) and return True if date1 is ealier than date2. Here is my code but I'm don't know why it returns True for the test case("2013/10/24", "2013/9/24")
# str, str -> boolean
def dateLessThan(date1,date2):
date1 = date1.split('/')
date2 = date2.split('/')
if date1[0] < date2[0]:
return True
elif date1[0] == date2[0] and date1[1] < date2[1]:
return True
elif date1[0] == date2[0] and date1[1] == date2[1] and date1[2] < date2[2]:
return True
else:
return False
Just use the datetime.strptime class method instead of doing your own parsing.
def dateLessThan(date1,date2):
date1 = datetime.datetime.strptime(date1, "%Y/%m/%d")
date2 = datetime.datetime.strptime(date2, "%Y/%m/%d")
return date1 < date2
Consider using datetime objects (assumed your time format is YY/mm/dd)
from datetime import datetime
def dateLessThan(date1,date2):
datetime1 = datetime.strptime(date1, '%Y/%m/%d')
datetime2 = datetime.strptime(date2, '%Y/%m/%d')
return datetime1 < datetime2
your test fails because of lexicographical comparison of strings. "10" < "9".
Without using datetime or time parsing (which is required when there are complex formats, months names...), it's possible to do something simple since there's only numbers involved (and you have years/month/day, so you're close to the ISO date format where you can compare lexicographically).
Just map the values into integers and convert to lists and let the natural/lexicographical order of lists do the rest:
def dateLessThan(date1,date2):
return [int(x) for x in date1.split('/')] < [int(x) for x in date2.split('/')]
What I am trying to do is take two lists of time stamps, find the difference between the corresponding time stamp pairs, and then print the differences as another list. When I print the final list of time differences I get this:
[datetime.timedelta(0, 2700), datetime.timedelta(0, 1800)]
Here is my code for reference:
import time
import datetime
strlist1 = ['12:45:00', '01:30:00']
format = '%H:%M:%S'
i = 0
timelist1 = []
for time in strlist1:
timelist1.append(datetime.datetime.strptime(strlist1[i], format))
i += 1
strlist2 = ['12:00:00', '01:00:00']
k = 0
timelist2 = []
for time in strlist2:
timelist2.append(datetime.datetime.strptime(strlist2[k], format))
k += 1
list3 = [x1 - x2 for (x1, x2) in zip(timelist1, timelist2)]
Also, I am fairly new to Python, so any other constructive input on ways to improve and/or change anything else is greatly appreciated. Thank you!
List elements will use the repr, and the repr is not usually human readable.
>>> L = [datetime.timedelta(0, 2700), datetime.timedelta(0, 1800)]
>>> L
[datetime.timedelta(0, 2700), datetime.timedelta(0, 1800)]
You want:
>>> map(str, L) # or: [str(delta) for delta in L]
['0:45:00', '0:30:00']
This should give you a more readable format:
[((datetime.datetime.strptime('00:00:00', format))+e).strftime(format) for e in list3]
Out[340]: ['00:45:00', '00:30:00']
Here's a start. In Python there's no need for a counter when you iterate over a sequence, so the variables i and k are not needed. As wim pointed out, you probably want a string representation of the output. Finally, you can just generate the lists with a list comprehension instead of the loop.
import time
import datetime
strlist1 = ['12:45:00', '01:30:00']
format = '%H:%M:%S'
# i = 0 Not needed
timelist1 = [datetime.datetime.strptime(s, format) for s in strlist1]
strlist2 = ['12:00:00', '01:00:00']
timelist2 = [datetime.datetime.strptime(s, format) for s in strlist2]
list3 = [str(x1 - x2) for (x1, x2) in zip(timelist1, timelist2)]
Assume I have 2 time intervals,such as 16:30 - 20:00 AND 15:00 - 19:00, I need to find the total time between these two intervals so the result is 5 hours (I add both intervals and subtract the intersecting interval), how can I write a generic function which also deals with all cases such as one interval inside other(so the result is the interval of the bigger one), no intersection (so the result is the sum of both intervals).
My incoming data structure is primitive, simply string like "15:30" so a conversion may be needed.
Thanks
from datetime import datetime, timedelta
START, END = xrange(2)
def tparse(timestring):
return datetime.strptime(timestring, '%H:%M')
def sum_intervals(intervals):
times = []
for interval in intervals:
times.append((tparse(interval[START]), START))
times.append((tparse(interval[END]), END))
times.sort()
started = 0
result = timedelta()
for t, type in times:
if type == START:
if not started:
start_time = t
started += 1
elif type == END:
started -= 1
if not started:
result += (t - start_time)
return result
Testing with your times from the question:
intervals = [
('16:30', '20:00'),
('15:00', '19:00'),
]
print sum_intervals(intervals)
That prints:
5:00:00
Testing it together with data that doesn't overlap
intervals = [
('16:30', '20:00'),
('15:00', '19:00'),
('03:00', '04:00'),
('06:00', '08:00'),
('07:30', '11:00'),
]
print sum_intervals(intervals)
result:
11:00:00
I'll assume you can do the conversion to something like datetime on your own.
Sum the two intervals, then subtract any overlap. You can get the overlap by comparing the min and max of each of the two ranges.
Code for when there is an overlap, please add it to one of your solutions:
def interval(i1, i2):
minstart, minend = [min(*e) for e in zip(i1, i2)]
maxstart, maxend = [max(*e) for e in zip(i1, i2)]
if minend < maxstart: # no overlap
return minend-minstart + maxend-maxstart
else: # overlap
return maxend-minstart
You'll want to convert your strings into datetimes. You can do this with datetime.datetime.strptime.
Given intervals of datetime.datetime objects, if the intervals are:
int1 = (start1, end1)
int2 = (start2, end2)
Then isn't it just:
if end1 < start2 or end2 < start1:
# The intervals are disjoint.
return (end1-start1) + (end2-start2)
else:
return max(end1, end2) - min(start1, start2)