Skip to content

PERF: put some Timetamp methods in _Timestamp #35036

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jun 30, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions pandas/_libs/tslibs/timestamps.pxd
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@ cdef class _Timestamp(ABCTimestamp):
int64_t value, nanosecond
object freq

cpdef bint _get_start_end_field(self, str field)
cpdef _get_date_name_field(self, object field, object locale)
cdef bint _get_start_end_field(self, str field)
cdef _get_date_name_field(self, str field, object locale)
cdef int64_t _maybe_convert_value_to_local(self)
cpdef to_datetime64(self)
cdef _assert_tzawareness_compat(_Timestamp self, datetime other)
Expand Down
291 changes: 149 additions & 142 deletions pandas/_libs/tslibs/timestamps.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -441,6 +441,8 @@ cdef class _Timestamp(ABCTimestamp):

return NotImplemented

# -----------------------------------------------------------------

cdef int64_t _maybe_convert_value_to_local(self):
"""Convert UTC i8 value to local i8 value if tz exists"""
cdef:
Expand All @@ -450,7 +452,7 @@ cdef class _Timestamp(ABCTimestamp):
val = tz_convert_single(self.value, UTC, self.tz)
return val

cpdef bint _get_start_end_field(self, str field):
cdef bint _get_start_end_field(self, str field):
cdef:
int64_t val
dict kwds
Expand All @@ -471,7 +473,67 @@ cdef class _Timestamp(ABCTimestamp):
field, freqstr, month_kw)
return out[0]

cpdef _get_date_name_field(self, object field, object locale):
@property
def is_month_start(self) -> bool:
"""
Return True if date is first day of month.
"""
if self.freq is None:
# fast-path for non-business frequencies
return self.day == 1
return self._get_start_end_field("is_month_start")

@property
def is_month_end(self) -> bool:
"""
Return True if date is last day of month.
"""
if self.freq is None:
# fast-path for non-business frequencies
return self.day == self.days_in_month
return self._get_start_end_field("is_month_end")

@property
def is_quarter_start(self) -> bool:
"""
Return True if date is first day of the quarter.
"""
if self.freq is None:
# fast-path for non-business frequencies
return self.day == 1 and self.month % 3 == 1
return self._get_start_end_field("is_quarter_start")

@property
def is_quarter_end(self) -> bool:
"""
Return True if date is last day of the quarter.
"""
if self.freq is None:
# fast-path for non-business frequencies
return (self.month % 3) == 0 and self.day == self.days_in_month
return self._get_start_end_field("is_quarter_end")

@property
def is_year_start(self) -> bool:
"""
Return True if date is first day of the year.
"""
if self.freq is None:
# fast-path for non-business frequencies
return self.day == self.month == 1
return self._get_start_end_field("is_year_start")

@property
def is_year_end(self) -> bool:
"""
Return True if date is last day of the year.
"""
if self.freq is None:
# fast-path for non-business frequencies
return self.month == 12 and self.day == 31
return self._get_start_end_field("is_year_end")

cdef _get_date_name_field(self, str field, object locale):
cdef:
int64_t val
object[:] out
Expand All @@ -481,6 +543,85 @@ cdef class _Timestamp(ABCTimestamp):
field, locale=locale)
return out[0]

def day_name(self, locale=None) -> str:
"""
Return the day name of the Timestamp with specified locale.

Parameters
----------
locale : str, default None (English locale)
Locale determining the language in which to return the day name.

Returns
-------
day_name : string

.. versionadded:: 0.23.0
"""
return self._get_date_name_field("day_name", locale)

def month_name(self, locale=None) -> str:
"""
Return the month name of the Timestamp with specified locale.

Parameters
----------
locale : str, default None (English locale)
Locale determining the language in which to return the month name.

Returns
-------
month_name : string

.. versionadded:: 0.23.0
"""
return self._get_date_name_field("month_name", locale)

@property
def is_leap_year(self) -> bool:
"""
Return True if year is a leap year.
"""
return bool(ccalendar.is_leapyear(self.year))

@property
def dayofweek(self) -> int:
"""
Return day of the week.
"""
return self.weekday()

@property
def dayofyear(self) -> int:
"""
Return the day of the year.
"""
return ccalendar.get_day_of_year(self.year, self.month, self.day)

