text: """
  datetimelike delegation
  """
  from typing import TYPE_CHECKING
  
  import numpy as np
  
  from pandas.core.dtypes.common import (
      is_categorical_dtype,
      is_datetime64_dtype,
      is_datetime64tz_dtype,
      is_integer_dtype,
      is_list_like,
      is_period_dtype,
      is_timedelta64_dtype,
  )
  from pandas.core.dtypes.generic import ABCSeries
  
  from pandas.core.accessor import PandasDelegate, delegate_names
  from pandas.core.arrays import DatetimeArray, PeriodArray, TimedeltaArray
  from pandas.core.base import NoNewAttributesMixin, PandasObject
  from pandas.core.indexes.datetimes import DatetimeIndex
  from pandas.core.indexes.timedeltas import TimedeltaIndex
  
  if TYPE_CHECKING:
      from pandas import Series  # noqa:F401
  
  
  class Properties(PandasDelegate, PandasObject, NoNewAttributesMixin):
      def __init__(self, data: "Series", orig):
          if not isinstance(data, ABCSeries):
              raise TypeError(
                  f"cannot convert an object of type {type(data)} to a datetimelike index"
              )
  
          self._parent = data
          self.orig = orig
          self.name = getattr(data, "name", None)
          self._freeze()
  
      def _get_values(self):
          data = self._parent
          if is_datetime64_dtype(data.dtype):
              return DatetimeIndex(data, copy=False, name=self.name)
  
          elif is_datetime64tz_dtype(data.dtype):
              return DatetimeIndex(data, copy=False, name=self.name)
  
          elif is_timedelta64_dtype(data.dtype):
              return TimedeltaIndex(data, copy=False, name=self.name)
  
          elif is_period_dtype(data):
              return PeriodArray(data, copy=False)
  
          raise TypeError(
              f"cannot convert an object of type {type(data)} to a datetimelike index"
          )
  
      def _delegate_property_get(self, name):
          from pandas import Series
  
          values = self._get_values()
  
          result = getattr(values, name)
  
          # maybe need to upcast (ints)
          if isinstance(result, np.ndarray):
              if is_integer_dtype(result):
                  result = result.astype("int64")
          elif not is_list_like(result):
              return result
  
          result = np.asarray(result)
  
          if self.orig is not None:
              index = self.orig.index
          else:
              index = self._parent.index
          # return the result as a Series, which is by definition a copy
          result = Series(result, index=index, name=self.name)
  
          # setting this object will show a SettingWithCopyWarning/Error
          result._is_copy = (
              "modifications to a property of a datetimelike "
              "object are not supported and are discarded. "
              "Change values on the original."
          )
  
          return result
  
      def _delegate_property_set(self, name, value, *args, **kwargs):
          raise ValueError(
              "modifications to a property of a datetimelike object are not supported. "
              "Change values on the original."
          )
  
      def _delegate_method(self, name, *args, **kwargs):
          from pandas import Series
  
          values = self._get_values()
  
          method = getattr(values, name)
          result = method(*args, **kwargs)
  
          if not is_list_like(result):
              return result
  
          result = Series(result, index=self._parent.index, name=self.name)
  
          # setting this object will show a SettingWithCopyWarning/Error
          result._is_copy = (
              "modifications to a method of a datetimelike "
              "object are not supported and are discarded. "
              "Change values on the original."
          )
  
          return result
  
  
  @delegate_names(
      delegate=DatetimeArray, accessors=DatetimeArray._datetimelike_ops, typ="property"
  )
  @delegate_names(
      delegate=DatetimeArray, accessors=DatetimeArray._datetimelike_methods, typ="method"
  )
  class DatetimeProperties(Properties):
      """
      Accessor object for datetimelike properties of the Series values.
  
      Examples
      --------
      >>> seconds_series = pd.Series(pd.date_range("2000-01-01", periods=3, freq="s"))
      >>> seconds_series
      0   2000-01-01 00:00:00
      1   2000-01-01 00:00:01
      2   2000-01-01 00:00:02
      dtype: datetime64[ns]
      >>> seconds_series.dt.second
      0    0
      1    1
      2    2
      dtype: int64
  
      >>> hours_series = pd.Series(pd.date_range("2000-01-01", periods=3, freq="h"))
      >>> hours_series
      0   2000-01-01 00:00:00
      1   2000-01-01 01:00:00
      2   2000-01-01 02:00:00
      dtype: datetime64[ns]
      >>> hours_series.dt.hour
      0    0
      1    1
      2    2
      dtype: int64
  
      >>> quarters_series = pd.Series(pd.date_range("2000-01-01", periods=3, freq="q"))
      >>> quarters_series
      0   2000-03-31
      1   2000-06-30
      2   2000-09-30
      dtype: datetime64[ns]
      >>> quarters_series.dt.quarter
      0    1
      1    2
      2    3
      dtype: int64
  
      Returns a Series indexed like the original Series.
      Raises TypeError if the Series does not contain datetimelike values.
      """
  
      def to_pydatetime(self) -> np.ndarray:
          """
          Return the data as an array of native Python datetime objects.
  
          Timezone information is retained if present.
  
          .. warning::
  
             Python's datetime uses microsecond resolution, which is lower than
             pandas (nanosecond). The values are truncated.
  
          Returns
          -------
          numpy.ndarray
              Object dtype array containing native Python datetime objects.
  
          See Also
          --------
          datetime.datetime : Standard library value for a datetime.
  
          Examples
          --------
          >>> s = pd.Series(pd.date_range('20180310', periods=2))
          >>> s
          0   2018-03-10
          1   2018-03-11
          dtype: datetime64[ns]
  
          >>> s.dt.to_pydatetime()
          array([datetime.datetime(2018, 3, 10, 0, 0),
                 datetime.datetime(2018, 3, 11, 0, 0)], dtype=object)
  
          pandas' nanosecond precision is truncated to microseconds.
  
          >>> s = pd.Series(pd.date_range('20180310', periods=2, freq='ns'))
          >>> s
          0   2018-03-10 00:00:00.000000000
          1   2018-03-10 00:00:00.000000001
          dtype: datetime64[ns]
  
          >>> s.dt.to_pydatetime()
          array([datetime.datetime(2018, 3, 10, 0, 0),
                 datetime.datetime(2018, 3, 10, 0, 0)], dtype=object)
          """
          return self._get_values().to_pydatetime()
  
      @property
      def freq(self):
          return self._get_values().inferred_freq
  
  
  @delegate_names(
      delegate=TimedeltaArray, accessors=TimedeltaArray._datetimelike_ops, typ="property"
  )
  @delegate_names(
      delegate=TimedeltaArray,
      accessors=TimedeltaArray._datetimelike_methods,
      typ="method",
  )
  class TimedeltaProperties(Properties):
      """
      Accessor object for datetimelike properties of the Series values.
  
      Returns a Series indexed like the original Series.
      Raises TypeError if the Series does not contain datetimelike values.
  
      Examples
      --------
      >>> seconds_series = pd.Series(
      ...     pd.timedelta_range(start="1 second", periods=3, freq="S")
      ... )
      >>> seconds_series
      0   0 days 00:00:01
      1   0 days 00:00:02
      2   0 days 00:00:03
      dtype: timedelta64[ns]
      >>> seconds_series.dt.seconds
      0    1
      1    2
      2    3
      dtype: int64
      """
  
      def to_pytimedelta(self) -> np.ndarray:
          """
          Return an array of native `datetime.timedelta` objects.
  
          Python's standard `datetime` library uses a different representation
          timedelta's. This method converts a Series of pandas Timedeltas
          to `datetime.timedelta` format with the same length as the original
          Series.
  
          Returns
          -------
          numpy.ndarray
              Array of 1D containing data with `datetime.timedelta` type.
  
          See Also
          --------
          datetime.timedelta
  
          Examples
          --------
          >>> s = pd.Series(pd.to_timedelta(np.arange(5), unit="d"))
          >>> s
          0   0 days
          1   1 days
          2   2 days
          3   3 days
          4   4 days
          dtype: timedelta64[ns]
  
          >>> s.dt.to_pytimedelta()
          array([datetime.timedelta(0), datetime.timedelta(days=1),
          datetime.timedelta(days=2), datetime.timedelta(days=3),
          datetime.timedelta(days=4)], dtype=object)
          """
          return self._get_values().to_pytimedelta()
  
      @property
      def components(self):
          """
          Return a Dataframe of the components of the Timedeltas.
  
          Returns
          -------
          DataFrame
  
          Examples
          --------
          >>> s = pd.Series(pd.to_timedelta(np.arange(5), unit='s'))
          >>> s
          0   0 days 00:00:00
          1   0 days 00:00:01
          2   0 days 00:00:02
          3   0 days 00:00:03
          4   0 days 00:00:04
          dtype: timedelta64[ns]
          >>> s.dt.components
             days  hours  minutes  seconds  milliseconds  microseconds  nanoseconds
          0     0      0        0        0             0             0            0
          1     0      0        0        1             0             0            0
          2     0      0        0        2             0             0            0
          3     0      0        0        3             0             0            0
          4     0      0        0        4             0             0            0
          """
          return self._get_values().components.set_index(self._parent.index)
  
      @property
      def freq(self):
          return self._get_values().inferred_freq
  
  
  @delegate_names(
      delegate=PeriodArray, accessors=PeriodArray._datetimelike_ops, typ="property"
  )
  @delegate_names(
      delegate=PeriodArray, accessors=PeriodArray._datetimelike_methods, typ="method"
  )
  class PeriodProperties(Properties):
      """
      Accessor object for datetimelike properties of the Series values.
  
      Returns a Series indexed like the original Series.
      Raises TypeError if the Series does not contain datetimelike values.
  
      Examples
      --------
      >>> seconds_series = pd.Series(
      ...     pd.period_range(
      ...         start="2000-01-01 00:00:00", end="2000-01-01 00:00:03", freq="s"
      ...     )
      ... )
      >>> seconds_series
      0    2000-01-01 00:00:00
      1    2000-01-01 00:00:01
      2    2000-01-01 00:00:02
      3    2000-01-01 00:00:03
      dtype: period[S]
      >>> seconds_series.dt.second
      0    0
      1    1
      2    2
      3    3
      dtype: int64
  
      >>> hours_series = pd.Series(
      ...     pd.period_range(start="2000-01-01 00:00", end="2000-01-01 03:00", freq="h")
      ... )
      >>> hours_series
      0    2000-01-01 00:00
      1    2000-01-01 01:00
      2    2000-01-01 02:00
      3    2000-01-01 03:00
      dtype: period[H]
      >>> hours_series.dt.hour
      0    0
      1    1
      2    2
      3    3
      dtype: int64
  
      >>> quarters_series = pd.Series(
      ...     pd.period_range(start="2000-01-01", end="2000-12-31", freq="Q-DEC")
      ... )
      >>> quarters_series
      0    2000Q1
      1    2000Q2
      2    2000Q3
      3    2000Q4
      dtype: period[Q-DEC]
      >>> quarters_series.dt.quarter
      0    1
      1    2
      2    3
      3    4
      dtype: int64
      """
  
  
  class CombinedDatetimelikeProperties(
      DatetimeProperties, TimedeltaProperties, PeriodProperties
  ):
      def __new__(cls, data: "Series"):
          # CombinedDatetimelikeProperties isn't really instantiated. Instead
          # we need to choose which parent (datetime or timedelta) is
          # appropriate. Since we're checking the dtypes anyway, we'll just
          # do all the validation here.
          from pandas import Series
  
          if not isinstance(data, ABCSeries):
              raise TypeError(
                  f"cannot convert an object of type {type(data)} to a datetimelike index"
              )
  
          orig = data if is_categorical_dtype(data) else None
          if orig is not None:
              data = Series(
                  orig.array,
                  name=orig.name,
                  copy=False,
                  dtype=orig._values.categories.dtype,
              )
  
          if is_datetime64_dtype(data.dtype):
              return DatetimeProperties(data, orig)
          elif is_datetime64tz_dtype(data.dtype):
              return DatetimeProperties(data, orig)
          elif is_timedelta64_dtype(data.dtype):
              return TimedeltaProperties(data, orig)
          elif is_period_dtype(data):
              return PeriodProperties(data, orig)
  
          raise AttributeError("Can only use .dt accessor with datetimelike values")
  