Skip to content

Commit 2428cdd

Browse files
authored
BUG: Period.to_timestamp not matching PeriodArray.to_timestamp (pandas-dev#34449)
1 parent 25cdc24 commit 2428cdd

File tree

4 files changed

+34
-7
lines changed

4 files changed

+34
-7
lines changed

pandas/_libs/tslibs/period.pyx

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1702,10 +1702,7 @@ cdef class _Period:
17021702

17031703
@property
17041704
def end_time(self) -> Timestamp:
1705-
# freq.n can't be negative or 0
1706-
# ordinal = (self + self.freq.n).start_time.value - 1
1707-
ordinal = (self + self.freq).start_time.value - 1
1708-
return Timestamp(ordinal)
1705+
return self.to_timestamp(how="end")
17091706

17101707
def to_timestamp(self, freq=None, how='start', tz=None) -> Timestamp:
17111708
"""
@@ -1727,18 +1724,22 @@ cdef class _Period:
17271724
-------
17281725
Timestamp
17291726
"""
1730-
if freq is not None:
1731-
freq = self._maybe_convert_freq(freq)
17321727
how = validate_end_alias(how)
17331728

17341729
end = how == 'E'
17351730
if end:
1731+
if freq == "B" or self.freq == "B":
1732+
# roll forward to ensure we land on B date
1733+
adjust = Timedelta(1, "D") - Timedelta(1, "ns")
1734+
return self.to_timestamp(how="start") + adjust
17361735
endpoint = (self + self.freq).to_timestamp(how='start')
17371736
return endpoint - Timedelta(1, 'ns')
17381737

17391738
if freq is None:
17401739
base, mult = get_freq_code(self.freq)
17411740
freq = get_to_timestamp_base(base)
1741+
else:
1742+
freq = self._maybe_convert_freq(freq)
17421743

17431744
base, mult = get_freq_code(freq)
17441745
val = self.asfreq(freq, how)

pandas/core/arrays/period.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -430,7 +430,7 @@ def to_timestamp(self, freq=None, how="start"):
430430

431431
end = how == "E"
432432
if end:
433-
if freq == "B":
433+
if freq == "B" or self.freq == "B":
434434
# roll forward to ensure we land on B date
435435
adjust = Timedelta(1, "D") - Timedelta(1, "ns")
436436
return self.to_timestamp(how="start") + adjust

pandas/tests/indexes/period/test_scalar_compat.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,3 +17,12 @@ def test_end_time(self):
1717
expected_index = date_range("2016-01-01", end="2016-05-31", freq="M")
1818
expected_index += Timedelta(1, "D") - Timedelta(1, "ns")
1919
tm.assert_index_equal(index.end_time, expected_index)
20+
21+
def test_end_time_business_friday(self):
22+
# GH#34449
23+
pi = period_range("1990-01-05", freq="B", periods=1)
24+
result = pi.end_time
25+
26+
dti = date_range("1990-01-05", freq="D", periods=1)._with_freq(None)
27+
expected = dti + Timedelta(days=1, nanoseconds=-1)
28+
tm.assert_index_equal(result, expected)

pandas/tests/scalar/period/test_period.py

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -589,6 +589,8 @@ def test_to_timestamp(self):
589589
from_lst = ["A", "Q", "M", "W", "B", "D", "H", "Min", "S"]
590590

591591
def _ex(p):
592+
if p.freq == "B":
593+
return p.start_time + Timedelta(days=1, nanoseconds=-1)
592594
return Timestamp((p + p.freq).start_time.value - 1)
593595

594596
for i, fcode in enumerate(from_lst):
@@ -632,6 +634,13 @@ def _ex(p):
632634
result = p.to_timestamp("5S", how="start")
633635
assert result == expected
634636

637+
def test_to_timestamp_business_end(self):
638+
per = pd.Period("1990-01-05", "B") # Friday
639+
result = per.to_timestamp("B", how="E")
640+
641+
expected = pd.Timestamp("1990-01-06") - pd.Timedelta(nanoseconds=1)
642+
assert result == expected
643+
635644
# --------------------------------------------------------------
636645
# Rendering: __repr__, strftime, etc
637646

@@ -786,6 +795,14 @@ def _ex(*args):
786795
xp = _ex(2012, 1, 2, 1)
787796
assert xp == p.end_time
788797

798+
def test_end_time_business_friday(self):
799+
# GH#34449
800+
per = Period("1990-01-05", "B")
801+
result = per.end_time
802+
803+
expected = pd.Timestamp("1990-01-06") - pd.Timedelta(nanoseconds=1)
804+
assert result == expected
805+
789806
def test_anchor_week_end_time(self):
790807
def _ex(*args):
791808
return Timestamp(Timestamp(datetime(*args)).value - 1)

0 commit comments

Comments
 (0)