Skip to content
Merged
38 changes: 37 additions & 1 deletion asv_bench/benchmarks/tslibs/period.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,15 @@
Period benchmarks that rely only on tslibs. See benchmarks.period for
Period benchmarks that rely on other parts fo pandas.
"""
from pandas import Period

import numpy as np

from pandas._libs.tslibs.period import Period, periodarr_to_dt64arr

from pandas.tseries.frequencies import to_offset

from .tslib import _sizes


class PeriodProperties:

Expand Down Expand Up @@ -68,3 +73,34 @@ def setup(self, freq, is_offset):

def time_period_constructor(self, freq, is_offset):
Period("2012-06-01", freq=freq)


class TimePeriodArrToDT64Arr:
params = [
_sizes,
[
1000,
1011, # Annual - November End
2000,
2011, # Quarterly - November End
3000,
4000,
4006, # Weekly - Saturday End
5000,
6000,
7000,
8000,
9000,
10000,
11000,
12000,
],
]
param_names = ["size", "freq"]

def setup(self, size, freq):
arr = np.arange(10, dtype="i8").repeat(size // 10)
self.i8values = arr

def time_periodarray_to_dt64arr(self, size, freq):
periodarr_to_dt64arr(self.i8values, freq)
31 changes: 26 additions & 5 deletions pandas/_libs/tslibs/period.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ from pandas._libs.tslibs.ccalendar cimport (
get_days_in_month,
)
from pandas._libs.tslibs.ccalendar cimport c_MONTH_NUMBERS
from pandas._libs.tslibs.conversion import ensure_datetime64ns

from pandas._libs.tslibs.dtypes cimport (
PeriodDtypeBase,
Expand Down Expand Up @@ -946,14 +947,34 @@ def periodarr_to_dt64arr(const int64_t[:] periodarr, int freq):
int64_t[:] out
Py_ssize_t i, l

l = len(periodarr)
if freq < 6000: # i.e. FR_DAY, hard-code to avoid need to cast
l = len(periodarr)
out = np.empty(l, dtype="i8")

out = np.empty(l, dtype='i8')
# We get here with freqs that do not correspond to a datetime64 unit
for i in range(l):
out[i] = period_ordinal_to_dt64(periodarr[i], freq)

for i in range(l):
out[i] = period_ordinal_to_dt64(periodarr[i], freq)
return out.base # .base to access underlying np.ndarray

return out.base # .base to access underlying np.ndarray
else:
# Short-circuit for performance
if freq == FR_NS:
return periodarr.base

if freq == FR_US:
dta = periodarr.base.view("M8[us]")
elif freq == FR_MS:
dta = periodarr.base.view("M8[ms]")
elif freq == FR_SEC:
dta = periodarr.base.view("M8[s]")
elif freq == FR_MIN:
dta = periodarr.base.view("M8[m]")
elif freq == FR_HR:
dta = periodarr.base.view("M8[h]")
elif freq == FR_DAY:
dta = periodarr.base.view("M8[D]")
return ensure_datetime64ns(dta)


cpdef int64_t period_asfreq(int64_t ordinal, int freq1, int freq2, bint end):
Expand Down