0

I have a list of six-hour time slots ['00:00','06:00','12:00','18:00']. I need to build a function that returns one of the time slots if the current time falls under:

From 00:00 - to 05:59 -> # should return -> 00:00
From 06:00 - to 11:59 -> # should return -> 06:00
From 12:00 - to 17:59 -> # should return -> 12:00
From 18:00 - to 23:59 -> # should return -> 18:00

I asked for a similar function that returns the closest and furthest time to the current time at: https://stackoverflow.com/a/68240328/14712981. I used the same code from @RJ Adriaansen for my current question but it didn't work as expected.

Here is the code:

current_time = '10:00'
time = ['00:00','06:00','12:00','18:00']

def get_time(time):
  return datetime.strptime(time, '%H:%M')


current_time = get_time(current_time)
time = [get_time(i) for i in time]

print(min(time,key=lambda x : abs(current_time-x)).strftime('%H:%M'))

# It returns 12:00, while it should return 06:00 in my case.

Can someone tell me what I need to do in order to solve the problem?

B A C H A S H
  • 126
  • 1
  • 9
  • Why are you using `abs()`? It will return the timeslot whose start time is closest to `x` rather than earlier than it. – Barmar Jul 06 '21 at 01:08

2 Answers2

1

This is really a string manipulation problem rather than a date/time one (as in there's not a need for datetime to get involved).

Here's a function (including test harness) that will do what you need (noting that I've changed your 6:00 to 06:00 so it matches the rest of the question and is the same format as the other times, especially 00:00 which indicates leading zeros):

def which_slot(slots, value):
    if slots[0] != "00:00":
        raise Exception("first slot must be 00:00")
    return slots[len(slots) - sum([1 for item in slots[1:] if value < item]) - 1]

slots = ["00:00", "06:00", "12:00", "18:00"]

for test in ["00:00", "00:01"]:
    print(f"{test} : {which_slot(slots, test)}")

for hour in [3, 6, 12, 18, 21]:
    for test in [f"{hour-1:02}:59", f"{hour:02}:00", f"{hour:02}:01"]:
        print(f"{test} : {which_slot(slots, test)}")

for test in ["23:59"]:
    print(f"{test} : {which_slot(slots, test)}")

The output shows the values you get for the various inputs:

00:00 : 00:00
00:01 : 00:00
02:59 : 00:00
03:00 : 00:00
03:01 : 00:00
05:59 : 00:00
06:00 : 06:00
06:01 : 06:00
11:59 : 06:00
12:00 : 12:00
12:01 : 12:00
17:59 : 12:00
18:00 : 18:00
18:01 : 18:00
20:59 : 18:00
21:00 : 18:00
21:01 : 18:00
23:59 : 18:00

The way it works is to construct a list of 1 values for each slot that is less than your desired item, then sum that list.

This gives you a reverse position (higher sums for earlier times) which you can manipulate into an index. Then that index is used to return the correct time for the slot.

paxdiablo
  • 854,327
  • 234
  • 1,573
  • 1,953
0

abs(current_time) is ignoring whether the x is before or after current_time, so it returns the closest timeslot, not the closest one starting before current_time.

If the timeslots are sorted, just loop until you find one that's less than or equal to the current time.

for slot in time:
    if slot <= current_time:
        print(slot.strftime('%H:%M'))
        break

if they're not already sorted, use for slot in sorted(time):

Barmar
  • 741,623
  • 53
  • 500
  • 612