Lorenzo Bottaccioli
Lorenzo Bottaccioli

Reputation: 441

Generate array of datetime.time object python

How can I generate an array of datetime.time objects from these two objects:

start = datetime.time(22, 0)
end   = datetime.time( 2, 0)

That will look like:

interval = array([datetime.time(22,0), datetime.time(23,0), datetime.time(0,0),
                  datetime.time( 1,0), datetime.time( 2,0)])

EDIT

In this example the delta is hour=1, but it might be minutes or seconds. I'm loking for something similar to pandas.date_range.

Upvotes: 3

Views: 11050

Answers (4)

Vivek Gupta
Vivek Gupta

Reputation: 1

More simplistic solution can be

T = np.arange(datetime.date(2019, 4, 13),datetime.date(2020, 4, 13))

Upvotes: -1

SwiftsNamesake
SwiftsNamesake

Reputation: 1578

You could first generate the numbers you want with a kind of modularRange function. The generator expression makes the code shorter; we could've used a for loop, coupled with yield.

def modularRange(start, end, step, mod):
  return (i % mod for i in range(start, end + 1 + (0 if end >= start else mod), step))

You could also cheat a bit with the upper bound, exploiting the fact that bools are ints at the core:

range(start, end + 1 + mod*(end < start)

The mod argument would be 24 in your case and step is 1 (hour).

You'd then use np.array to construct the array, as the other posters have shown.

np.array([datetime.time(hour,0) for hour in modularRange(start.hour, end.hour, 1, 24)])

The OP requested an example with minutes. The code below will generate datetime.time objects at 5-minute intervals. I had to amend the modularRange function to account for steps.

startMin = start.hour * 60 + start.minute # Convert to minutes
endMin   = end.hour   * 60 + end.minute   # Convert to minutes
np.array([datetime.time(mins//60, mins%60) for mins in modularRange(startMin, endMin, 5, 24*60)])

Upvotes: 1

Anton vBR
Anton vBR

Reputation: 18916

update shorter version with numpy

import datetime
import numpy as np

def return_times(start,end):
    if start < end:
        return np.array([datetime.time(i,0) for i in range(start.hour,end.hour+1)])
    else:
        hours = list(range(24))
        nplist = np.array([datetime.time(i,0) for i in hours if i not in list(range(end.hour+1,start.hour))])
        return np.roll(nplist, -np.where(nplist==start)[0][0])

return_times(datetime.time(0,0),datetime.time(3,0)) # if-case 1
return_times(datetime.time(22,0),datetime.time(2,0)) # else-case

00:00 -> 03:00

array([datetime.time(0, 0), datetime.time(1, 0), datetime.time(2, 0),
   datetime.time(3, 0)], dtype=object)

100000 loops, best of 3: 12.6 µs per loop

22:00 -> 02:00

array([datetime.time(22, 0), datetime.time(23, 0), datetime.time(0, 0),
       datetime.time(1, 0), datetime.time(2, 0)], dtype=object)

10000 loops, best of 3: 79.9 µs per loop


update2 Using mod thanks to SwiftsNamesake, this can be solved in a single list comprehension

import datetime

def return_times(start,end):
    s  = start.hour
    e  = end.hour 
    hours = [i%24 for i in range(s, e+1 if e >= s else 24+e+1)]
    return [datetime.time(i,0) for i in hours]

return_times(datetime.time(0,0),datetime.time(3,0))

100000 loops, best of 3: 3.75 µs per loop

Upvotes: 1

Vishnu Upadhyay
Vishnu Upadhyay

Reputation: 5061

datetime.time([hour[, minute[, second[, microsecond[, tzinfo]]]]]) --> a time object

So if you look out some attributes of datetime.time like

start.hour
>>> 22    
end.hour
>>> 2
start.max
>>> datetime.time(23, 59, 59, 999999)
start.max.hour
>>> 23

You can implement your list using above factor.

[datetime.time(i, 0) for i in range(start.hour, start.max.hour+1)] + [datetime.time(i, 0) for i in range(end.min.hour, end.hour+1)]
Out[157]: [datetime.time(22, 0), datetime.time(23, 0), datetime.time(0, 0), datetime.time(1, 0), datetime.time(2, 0)]

Upvotes: 0

Related Questions