@@ -1489,6 +1489,60 @@ cdef class PeriodMixin:
1489
1489
return FR_SEC
1490
1490
return base
1491
1491
1492
+ @property
1493
+ def start_time (self ) -> Timestamp:
1494
+ """
1495
+ Get the Timestamp for the start of the period.
1496
+
1497
+ Returns
1498
+ -------
1499
+ Timestamp
1500
+
1501
+ See Also
1502
+ --------
1503
+ Period.end_time : Return the end Timestamp.
1504
+ Period.dayofyear : Return the day of year.
1505
+ Period.daysinmonth : Return the days in that month.
1506
+ Period.dayofweek : Return the day of the week.
1507
+
1508
+ Examples
1509
+ --------
1510
+ >>> period = pd.Period(' 2012-1-1' , freq = ' D' )
1511
+ >>> period
1512
+ Period('2012-01-01', 'D')
1513
+
1514
+ >>> period.start_time
1515
+ Timestamp('2012-01-01 00:00:00')
1516
+
1517
+ >>> period.end_time
1518
+ Timestamp('2012-01-01 23:59:59.999999999')
1519
+ """
1520
+ return self.to_timestamp(how = " start" )
1521
+
1522
+ @property
1523
+ def end_time(self ) -> Timestamp:
1524
+ return self.to_timestamp(how = " end" )
1525
+
1526
+ def _require_matching_freq(self , other , base = False ):
1527
+ # See also arrays.period.raise_on_incompatible
1528
+ if is_offset_object(other):
1529
+ other_freq = other
1530
+ else :
1531
+ other_freq = other.freq
1532
+
1533
+ if base:
1534
+ condition = self .freq.base != other_freq.base
1535
+ else :
1536
+ condition = self .freq != other_freq
1537
+
1538
+ if condition:
1539
+ msg = DIFFERENT_FREQ.format(
1540
+ cls = type (self ).__name__,
1541
+ own_freq = self .freqstr,
1542
+ other_freq = other_freq.freqstr,
1543
+ )
1544
+ raise IncompatibleFrequency(msg)
1545
+
1492
1546
1493
1547
cdef class _Period(PeriodMixin):
1494
1548
@@ -1551,10 +1605,7 @@ cdef class _Period(PeriodMixin):
1551
1605
return False
1552
1606
elif op == Py_NE:
1553
1607
return True
1554
- msg = DIFFERENT_FREQ.format(cls = type (self ).__name__,
1555
- own_freq = self .freqstr,
1556
- other_freq = other.freqstr)
1557
- raise IncompatibleFrequency(msg)
1608
+ self ._require_matching_freq(other)
1558
1609
return PyObject_RichCompareBool(self .ordinal, other.ordinal, op)
1559
1610
elif other is NaT:
1560
1611
return _nat_scalar_rules[op]
@@ -1563,15 +1614,15 @@ cdef class _Period(PeriodMixin):
1563
1614
def __hash__ (self ):
1564
1615
return hash ((self .ordinal, self .freqstr))
1565
1616
1566
- def _add_delta (self , other ) -> "Period":
1617
+ def _add_timedeltalike_scalar (self , other ) -> "Period":
1567
1618
cdef:
1568
- int64_t nanos , offset_nanos
1619
+ int64_t nanos , base_nanos
1569
1620
1570
1621
if is_tick_object(self.freq ):
1571
1622
nanos = delta_to_nanoseconds(other)
1572
- offset_nanos = self .freq.base.nanos
1573
- if nanos % offset_nanos == 0 :
1574
- ordinal = self .ordinal + (nanos // offset_nanos )
1623
+ base_nanos = self .freq.base.nanos
1624
+ if nanos % base_nanos == 0 :
1625
+ ordinal = self .ordinal + (nanos // base_nanos )
1575
1626
return Period(ordinal = ordinal, freq = self .freq)
1576
1627
raise IncompatibleFrequency(" Input cannot be converted to "
1577
1628
f" Period(freq={self.freqstr})" )
@@ -1581,14 +1632,10 @@ cdef class _Period(PeriodMixin):
1581
1632
cdef:
1582
1633
int64_t ordinal
1583
1634
1584
- if other.base == self.freq.base:
1585
- ordinal = self .ordinal + other.n
1586
- return Period(ordinal = ordinal, freq = self .freq)
1635
+ self._require_matching_freq(other , base = True )
1587
1636
1588
- msg = DIFFERENT_FREQ.format(cls = type (self ).__name__,
1589
- own_freq = self .freqstr,
1590
- other_freq = other.freqstr)
1591
- raise IncompatibleFrequency(msg )
1637
+ ordinal = self .ordinal + other.n
1638
+ return Period(ordinal = ordinal, freq = self .freq)
1592
1639
1593
1640
def __add__(self , other ):
1594
1641
if not is_period_object(self ):
@@ -1598,7 +1645,7 @@ cdef class _Period(PeriodMixin):
1598
1645
return other.__add__ (self )
1599
1646
1600
1647
if is_any_td_scalar(other):
1601
- return self ._add_delta (other)
1648
+ return self ._add_timedeltalike_scalar (other)
1602
1649
elif is_offset_object(other):
1603
1650
return self ._add_offset(other)
1604
1651
elif other is NaT:
@@ -1635,11 +1682,7 @@ cdef class _Period(PeriodMixin):
1635
1682
ordinal = self .ordinal - other * self .freq.n
1636
1683
return Period(ordinal = ordinal, freq = self .freq)
1637
1684
elif is_period_object(other):
1638
- if other.freq != self .freq:
1639
- msg = DIFFERENT_FREQ.format(cls = type (self ).__name__,
1640
- own_freq = self .freqstr,
1641
- other_freq = other.freqstr)
1642
- raise IncompatibleFrequency(msg)
1685
+ self ._require_matching_freq(other)
1643
1686
# GH 23915 - mul by base freq since __add__ is agnostic of n
1644
1687
return (self .ordinal - other.ordinal) * self .freq.base
1645
1688
elif other is NaT:
@@ -1677,40 +1720,6 @@ cdef class _Period(PeriodMixin):
1677
1720
1678
1721
return Period(ordinal = ordinal, freq = freq)
1679
1722
1680
- @property
1681
- def start_time(self ) -> Timestamp:
1682
- """
1683
- Get the Timestamp for the start of the period.
1684
-
1685
- Returns
1686
- -------
1687
- Timestamp
1688
-
1689
- See Also
1690
- --------
1691
- Period.end_time : Return the end Timestamp.
1692
- Period.dayofyear : Return the day of year.
1693
- Period.daysinmonth : Return the days in that month.
1694
- Period.dayofweek : Return the day of the week.
1695
-
1696
- Examples
1697
- --------
1698
- >>> period = pd.Period(' 2012-1-1' , freq = ' D' )
1699
- >>> period
1700
- Period('2012-01-01', 'D')
1701
-
1702
- >>> period.start_time
1703
- Timestamp('2012-01-01 00:00:00')
1704
-
1705
- >>> period.end_time
1706
- Timestamp('2012-01-01 23:59:59.999999999')
1707
- """
1708
- return self.to_timestamp(how = ' S' )
1709
-
1710
- @property
1711
- def end_time(self ) -> Timestamp:
1712
- return self.to_timestamp(how = " end" )
1713
-
1714
1723
def to_timestamp(self , freq = None , how = ' start' , tz = None ) -> Timestamp:
1715
1724
"""
1716
1725
Return the Timestamp representation of the Period.
0 commit comments