在python中计算日历约会之外的空闲时间段(datetime)

在python中计算日历约会之外的空闲时间段(datetime),python,date,date-range,date-comparison,Python,Date,Date Range,Date Comparison,我通过ExchangeEWSAPI获取约会,并创建包含开始/结束忙碌(datetime)时段的json数组。我想反转此数据以获取每天的空闲时间段列表 办公时间从早上8点开始。 办公时间下午6点结束 最后,我找到了如何从繁忙时段的元组中计算空闲时段的算法问题的解决方案。下面是我是如何做到这一点的简化代码 from datetime import datetime, timedelta import pprint pp = pprint.PrettyPrinter() tstart = datet

我通过ExchangeEWSAPI获取约会,并创建包含开始/结束忙碌(datetime)时段的json数组。我想反转此数据以获取每天的空闲时间段列表

办公时间从早上8点开始。 办公时间下午6点结束

最后,我找到了如何从繁忙时段的元组中计算空闲时段的算法问题的解决方案。下面是我是如何做到这一点的简化代码

from datetime import datetime, timedelta
import pprint
pp = pprint.PrettyPrinter()

tstart = datetime.strptime('08:00:00', '%H:%M:%S')
tstop = datetime.strptime('18:00:00', '%H:%M:%S')

appointments = ([
    {
        'start' : datetime.strptime('08:30:00', '%H:%M:%S'),
        'end' : datetime.strptime('10:00:00', '%H:%M:%S')
    },
    {
        'start' : datetime.strptime('09:30:00', '%H:%M:%S'),
        'end' : datetime.strptime('11:00:00', '%H:%M:%S')
    },
    {
        'start' : datetime.strptime('12:30:00', '%H:%M:%S'),
        'end' : datetime.strptime('14:00:00', '%H:%M:%S')
    },
    {
        'start' : datetime.strptime('15:30:00', '%H:%M:%S'),
        'end' : datetime.strptime('16:00:00', '%H:%M:%S')
    },
    {
        'start' : datetime.strptime('16:00:00', '%H:%M:%S'),
        'end' : datetime.strptime('17:00:00', '%H:%M:%S')
    },
    ])

"""
CORRECT FREE PERIODS ARE:
8:00 - 8:30
11:00 - 12:30
14:00 - 15:30
17:00 - 18:00
"""

tp = [(tstart , tstart)]
free_time = []
for t in appointments:
    tp.append( ( t['start'] , t['end'] ) )
tp.append( (tstop , tstop) )

for i,v in enumerate(tp):
    if i > 0:
        if (tp[i][0] - tp[i-1][1]) > timedelta(seconds=0):
            tf_start = tp[i-1][1]
            delta = tp[i][0] - tp[i-1][1]
            tf_end = tf_start + delta
            free_time.append( (tf_start ,tf_end ) )

for tp in free_time:
    print tp

你的代码帮助我们建立了一个项目!非常感谢。但是,我发现了一种边缘情况,当存在重叠事件时,上述算法错误地注册空闲时间:

例句:7:8和7:30-9的比赛将打破僵局

我在您的代码中添加了一点来解决这个问题。以下是我使用的:

a_busy = [
    {'start': datetime.datetime(2020, 1, 1, 6), 'end': datetime.datetime(2020, 1, 1, 6, 30)},
    {'start': datetime.datetime(2020, 1, 1, 7), 'end': datetime.datetime(2020, 1, 1, 8)},
    {'start': datetime.datetime(2020, 1, 1, 7, 30), 'end': datetime.datetime(2020, 1, 1, 9, 30)},
    {'start': datetime.datetime(2020, 1, 1, 11), 'end': datetime.datetime(2020, 1, 1, 12, 30)},
    {'start': datetime.datetime(2020, 1, 1, 15), 'end': datetime.datetime(2020, 1, 1, 15, 45)},
    {'start': datetime.datetime(2020, 1, 1, 16, 45), 'end': datetime.datetime(2020, 1, 1, 17, 30)}
]

b_busy = [
    {'start': datetime.datetime(2020, 1, 1, 5, 45), 'end': datetime.datetime(2020, 1, 1, 6, 30)},
    {'start': datetime.datetime(2020, 1, 1, 7, 30), 'end': datetime.datetime(2020, 1, 1, 8)},
    {'start': datetime.datetime(2020, 1, 1, 8), 'end': datetime.datetime(2020, 1, 1, 9)},
    {'start': datetime.datetime(2020, 1, 1, 10, 30), 'end': datetime.datetime(2020, 1, 1, 13)},
    {'start': datetime.datetime(2020, 1, 1, 14), 'end': datetime.datetime(2020, 1, 1, 15)},
    {'start': datetime.datetime(2020, 1, 1, 15, 30), 'end': datetime.datetime(2020, 1, 1, 16, 30)}
]
# free times: 6:30-7, 9:30-10:30, 13:00-14:00, 16:30-16:45
tstart = datetime.datetime(2020, 1, 1, 6)
tstop = datetime.datetime(2020, 1, 1, 17)

