Muhammad Hamid Raza
Muhammad Hamid Raza

Reputation: 205

How to divide datetime range into slots with respect to slot duration and breaks

I have an interesting problem to solve. I need to divide a given time range into chunks of let's say 1 hour and there could be a constant break as well.

So, the scenario is that let's say a company has working hours from 9 AM to 5 PM for a given day, and they want to divide their work slots into slots of 1 hour. Also, there is usually a break in every working company hours and let's say that break is from 12:00 PM to 1:00 PM. That is the constant break. Another restriction is that after every 1-hour work slot, there is a break of 15 mins. So, keeping in view all this information I need to decide how many slots can be made in a given day.

Let's understand this with an example:

Working hours: 9 AM to 5 PM  
Constant break: 12:00 PM to 1:00 PM  
Max duration of one slot: 1-hour  
Break between each slot: 15 mins  

The resulting slots should be:

Slot#1: 9 AM to 10 AM
Slot#2: 10:15 AM to 11:15 AM  
Slot#3: 1:00 PM to 2:00 PM  
Slot#4: 2:15 PM to 3:15 PM  
Slot#5: 3:30 PM to 4:30 PM

Just to make a problem bit easier, along with the time we can consider the date as of today.

I am trying to solve the above problem using the native datetime and calendar library of python but could not do so. Can someone help me solve this?
Thanks!

Upvotes: 1

Views: 1206

Answers (1)

Hoxha Alban
Hoxha Alban

Reputation: 1137

Here is my solution:

First, i've created a new object called Day so i can easily do math with hour and minutes:

from functools import total_ordering

@total_ordering
class Day():
    def __init__(self, h=0, m=0):
        self.h = (h + m // 60) % 24
        self.m = m % 60

    def __add__(self, other):
        return Day(self.h + other.h, self.m + other.m)

    def __iadd__(self, other):
        return self.__add__(other)

    def __sub__(self, other):
        return Day(self.h - other.h, self.m - other.m)

    def __isub__(self, other):
        return self.__sub__(other)

    def __repr__(self):
        return f'h: {self.h}, m:{self.m}'

    def __str__(self):
        return self.__repr__()

    def __eq__(self, other):
        return self.h == other.h and self.m == other.m

    def __gt__(self, other):
        return self.h > other.h or (self.h == other.h and self.m > other.m)

    def __copy__(self):
        return Day(self.h, self.m)

    def copy(self):
        return self.__copy__()

Then i've saved the data in your example in the form of Day objects

start_day = Day(9) # starting working day
end_day = Day(17) # end working day

start_break = Day(12)
end_break = Day(13)

slot_duration = Day(1)
interbreak_duration = Day(0, 15) # break between slots

Now with this setup it should be easier to write an algorithm to do you calculations.

Here is a draft of my solution but it doesn't work that well, i'll recommend you to write a new algorithm tailored to your desired output

def calculate(start_day, end_day, start_break, end_break, slot_duration, interbreak_duration):
    now = start_day.copy()
    break_done = False # mid day break
    interbreak_done = True # break between slots

    while True:
        print(now, end=' ')
        if interbreak_done: 
            print('\tslot', end='')
        else:
            print('\tbreak', end='')
        if break_done:
            if interbreak_done:
                now += slot_duration
                if now == end_day:
                    print(now)
                    break
                if now >= end_day:
                    print('\r', end='')
                    break
                interbreak_done = False
            else:
                now += interbreak_duration
                if now == end_day:
                    print(now)
                    break
                if now > end_day:
                    print('\r', end='')
                    break
                interbreak_done = True
        else:
            if interbreak_done:
                now += slot_duration
                interbreak_done = False
                if now == start_break:
                    print('slot')
                if now >= start_break:
                    print('\r', end='')
                    now = end_break
                    interbreak_done = True
                    break_done = True
                    continue
            else:
                now += interbreak_duration
                if now >= start_break:
                    now = end_break
                    break_done = True
                interbreak_done = True


        print('\t', now)

the output is:

calculate(start_day, end_day, start_break, end_break, slot_duration, interbreak_duration)

h: 9, m:0       slot     h: 10, m:0
h: 10, m:0      break    h: 10, m:15
h: 10, m:15     slot     h: 11, m:15
h: 11, m:15     break    h: 11, m:30
h: 13, m:0      slot     h: 14, m:0
h: 14, m:0      break    h: 14, m:15
h: 14, m:15     slot     h: 15, m:15
h: 15, m:15     break    h: 15, m:30
h: 15, m:30     slot     h: 16, m:30
h: 16, m:30     break    h: 16, m:45
h: 16, m:45     slot

it's a little buggy but it should help you to get started

Upvotes: 1

Related Questions