Johnston
Johnston

Reputation: 20884

Adjust start and end range for time list in Python

I have this magical incantation that I use (and understand) to populate a time field with the all hours of the day in fifteen minute intervals.

['%s:%s%s' % (h, m, ap) for ap in ('am', 'pm') for h in ([12] + range(1,12)) for m in ('00', '15','30','45')]

This prints out a list:

['12:00am', '12:15am', '12:30am', '12:45am', '1:00am',...

I am attempting to adjust that code so that it works for a start time and end time. For example I want it to start at 9am and end at 5pm.
When the time comes back from the database it is a time object: datetime.time(18, 0)
What I tried to do was to take the hour of the datetime.time and start the range there. But my mind got kind of blown by the idea of adjusting it for am and pm.

How do I adjust the code to work with a start and end time?

Upvotes: 1

Views: 311

Answers (2)

Hyperboreus
Hyperboreus

Reputation: 32429

You can do something like this. Write your own generator which works like range and takes a time-object (which comes from your DB if I understand you correctly) as start and stop (exclusively):

#! /usr/bin/python3
import datetime

def timerange(start, stop, step = datetime.timedelta(minutes = 15)):
    t = datetime.datetime(2000, 1, 1, start.hour, start.minute)
    stop = datetime.datetime(2000, 1, 1 if start <= stop else 2, stop.hour, stop.minute)
    while t < stop:
        yield t.time()
        t += step

Now you can use it like this and it yields time-objects:

nineam = datetime.time(9, 0) #from DB
fivepm = datetime.time(17, 0) #from DB

for t in timerange(nineam, fivepm):
    print(t)

If you want it formatted, write another generator that returns a string according to your necessities:

def ftimerange(start, stop, step = datetime.timedelta(minutes = 15)):
    for t in timerange(start, stop, step):
        yield t.strftime('%I:%M%p')

for s in ftimerange(nineam, fivepm):
    print(s)

This also works if start is before midnight and stop after it.


Here a working sample:

>>> elevenpm = datetime.time(23, 0)
>>> oneam = datetime.time(1, 0)
>>> for s in ftimerange(elevenpm, oneam): print(s)
... 
11:00PM
11:15PM
11:30PM
11:45PM
12:00AM
12:15AM
12:30AM
12:45AM

Or with another step in the seconds-range:

>>> start = datetime.time(8, 5)
>>> stop = datetime.time(9, 12)
>>> step = datetime.timedelta(minutes = 3, seconds = 22)
>>> for s in ftimerange(start, stop, step): print(s)
... 
08:05AM
08:08AM
08:11AM
08:15AM
08:18AM
08:21AM
08:25AM
08:28AM
08:31AM
08:35AM
08:38AM
08:42AM
08:45AM
08:48AM
08:52AM
08:55AM
08:58AM
09:02AM
09:05AM
09:08AM

Upvotes: 3

Simeon Visser
Simeon Visser

Reputation: 122376

You can adapt h for a specific range:

['%s:%s%s' % (h, m, ap) for ap in ('am', 'pm') for h in ([9] + range(1,5)) for m in ('00', '15','30','45')]

However this won't produce 5.00pm as the range does not include the last time.

Upvotes: 0

Related Questions