together = sorted(a_busy + b_busy, key=lambda k: k['start'])
tp = [(tstart, tstart)]
free_time = []
for t in together:
    tp.append((t['start'], t['end']))
tp.append((tstop, tstop))

# This section added to resolve the case mentioned above
i = 1
while i < len(tp):
    if tp[i][0] < tp[i - 1][1]:
        start_times = [tp[i - 1][0], tp[i][0]]
        end_times = [tp[i - 1][1], tp[i][1]]
        tp[i - 1] = (min(start_times), max(end_times))
        tp.pop(i)
    else:
        i += 1

for i, v in enumerate(tp):
    if i > 0:
        if (tp[i][0] - tp[i - 1][1]) > datetime.timedelta(seconds=0):
            tf_start = tp[i - 1][1]
            delta = tp[i][0] - tp[i - 1][1]
            tf_end = tf_start + delta
            free_time.append(tup)
a_busy=[
{'start':datetime.datetime(2020,1,1,6),'end':datetime.datetime(2020,1,1,6,30)},
{'start':datetime.datetime(2020,1,1,7),'end':datetime.datetime(2020,1,1,8)},
{'start':datetime.datetime(2020,1,1,7,30),'end':datetime.datetime(2020,1,1,9,30)},
{'start':datetime.datetime(2020,1,1,11),'end':datetime.datetime(2020,1,1,12,30)},
{'start':datetime.datetime(2020,1,1,15),'end':datetime.datetime(2020,1,1,15,45)},
{'start':datetime.datetime(2020,1,1,16,45),'end':datetime.datetime(2020,1,1,17,30)}
]
b_忙=[
{'start':datetime.datetime(2020,1,1,5,45),'end':datetime.datetime(2020,1,1,6,30)},
{'start':datetime.datetime(2020,1,1,7,30),'end':datetime.datetime(2020,1,1,8)},
{'start':datetime.datetime(2020,1,1,8),'end':datetime.datetime(2020,1,1,9)},
{'start':datetime.datetime(2020,1,1,10,30),'end':datetime.datetime(2020,1,1,13)},
{'start':datetime.datetime(2020,1,1,14),'end':datetime.datetime(2020,1,1,15)},
{'start':datetime.datetime(2020,1,1,15,30),'end':datetime.datetime(2020,1,1,16,30)}
]
#自由时间:6:30-7,9:30-10:30,13:00-14:00,16:30-16:45
tstart=datetime.datetime(2020,1,1,6)
tstop=datetime.datetime(2020,1,1,17)
合在一起=排序(a_busy+b_busy,key=lambda k:k['start']))
tp=[(tstart,tstart)]
自由时间=[]
对于t in,请同时执行以下操作:
tp.append((t['start'],t['end']))
tp.append((tstop,tstop))
#增加本节是为了解决上述情况
i=1
而i0:
如果(tp[i][0]-tp[i-1][1])>datetime.timedelta(秒=0):
tf_start=tp[i-1][1]
delta=tp[i][0]-tp[i-1][1]
tf_end=tf_start+delta
空闲时间追加(tup)

您的代码帮助我们构建了一个项目!非常感谢。但是,我发现了一种边缘情况,当存在重叠事件时,上述算法错误地注册空闲时间:

例句:7:8和7:30-9的比赛将打破僵局

我在您的代码中添加了一点来解决这个问题。以下是我使用的:

a_busy = [
    {'start': datetime.datetime(2020, 1, 1, 6), 'end': datetime.datetime(2020, 1, 1, 6, 30)},
    {'start': datetime.datetime(2020, 1, 1, 7), 'end': datetime.datetime(2020, 1, 1, 8)},
    {'start': datetime.datetime(2020, 1, 1, 7, 30), 'end': datetime.datetime(2020, 1, 1, 9, 30)},
    {'start': datetime.datetime(2020, 1, 1, 11), 'end': datetime.datetime(2020, 1, 1, 12, 30)},
    {'start': datetime.datetime(2020, 1, 1, 15), 'end': datetime.datetime(2020, 1, 1, 15, 45)},
    {'start': datetime.datetime(2020, 1, 1, 16, 45), 'end': datetime.datetime(2020, 1, 1, 17, 30)}
]