@property
def quarter(self) -> int:
"""
Return the quarter of the year.
"""
return ((self.month - 1) // 3) + 1

@property
def week(self) -> int:
"""
Return the week number of the year.
"""
return ccalendar.get_week_of_year(self.year, self.month, self.day)

@property
def days_in_month(self) -> int:
"""
Return the number of days in the month.
"""
return ccalendar.get_days_in_month(self.year, self.month)

# -----------------------------------------------------------------
# Rendering Methods

@property
def _repr_base(self) -> str:
return f"{self._date_repr} {self._time_repr}"
Expand Down Expand Up @@ -514,6 +655,8 @@ cdef class _Timestamp(ABCTimestamp):
return self._date_repr
return self._repr_base

# -----------------------------------------------------------------

@property
def asm8(self) -> np.datetime64:
"""
Expand Down Expand Up @@ -1040,153 +1183,13 @@ timedelta}, default 'raise'

return Period(self, freq=freq)

@property
def dayofweek(self) -> int:
"""
Return day of the week.
"""
return self.weekday()

def day_name(self, locale=None) -> str:
"""
Return the day name of the Timestamp with specified locale.

Parameters
----------
locale : str, default None (English locale)
Locale determining the language in which to return the day name.

Returns
-------
day_name : string

.. versionadded:: 0.23.0
"""
return self._get_date_name_field('day_name', locale)

def month_name(self, locale=None) -> str:
"""
Return the month name of the Timestamp with specified locale.

Parameters
----------
locale : str, default None (English locale)
Locale determining the language in which to return the month name.

Returns
-------
month_name : string

.. versionadded:: 0.23.0
"""
return self._get_date_name_field('month_name', locale)

@property
def dayofyear(self) -> int:
"""
Return the day of the year.
"""
return ccalendar.get_day_of_year(self.year, self.month, self.day)

@property
def week(self) -> int:
"""
Return the week number of the year.
"""
return ccalendar.get_week_of_year(self.year, self.month, self.day)

weekofyear = week

@property
def quarter(self) -> int:
"""
Return the quarter of the year.
"""
return ((self.month - 1) // 3) + 1

@property
def days_in_month(self) -> int:
"""
Return the number of days in the month.
"""
return ccalendar.get_days_in_month(self.year, self.month)

daysinmonth = days_in_month

@property
def freqstr(self):
"""
Return the total number of days in the month.
"""
return getattr(self.freq, 'freqstr', self.freq)

@property
def is_month_start(self) -> bool:
"""
Return True if date is first day of month.
"""
if self.freq is None:
# fast-path for non-business frequencies
return self.day == 1
return self._get_start_end_field('is_month_start')

@property
def is_month_end(self) -> bool:
"""
Return True if date is last day of month.
"""
if self.freq is None:
# fast-path for non-business frequencies
return self.day == self.days_in_month
return self._get_start_end_field('is_month_end')

@property
def is_quarter_start(self) -> bool:
"""
Return True if date is first day of the quarter.
"""
if self.freq is None:
# fast-path for non-business frequencies
return self.day == 1 and self.month % 3 == 1
return self._get_start_end_field('is_quarter_start')

@property
def is_quarter_end(self) -> bool:
"""
Return True if date is last day of the quarter.
"""
if self.freq is None:
# fast-path for non-business frequencies
return (self.month % 3) == 0 and self.day == self.days_in_month
return self._get_start_end_field('is_quarter_end')

@property
def is_year_start(self) -> bool:
"""
Return True if date is first day of the year.
"""
if self.freq is None:
# fast-path for non-business frequencies
return self.day == self.month == 1
return self._get_start_end_field('is_year_start')

@property
def is_year_end(self) -> bool:
"""
Return True if date is last day of the year.
"""
if self.freq is None:
# fast-path for non-business frequencies
return self.month == 12 and self.day == 31
return self._get_start_end_field('is_year_end')

@property
def is_leap_year(self) -> bool:
"""
Return True if year is a leap year.
"""
return bool(ccalendar.is_leapyear(self.year))

def tz_localize(self, tz, ambiguous='raise', nonexistent='raise'):
"""
Convert naive Timestamp to local time zone, or remove
Expand Down Expand Up @@ -1456,6 +1459,10 @@ default 'raise'
return Timestamp(normalized[0]).tz_localize(own_tz)


# Aliases
Timestamp.weekofyear = Timestamp.week
Timestamp.daysinmonth = Timestamp.days_in_month

# Add the min and max fields at the class level
cdef int64_t _NS_UPPER_BOUND = np.iinfo(np.int64).max
# the smallest value we could actually represent is
Expand Down