Skip to content

Commit 51599e7

Browse files
committed
API: Use lowest possible datetime64 resolution in PeriodIndex.to_timestamp
1 parent 1efb8c3 commit 51599e7

File tree

2 files changed

+60
-1
lines changed

2 files changed

+60
-1
lines changed

pandas/core/arrays/period.py

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -824,8 +824,27 @@ def to_timestamp(self, freq=None, how: str = "start") -> DatetimeArray:
824824

825825
new_parr = self.asfreq(freq, how=how)
826826

827+
# Map period frequency to appropriate datetime64 resolution
828+
freq_to_unit = {
829+
"A": "Y",
830+
"Y": "Y",
831+
"Q": "M",
832+
"M": "M",
833+
"W": "D",
834+
"D": "D",
835+
"H": "h",
836+
"T": "m",
837+
"S": "s",
838+
"L": "ms",
839+
"U": "us",
840+
"N": "ns",
841+
}
842+
rule_code = getattr(freq, "rule_code", None)
843+
unit = freq_to_unit.get(rule_code, "ns")
844+
dt64_dtype = np.dtype(f"datetime64[{unit}]")
845+
827846
new_data = libperiod.periodarr_to_dt64arr(new_parr.asi8, base)
828-
dta = DatetimeArray._from_sequence(new_data, dtype=np.dtype("M8[ns]"))
847+
dta = DatetimeArray._from_sequence(new_data, dtype=dt64_dtype)
829848

830849
if self.freq.name == "B":
831850
# See if we can retain BDay instead of Day in cases where

pandas/tests/indexes/period/test_period.py

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -231,3 +231,43 @@ def test_dunder_array(array):
231231
np.array(obj, dtype=dtype)
232232
with pytest.raises(TypeError, match=msg):
233233
np.array(obj, dtype=getattr(np, dtype))
234+
235+
236+
def test_to_timestamp_monthly_resolution():
237+
idx = PeriodIndex(["2011-01", "NaT", "2011-02"], freq="2M")
238+
ts = idx.to_timestamp()
239+
assert ts.dtype == np.dtype("datetime64[M]")
240+
241+
242+
def test_to_timestamp_yearly_resolution():
243+
idx = PeriodIndex(["2011", "2012"], freq="A")
244+
ts = idx.to_timestamp()
245+
assert ts.dtype == np.dtype("datetime64[Y]")
246+
247+
248+
def test_to_timestamp_large_month_no_out_of_bounds():
249+
idx = PeriodIndex(["May 3000"], freq="M")
250+
ts = idx.to_timestamp()
251+
assert ts.dtype == np.dtype("datetime64[M]")
252+
assert str(ts[0]) == "3000-05"
253+
254+
255+
def test_to_timestamp_large_year_no_out_of_bounds():
256+
idx = PeriodIndex(["3000"], freq="Y")
257+
ts = idx.to_timestamp()
258+
assert ts.dtype == np.dtype("datetime64[Y]")
259+
assert str(ts[0]) == "3000"
260+
261+
262+
def test_to_timestamp_daily_resolution():
263+
idx = PeriodIndex(["2011-01-01", "2011-01-02"], freq="D")
264+
ts = idx.to_timestamp()
265+
assert ts.dtype == np.dtype("datetime64[D]")
266+
267+
268+
def test_to_timestamp_nanosecond_resolution():
269+
idx = PeriodIndex(
270+
["2011-01-01 00:00:00.000000001", "2011-01-01 00:00:00.000000002"], freq="N"
271+
)
272+
ts = idx.to_timestamp()
273+
assert ts.dtype == np.dtype("datetime64[ns]")

0 commit comments

Comments
 (0)