Как правильно рассчитать промежутки времени между заданными отрезками времени? - PullRequest
1 голос
/ 06 мая 2020

В приложении для учета рабочего времени день разделен на пять частей:

0: 00 - 6:00, 6:00 - 14:00, 14:00 - 20:00, 20:00 - 23:00, 23:00 - (бесконечность)

Эти пять «ящиков» должны быть заполнены в соответствии со временем, проведенным в любом из них. Например, рассматриваемый интервал начинается в 5:00 и заканчивается в 16:00, ячейка №1 содержит 1 час, ячейка №2 содержит 8 часов, ячейка №3 содержит 2 часа, ячейка №4 содержит 0 часов, ячейка №5 содержит 0 часов. Любое время после 23:00 попадает в корзину № 5.

До сих пор я придумал следующее:

    sections = [ 0, 0, 0, 0, 0 ]
    for tframe in numericdata:
        if tframe[0] < 6.00: # starts before 6:00
            if tframe[1] >= 6.00: # ends after 6:00
                sections[0] += 6.00 - tframe[0]
            else: # ends before 6:00
                sections[0] += tframe[1] - tframe[0]
                continue

            if tframe[1] >= 14.00: # ends after 14:00
                sections[1] += 14.00 - 6.00
            else: # ends between 6:00 and 14:00
                sections[1] += tframe[1] - 6.00
                continue

            if tframe[1] >= 20.00: # ends after 20:00
                sections[2] += 20.00 - 14.00
            else: # ends between 14:00 and 20:00
                sections[2] += tframe[1] - 14.00
                continue

            if tframe[1] >= 23.00: # ends after 23:00
                sections[3] += 23.00 - 20.00
                sections[4] += tframe[1] - 23.00
            else: # ends between 20:00 and 23:00
                sections[3] += tframe[1] - 20.00
                continue

        elif tframe[0] < 14.00: # starts between 6:00 and 14:00
            if tframe[1] >= 14.00: # ends after 14:00
                sections[1] += 14.00 - tframe[0]
            else: # ends before 14:00
                sections[1] += tframe[1] - tframe[0]
                continue

            if tframe[1] >= 20.00: # ends after 20:00
                sections[2] += 20.00 - 14.00
            else: # ends between 14:00 and 20:00
                sections[2] += tframe[1] - 14.00
                continue

            if tframe[1] >= 23.00: # ends after 23:00
                sections[3] += 23.00 - 20.00
                sections[4] += tframe[1] - 23.00
            else: # ends between 20:00 and 23:00
                sections[3] += tframe[1] - 20.00
                continue

        elif tframe[0] < 20.00: # starts between 14:00 and 20:00
            if tframe[1] >= 20.00: # ends after 20:00
                sections[2] += 20.00 - tframe[0]
            else: # ends before 20:00
                sections[2] += tframe[1] - tframe[0]
                continue

            if tframe[1] >= 23.00: # ends after 23:00
                sections[3] += 23.00 - 20.00
                sections[4] += tframe[1] - 23.00
            else: # ends between 20:00 and 23:00
                sections[3] += tframe[1] - 20.00
                continue

        elif tframe[0] < 23.00: # starts between 20:00 and 23:00
            if tframe[1] >= 23.00: # ends after 23:00
                sections[3] += 23.00 - tframe[0]
                sections[4] += tframe[1] - 23.00
            else: # ends before 23:00
                sections[3] += tframe[1] - tframe[0]
                continue

        else: # starts and ends some time after 23:00
            sections[4] += tframe[1] - tframe[0]

numericdata - это массив, содержащий интервалы как кортежи начала. и конец времен. Все значения времени были преобразованы в часы с дробями, поэтому 13:15 кодируется как 13,25, et c. Например, numericdata может содержать [ [ 6.75, 12.5 ], [ 13.5, 18.25 ] ], поэтому два интервала: один с 6:45 до 12:30, а другой - с 13:30 до 18:15. Результирующий массив sections будет выглядеть так: [ 0, 6.25, 4.25, 0, 0 ]

Я чувствую, что должен быть лучший способ сделать это, чем то, что я придумал. Это полностью жестко запрограммировано, и я не могу придумать что-то, что уменьшало бы дублирование кода и, возможно, было бы немного более гибким, например, определение количества ячеек и их длины, а не жесткое их кодирование таким образом.

Заранее спасибо!

1 Ответ

1 голос
/ 07 мая 2020

Надеюсь, я правильно понял ваш вопрос. разделение часов определяется в списке splits, поэтому его можно настроить:

data = [[ 6.75, 12.5 ], [ 13.5, 18.25 ]]
splits = [0, 6, 14, 20, 23, float('inf')]

def intersection(a, b, c, d):
    if a > d or b < c:
        return 0 # no intersection
    left, right = max(a, c), min(b, d)
    return right - left

out = [sum(v) for v in zip(*[[intersection(*i, *s) for s in zip(splits, splits[1::])] for i in data])]

print(out)

Печать:

[0, 6.25, 4.25, 0, 0]
...