Skip to content

Commit 451811d

Browse files
jamestran201-altjreback
authored andcommitted
Improve DatetimeIndex.time performance (#18461)
1 parent 1355df6 commit 451811d

File tree

4 files changed

+19
-12
lines changed

4 files changed

+19
-12
lines changed

asv_bench/benchmarks/timeseries.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@ def time_dti_tz_factorize(self):
8585
self.dti_tz.factorize()
8686

8787
def time_dti_time(self):
88-
self.rng.time
88+
self.dst_rng.time
8989

9090
def time_timestamp_tzinfo_cons(self):
9191
self.rng5[0]

doc/source/whatsnew/v0.22.0.txt

+1
Original file line numberDiff line numberDiff line change
@@ -233,6 +233,7 @@ Performance Improvements
233233
- Improved performance of :func:`Series.dt.date` and :func:`DatetimeIndex.date` (:issue:`18058`)
234234
- Improved performance of :func:`IntervalIndex.symmetric_difference()` (:issue:`18475`)
235235
- Improved performance of ``DatetimeIndex`` and ``Series`` arithmetic operations with Business-Month and Business-Quarter frequencies (:issue:`18489`)
236+
- Improved performance of :func:`Series.dt.time` and :func:`DatetimeIndex.time`
236237

237238
.. _whatsnew_0220.docs:
238239

pandas/_libs/tslib.pyx

+15-6
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ from util cimport (is_integer_object, is_float_object, is_string_object,
1515
from cpython.datetime cimport (PyDateTime_Check, PyDate_Check,
1616
PyDateTime_CheckExact,
1717
PyDateTime_IMPORT,
18-
timedelta, datetime, date)
18+
timedelta, datetime, date, time)
1919
# import datetime C API
2020
PyDateTime_IMPORT
2121

@@ -70,11 +70,17 @@ cdef inline object create_date_from_ts(
7070
""" convenience routine to construct a datetime.date from its parts """
7171
return date(dts.year, dts.month, dts.day)
7272

73+
cdef inline object create_time_from_ts(
74+
int64_t value, pandas_datetimestruct dts,
75+
object tz, object freq):
76+
""" convenience routine to construct a datetime.time from its parts """
77+
return time(dts.hour, dts.min, dts.sec, dts.us, tz)
78+
7379

7480
def ints_to_pydatetime(ndarray[int64_t] arr, tz=None, freq=None,
7581
box="datetime"):
7682
"""
77-
Convert an i8 repr to an ndarray of datetimes, date or Timestamp
83+
Convert an i8 repr to an ndarray of datetimes, date, time or Timestamp
7884
7985
Parameters
8086
----------
@@ -83,19 +89,17 @@ def ints_to_pydatetime(ndarray[int64_t] arr, tz=None, freq=None,
8389
convert to this timezone
8490
freq : str/Offset, default None
8591
freq to convert
86-
box : {'datetime', 'timestamp', 'date'}, default 'datetime'
92+
box : {'datetime', 'timestamp', 'date', 'time'}, default 'datetime'
8793
If datetime, convert to datetime.datetime
8894
If date, convert to datetime.date
95+
If time, convert to datetime.time
8996
If Timestamp, convert to pandas.Timestamp
9097
9198
Returns
9299
-------
93100
result : array of dtype specified by box
94101
"""
95102

96-
assert ((box == "datetime") or (box == "date") or (box == "timestamp")), \
97-
"box must be one of 'datetime', 'date' or 'timestamp'"
98-
99103
cdef:
100104
Py_ssize_t i, n = len(arr)
101105
ndarray[int64_t] trans, deltas
@@ -115,8 +119,13 @@ def ints_to_pydatetime(ndarray[int64_t] arr, tz=None, freq=None,
115119
if is_string_object(freq):
116120
from pandas.tseries.frequencies import to_offset
117121
freq = to_offset(freq)
122+
elif box == "time":
123+
func_create = create_time_from_ts
118124
elif box == "datetime":
119125
func_create = create_datetime_from_ts
126+
else:
127+
raise ValueError("box must be one of 'datetime', 'date', 'time' or" +
128+
" 'timestamp'")
120129

121130
if tz is not None:
122131
if is_utc(tz):

pandas/core/indexes/datetimes.py

+2-5
Original file line numberDiff line numberDiff line change
@@ -53,8 +53,7 @@
5353
import pandas.core.tools.datetimes as tools
5454

5555
from pandas._libs import (lib, index as libindex, tslib as libts,
56-
algos as libalgos, join as libjoin,
57-
Timestamp)
56+
join as libjoin, Timestamp)
5857
from pandas._libs.tslibs import (timezones, conversion, fields, parsing,
5958
period as libperiod)
6059

@@ -1677,9 +1676,7 @@ def time(self):
16771676
"""
16781677
Returns numpy array of datetime.time. The time part of the Timestamps.
16791678
"""
1680-
return self._maybe_mask_results(libalgos.arrmap_object(
1681-
self.astype(object).values,
1682-
lambda x: np.nan if x is libts.NaT else x.time()))
1679+
return libts.ints_to_pydatetime(self.asi8, self.tz, box="time")
16831680

16841681
@property
16851682
def date(self):

0 commit comments

Comments
 (0)