Skip to content

Commit b3af89b

Browse files
author
Chang She
committed
ENH: between_time across midnight #1871
1 parent c78d5c5 commit b3af89b

File tree

3 files changed

+45
-8
lines changed

3 files changed

+45
-8
lines changed

RELEASE.rst

+1
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ pandas 0.9.0
5656
(dropping both columns and rows) (#924)
5757
- Improve DataFrame.to_html output for hierarchically-indexed rows (do not
5858
repeat levels) (#1929)
59+
- TimeSeries.between_time can now select times across midnight (#1871)
5960

6061
**API Changes**
6162

pandas/tseries/index.py

+16-8
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
# pylint: disable=E1101
2+
import operator
23

34
from datetime import time, datetime
45
from datetime import timedelta
@@ -1358,18 +1359,25 @@ def indexer_between_time(self, start_time, end_time, include_start=True,
13581359
start_micros = _time_to_micros(start_time)
13591360
end_micros = _time_to_micros(end_time)
13601361

1362+
13611363
if include_start and include_end:
1362-
mask = ((start_micros <= time_micros) &
1363-
(time_micros <= end_micros))
1364+
lop = rop = operator.le
13641365
elif include_start:
1365-
mask = ((start_micros <= time_micros) &
1366-
(time_micros < end_micros))
1366+
lop = operator.le
1367+
rop = operator.lt
13671368
elif include_end:
1368-
mask = ((start_micros < time_micros) &
1369-
(time_micros <= end_micros))
1369+
lop = operator.lt
1370+
rop = operator.le
1371+
else:
1372+
lop = rop = operator.lt
1373+
1374+
if start_time <= end_time:
1375+
join_op = operator.and_
13701376
else:
1371-
mask = ((start_micros < time_micros) &
1372-
(time_micros < end_micros))
1377+
join_op = operator.or_
1378+
1379+
mask = join_op(lop(start_micros, time_micros),
1380+
rop(time_micros, end_micros))
13731381

13741382
return mask.nonzero()[0]
13751383

pandas/tseries/tests/test_timeseries.py

+28
Original file line numberDiff line numberDiff line change
@@ -879,6 +879,34 @@ def test_between_time(self):
879879
expected = ts.between_time(stime, etime)
880880
assert_series_equal(result, expected)
881881

882+
#across midnight
883+
rng = date_range('1/1/2000', '1/5/2000', freq='5min')
884+
ts = Series(np.random.randn(len(rng)), index=rng)
885+
stime = time(22, 0)
886+
etime = time(9, 0)
887+
888+
close_open = itertools.product([True, False], [True, False])
889+
for inc_start, inc_end in close_open:
890+
filtered = ts.between_time(stime, etime, inc_start, inc_end)
891+
exp_len = (12 * 11 + 1) * 4 + 1
892+
if not inc_start:
893+
exp_len -= 4
894+
if not inc_end:
895+
exp_len -= 4
896+
897+
self.assert_(len(filtered) == exp_len)
898+
for rs in filtered.index:
899+
t = rs.time()
900+
if inc_start:
901+
self.assert_((t >= stime) or (t <= etime))
902+
else:
903+
self.assert_((t > stime) or (t <= etime))
904+
905+
if inc_end:
906+
self.assert_((t <= etime) or (t >= stime))
907+
else:
908+
self.assert_((t < etime) or (t >= stime))
909+
882910
def test_dti_constructor_preserve_dti_freq(self):
883911
rng = date_range('1/1/2000', '1/2/2000', freq='5min')
884912

0 commit comments

Comments
 (0)