What is the easy way to validate scheduling data in python

Question:

I have a JSON object that contains the scheduling of a single day.

{
    "timings":{
        "id":43,
        "partition":7,
        "day_name":"Tuesday",
        "full_day":false,
        "close_day":false,
        "start_time":"2022-12-20 00:00:00",
        "close_time":"2022-12-20 23:00:00"
    },
    "pricings":[
        {
            "partition":7,
            "day_name":"Tuesday",
            "peak_hours":true,
            "start_time":"2022-12-20 17:00:00",
            "close_time":"2022-12-20 23:00:00",
            "price":"1300"
        },
        {
            "partition":7,
            "day_name":"Tuesday",
            "peak_hours":true,
            "start_time":"2022-12-20 00:00:00",
            "close_time":"2022-12-20 04:00:00",
            "price":"1300"
        },
        {
            "id":54,
            "partition":7,
            "day_name":"Tuesday",
            "peak_hours":false,
            "start_time":"2022-12-20 04:00:00",
            "close_time":"2022-12-20 17:00:00",
            "price":2000
        }
    ]
}

As you can see the first key is timings. Which contains the detail of the shop when it will open and when it’ll close.

Then we move on to the second key which is pricings. It’s a list of objects that contains that is it a peak hour or off_peak_hours or when they start and when they end.

How can we validate all timing values such as start times and close times of each entry?
they should not overlap each other and all time should be within shop opening and closing timings?

e.g with valid data:
the shop opens at 1 A.M.
shop closes at 11 A.M.

Now we have a list of hours:
first peak hours start at 1 A.M. to 4 A.M.
second off_hours starts from 4 A.M. to 7 A.M.
third peak_hours again starts at 7 A.M. and to 11 A.M.

e.g. invalid data:

The first peak hours start at 1 A.M. to 5 A.M.
second off_hours starts from 4 A.M. to 7 A.M.
third peak_hours again starts at 7 A.M. and to 11 A.M.

As you can see in the first line peak hour start from 1 A.M. to 5 A.M.
Second off hours start at 4 A.M. to 7 A.M..

Here the problem comes that 4 A.M. to 5 A.M. overlapping that single hour is coming into a peak hour as well as an off-peak hour so that input is not valid.

Another case:

{
    "timings":{
        "id":43,
        "partition":7,
        "day_name":"Tuesday",
        "full_day":false,
        "close_day":false,
        "start_time":"2022-12-20 00:00:00",
        "close_time":"2022-12-20 22:00:00"
    },
    "pricings":[
        {
            "partition":7,
            "day_name":"Tuesday",
            "peak_hours":true,
            "start_time":"2022-12-20 17:00:00",
            "close_time":"2022-12-20 23:00:00",
            "price":"1300"
        },
        {
            "partition":7,
            "day_name":"Tuesday",
            "peak_hours":true,
            "start_time":"2022-12-20 00:00:00",
            "close_time":"2022-12-20 04:00:00",
            "price":"1300"
        }
    ]
}

As you can see in the timings my shop opens from 00:00 to 22:00
in the pricings list, I have put the start time from 17:00 to 23:00

It returns valid even though you can see 22:00 to 23:00 shop is not even on.

And it is handled by following code :

for time in closeTime:
        if time > close :
            print("Not Valid")

    for time in startTime:
        if time < start:
            print("Not Valid")
Asked By: Ahmed Yasin

||

Answers:

Assuming objects in the pricings list are entered in chronological order (start at 00:00:00, end at 23:59:59) then we can jsut check to mak sure the diffrence between the i close_time and i+1 start_time is 0. If it is any other number then there must be overlap.

This can be accomplished using datetime

import datetime

validFlag = True
for i in range(len(obj["pricings"])-1):
    currentClose = datetime.datetime.strptime(obj["pricings"][i]["close_time"],'%Y-%m-%d %H:%M:%S')
    nextStart = datetime.datetime.strptime(obj["pricings"][i+1]["start_time"],'%Y-%m-%d %H:%M:%S')
    if currentClose-nextStart==datetime.timedelta(0):
        pass
    else:
        validFlag = False

if validFlag:
    print("Valid")
else:
    print("Not Valid")

Here we take the strings that indicate the time, change them to date times, find the difference between them. If the difference is anything but 0, we check a flag that indicates that it is not a valid entry.

This works according to your wishes given that the entries are in chronological order. In your example however they are not. So we will go over an example for this as well. The only idffrence in this second example is the use of list.sort() to sort the times

startTime = []
    closeTime = []
    for i in range(len(obj["pricings"])):
        startTime.append(datetime.datetime.strptime(obj["pricings"][i]["start_time"],'%Y-%m-%d %H:%M:%S'))
        closeTime.append(datetime.datetime.strptime(obj["pricings"][i]["close_time"],'%Y-%m-%d %H:%M:%S'))
    startTime.sort()
    closeTime.sort()
    validFlag = True
    for i in range(len(startTime)-1):
        if closeTime[i]-startTime[i+1]==datetime.timedelta(0):
            pass
        else:
            validFlag = False

    if validFlag:
        print("Valid")
    else:
        print("Not Valid")
Answered By: Eric Olsen
Categories: questions Tags: ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.