b_busy = [
    {'start': datetime.datetime(2020, 1, 1, 5, 45), 'end': datetime.datetime(2020, 1, 1, 6, 30)},
    {'start': datetime.datetime(2020, 1, 1, 7, 30), 'end': datetime.datetime(2020, 1, 1, 8)},
    {'start': datetime.datetime(2020, 1, 1, 8), 'end': datetime.datetime(2020, 1, 1, 9)},
    {'start': datetime.datetime(2020, 1, 1, 10, 30), 'end': datetime.datetime(2020, 1, 1, 13)},
    {'start': datetime.datetime(2020, 1, 1, 14), 'end': datetime.datetime(2020, 1, 1, 15)},
    {'start': datetime.datetime(2020, 1, 1, 15, 30), 'end': datetime.datetime(2020, 1, 1, 16, 30)}
]
# free times: 6:30-7, 9:30-10:30, 13:00-14:00, 16:30-16:45
tstart = datetime.datetime(2020, 1, 1, 6)
tstop = datetime.datetime(2020, 1, 1, 17)

together = sorted(a_busy + b_busy, key=lambda k: k['start'])
tp = [(tstart, tstart)]
free_time = []
for t in together:
    tp.append((t['start'], t['end']))
tp.append((tstop, tstop))

# This section added to resolve the case mentioned above
i = 1
while i < len(tp):
    if tp[i][0] < tp[i - 1][1]:
        start_times = [tp[i - 1][0], tp[i][0]]
        end_times = [tp[i - 1][1], tp[i][1]]
        tp[i - 1] = (min(start_times), max(end_times))
        tp.pop(i)
    else:
        i += 1

for i, v in enumerate(tp):
    if i > 0:
        if (tp[i][0] - tp[i - 1][1]) > datetime.timedelta(seconds=0):
            tf_start = tp[i - 1][1]
            delta = tp[i][0] - tp[i - 1][1]
            tf_end = tf_start + delta
            free_time.append(tup)
a_busy=[
{'start':datetime.datetime(2020,1,1,6),'end':datetime.datetime(2020,1,1,6,30)},
{'start':datetime.datetime(2020,1,1,7),'end':datetime.datetime(2020,1,1,8)},
{'start':datetime.datetime(2020,1,1,7,30),'end':datetime.datetime(2020,1,1,9,30)},
{'start':datetime.datetime(2020,1,1,11),'end':datetime.datetime(2020,1,1,12,30)},
{'start':datetime.datetime(2020,1,1,15),'end':datetime.datetime(2020,1,1,15,45)},
{'start':datetime.datetime(2020,1,1,16,45),'end':datetime.datetime(2020,1,1,17,30)}
]
b_忙=[
{'start':datetime.datetime(2020,1,1,5,45),'end':datetime.datetime(2020,1,1,6,30)},
{'start':datetime.datetime(2020,1,1,7,30),'end':datetime.datetime(2020,1,1,8)},
{'start':datetime.datetime(2020,1,1,8),'end':datetime.datetime(2020,1,1,9)},
{'start':datetime.datetime(2020,1,1,10,30),'end':datetime.datetime(2020,1,1,13)},
{'start':datetime.datetime(2020,1,1,14),'end':datetime.datetime(2020,1,1,15)},
{'start':datetime.datetime(2020,1,1,15,30),'end':datetime.datetime(2020,1,1,16,30)}
]
#自由时间:6:30-7,9:30-10:30,13:00-14:00,16:30-16:45
tstart=datetime.datetime(2020,1,1,6)
tstop=datetime.datetime(2020,1,1,17)
合在一起=排序(a_busy+b_busy,key=lambda k:k['start']))
tp=[(tstart,tstart)]
自由时间=[]
对于t in,请同时执行以下操作:
tp.append((t['start'],t['end']))
tp.append((tstop,tstop))
#增加本节是为了解决上述情况
i=1
而i0:
如果(tp[i][0]-tp[i-1][1])>datetime.timedelta(秒=0):
tf_start=tp[i-1][1]
delta=tp[i][0]-tp[i-1][1]
tf_end=tf_start+delta
空闲时间追加(tup)

“以下代码在if子句中失败”您能给我们提供一个答案吗?除了@TemporalWolf(非常好)建议您编写a之外,您还需要尽可能详细地描述您的错误-发生了什么,您期望发生什么以及它们之间的区别。感谢您的建议,现在我发布了一个,不完整但可验证的示例。不幸的是,我不能给出一个完整的工作示例,因为这就是我的问题的来源。当您运行上面的代码时,错误是显而易见的——if子句是错误的和不完整的,因为太复杂了。我为所描述的目标寻找一种工作方法。为我的任务找到了算术解,也许其他人可以