diff --git a/pandas-stubs/core/indexes/accessors.pyi b/pandas-stubs/core/indexes/accessors.pyi index faccf0b5c..3f8a7c768 100644 --- a/pandas-stubs/core/indexes/accessors.pyi +++ b/pandas-stubs/core/indexes/accessors.pyi @@ -1,11 +1,17 @@ import datetime as dt from datetime import tzinfo -from typing import Literal +from typing import ( + Generic, + Literal, + TypeVar, +) import numpy as np import numpy.typing as npt from pandas import ( - Period, + DatetimeIndex, + Index, + PeriodIndex, Timedelta, ) from pandas.core.accessor import PandasDelegate @@ -18,8 +24,11 @@ from pandas.core.base import ( PandasObject, ) from pandas.core.frame import DataFrame +from pandas.core.indexes.numeric import IntegerIndex from pandas.core.series import ( + PeriodSeries, Series, + TimedeltaSeries, TimestampSeries, ) from pytz.tzinfo import BaseTzInfo @@ -31,111 +40,242 @@ from pandas._typing import np_ndarray_bool class Properties(PandasDelegate, PandasObject, NoNewAttributesMixin): def __init__(self, data: Series, orig) -> None: ... -class DatetimeAndPeriodProperties(Properties): - # Common ones are here - @property - def year(self) -> Series[int]: ... - @property - def month(self) -> Series[int]: ... +_DTFieldOpsReturnType = TypeVar("_DTFieldOpsReturnType", Series[int], IntegerIndex) + +class _DatetimeFieldOps(Generic[_DTFieldOpsReturnType]): @property - def day(self) -> Series[int]: ... + def year(self) -> _DTFieldOpsReturnType: ... @property - def hour(self) -> Series[int]: ... + def month(self) -> _DTFieldOpsReturnType: ... @property - def minute(self) -> Series[int]: ... + def day(self) -> _DTFieldOpsReturnType: ... @property - def second(self) -> Series[int]: ... + def hour(self) -> _DTFieldOpsReturnType: ... @property - def weekday(self) -> Series[int]: ... + def minute(self) -> _DTFieldOpsReturnType: ... @property - def dayofweek(self) -> Series[int]: ... + def second(self) -> _DTFieldOpsReturnType: ... @property - def day_of_week(self) -> Series[int]: ... + def weekday(self) -> _DTFieldOpsReturnType: ... @property - def dayofyear(self) -> Series[int]: ... + def dayofweek(self) -> _DTFieldOpsReturnType: ... @property - def day_of_year(self) -> Series[int]: ... + def day_of_week(self) -> _DTFieldOpsReturnType: ... @property - def quarter(self) -> Series[int]: ... + def dayofyear(self) -> _DTFieldOpsReturnType: ... @property - def days_in_month(self) -> Series[int]: ... + def day_of_year(self) -> _DTFieldOpsReturnType: ... @property - def daysinmonth(self) -> Series[int]: ... + def quarter(self) -> _DTFieldOpsReturnType: ... @property - def microsecond(self) -> Series[int]: ... + def days_in_month(self) -> _DTFieldOpsReturnType: ... @property - def nanosecond(self) -> Series[int]: ... + def daysinmonth(self) -> _DTFieldOpsReturnType: ... @property - def is_leap_year(self) -> Series[bool]: ... + def microsecond(self) -> _DTFieldOpsReturnType: ... @property - def freq(self) -> str | None: ... + def nanosecond(self) -> _DTFieldOpsReturnType: ... -class DatetimeProperties(DatetimeAndPeriodProperties): - def to_pydatetime(self) -> np.ndarray: ... - def isocalendar(self) -> DataFrame: ... +_DTBoolOpsReturnType = TypeVar("_DTBoolOpsReturnType", "Series[bool]", np_ndarray_bool) + +class _IsLeapYearProperty(Generic[_DTBoolOpsReturnType]): @property - def weekofyear(self) -> Series[int]: ... + def is_leap_year(self) -> _DTBoolOpsReturnType: ... + +class _DatetimeBoolOps( + _IsLeapYearProperty[_DTBoolOpsReturnType], Generic[_DTBoolOpsReturnType] +): @property - def week(self) -> Series[int]: ... + def is_month_start(self) -> _DTBoolOpsReturnType: ... @property - def is_month_start(self) -> Series[bool]: ... + def is_month_end(self) -> _DTBoolOpsReturnType: ... @property - def is_month_end(self) -> Series[bool]: ... + def is_quarter_start(self) -> _DTBoolOpsReturnType: ... @property - def is_quarter_start(self) -> Series[bool]: ... + def is_quarter_end(self) -> _DTBoolOpsReturnType: ... @property - def is_quarter_end(self) -> Series[bool]: ... + def is_year_start(self) -> _DTBoolOpsReturnType: ... @property - def is_year_start(self) -> Series[bool]: ... + def is_year_end(self) -> _DTBoolOpsReturnType: ... + +_DTFreqReturnType = TypeVar("_DTFreqReturnType", str, BaseOffset) + +class _FreqProperty(Generic[_DTFreqReturnType]): @property - def is_year_end(self) -> Series[bool]: ... + def freq(self) -> _DTFreqReturnType | None: ... + +class _TZProperty: @property def tz(self) -> tzinfo | BaseTzInfo | None: ... + +class _DatetimeObjectOps( + _FreqProperty[_DTFreqReturnType], _TZProperty, Generic[_DTFreqReturnType] +): ... + +_DTOtherOpsDateReturnType = TypeVar( + "_DTOtherOpsDateReturnType", Series[dt.date], np.ndarray +) +_DTOtherOpsTimeReturnType = TypeVar( + "_DTOtherOpsTimeReturnType", Series[dt.time], np.ndarray +) + +class _DatetimeOtherOps(Generic[_DTOtherOpsDateReturnType, _DTOtherOpsTimeReturnType]): @property - def date(self) -> Series[dt.date]: ... + def date(self) -> _DTOtherOpsDateReturnType: ... @property - def time(self) -> Series[dt.time]: ... + def time(self) -> _DTOtherOpsTimeReturnType: ... @property - def timetz(self) -> Series[dt.time]: ... - def to_period(self, freq: str | BaseOffset | None = ...) -> Series[Period]: ... - def tz_localize( - self, - tz: str | None, - ambiguous: Literal["raise", "infer", "NaT"] | np_ndarray_bool = ..., - nonexistent: Literal["shift_forward", "shift_backward", "NaT", "raise"] - | Timedelta = ..., - ) -> DatetimeArray: ... - def tz_convert(self, tz: str | None) -> TimestampSeries: ... - def normalize(self) -> TimestampSeries: ... - def strftime(self, date_format: str) -> Series[str]: ... - # Ideally, the next 3 methods would return TimestampSeries, but because of - # how Series.dt is hooked in, we don't know which kind of series was passed - # in to the dt accessor + def timetz(self) -> _DTOtherOpsTimeReturnType: ... + +class DatetimeAndPeriodProperties(_DatetimeFieldOps[Series[int]]): ... +class _DatetimeLikeOps( + _DatetimeFieldOps[_DTFieldOpsReturnType], + _DatetimeObjectOps[_DTFreqReturnType], + _DatetimeBoolOps[_DTBoolOpsReturnType], + _DatetimeOtherOps[_DTOtherOpsDateReturnType, _DTOtherOpsTimeReturnType], + Generic[ + _DTFieldOpsReturnType, + _DTBoolOpsReturnType, + _DTOtherOpsDateReturnType, + _DTOtherOpsTimeReturnType, + _DTFreqReturnType, + ], +): ... + +# Ideally, the rounding methods would return TimestampSeries when `Series.dt.method` +# is invoked, but because of how Series.dt is hooked in and that we may not know the +# type of the series, we don't know which kind of series was ...ed +# in to the dt accessor + +_DTRoundingMethodReturnType = TypeVar( + "_DTRoundingMethodReturnType", + Series, + TimedeltaSeries, + TimestampSeries, + DatetimeIndex, +) + +class _DatetimeRoundingMethods(Generic[_DTRoundingMethodReturnType]): def round( self, freq: str | BaseOffset | None, ambiguous: Literal["raise", "infer", "NaT"] | np_ndarray_bool = ..., nonexistent: Literal["shift_forward", "shift_backward", "NaT", "raise"] | Timedelta = ..., - ) -> Series: ... + ) -> _DTRoundingMethodReturnType: ... def floor( self, freq: str | BaseOffset | None, ambiguous: Literal["raise", "infer", "NaT"] | np_ndarray_bool = ..., nonexistent: Literal["shift_forward", "shift_backward", "NaT", "raise"] | Timedelta = ..., - ) -> Series: ... + ) -> _DTRoundingMethodReturnType: ... def ceil( self, freq: str | BaseOffset | None, ambiguous: Literal["raise", "infer", "NaT"] | np_ndarray_bool = ..., nonexistent: Literal["shift_forward", "shift_backward", "NaT", "raise"] | Timedelta = ..., - ) -> Series: ... - def month_name(self, locale: str | None = ...) -> Series[str]: ... - def day_name(self, locale: str | None = ...) -> Series[str]: ... + ) -> _DTRoundingMethodReturnType: ... + +class _TZConversionMethods: + def tz_localize( + self, + tz: str | None, + ambiguous: Literal["raise", "infer", "NaT"] | np_ndarray_bool = ..., + nonexistent: Literal["shift_forward", "shift_backward", "NaT", "raise"] + | Timedelta = ..., + ) -> DatetimeArray: ... + def tz_convert(self, tz: str | None) -> TimestampSeries: ... + +_DTNormalizeReturnType = TypeVar( + "_DTNormalizeReturnType", TimestampSeries, DatetimeIndex +) +_DTStrKindReturnType = TypeVar("_DTStrKindReturnType", Series[str], Index) +_DTToPeriodReturnType = TypeVar("_DTToPeriodReturnType", PeriodSeries, PeriodIndex) + +class _DatetimeLikeNoTZMethods( + _DatetimeRoundingMethods[_DTRoundingMethodReturnType], + Generic[ + _DTRoundingMethodReturnType, + _DTNormalizeReturnType, + _DTStrKindReturnType, + _DTToPeriodReturnType, + ], +): + def to_period( + self, freq: str | BaseOffset | None = ... + ) -> _DTToPeriodReturnType: ... + def tz_localize( + self, + tz: str | None, + ambiguous: Literal["raise", "infer", "NaT"] | np_ndarray_bool = ..., + nonexistent: Literal["shift_forward", "shift_backward", "NaT", "raise"] + | Timedelta = ..., + ) -> DatetimeArray: ... + def tz_convert(self, tz: str | None) -> TimestampSeries: ... + def normalize(self) -> _DTNormalizeReturnType: ... + def strftime(self, date_format: str) -> _DTStrKindReturnType: ... + def month_name(self, locale: str | None = ...) -> _DTStrKindReturnType: ... + def day_name(self, locale: str | None = ...) -> _DTStrKindReturnType: ... + +class _DatetimeNoTZProperties( + _DatetimeLikeOps[ + _DTFieldOpsReturnType, + _DTBoolOpsReturnType, + _DTOtherOpsDateReturnType, + _DTOtherOpsTimeReturnType, + _DTFreqReturnType, + ], + _DatetimeLikeNoTZMethods[ + _DTRoundingMethodReturnType, + _DTNormalizeReturnType, + _DTStrKindReturnType, + _DTToPeriodReturnType, + ], + Generic[ + _DTFieldOpsReturnType, + _DTBoolOpsReturnType, + _DTRoundingMethodReturnType, + _DTOtherOpsDateReturnType, + _DTOtherOpsTimeReturnType, + _DTFreqReturnType, + _DTNormalizeReturnType, + _DTStrKindReturnType, + _DTToPeriodReturnType, + ], +): ... + +class DatetimeProperties( + Properties, + _DatetimeNoTZProperties[ + _DTFieldOpsReturnType, + _DTBoolOpsReturnType, + _DTRoundingMethodReturnType, + _DTOtherOpsDateReturnType, + _DTOtherOpsTimeReturnType, + _DTFreqReturnType, + _DTNormalizeReturnType, + _DTStrKindReturnType, + _DTToPeriodReturnType, + ], + _TZConversionMethods, + Generic[ + _DTFieldOpsReturnType, + _DTBoolOpsReturnType, + _DTRoundingMethodReturnType, + _DTOtherOpsDateReturnType, + _DTOtherOpsTimeReturnType, + _DTFreqReturnType, + _DTNormalizeReturnType, + _DTStrKindReturnType, + _DTToPeriodReturnType, + ], +): + def to_pydatetime(self) -> np.ndarray: ... + def isocalendar(self) -> DataFrame: ... -class TimedeltaProperties(Properties): +class _TimedeltaPropertiesNoRounding: def to_pytimedelta(self) -> np.ndarray: ... @property def components(self) -> DataFrame: ... @@ -148,32 +288,14 @@ class TimedeltaProperties(Properties): @property def nanoseconds(self) -> Series[int]: ... def total_seconds(self) -> Series[float]: ... - # Ideally, the next 3 methods would return TimedeltaSeries, but because of - # how Series.dt is hooked in, we don't know which kind of series was passed - # in to the dt accessor - def round( - self, - freq: str | BaseOffset | None, - ambiguous: Literal["raise", "infer", "NaT"] | np_ndarray_bool = ..., - nonexistent: Literal["shift_forward", "shift_backward", "NaT", "raise"] - | Timedelta = ..., - ) -> Series: ... - def floor( - self, - freq: str | BaseOffset | None, - ambiguous: Literal["raise", "infer", "NaT"] | np_ndarray_bool = ..., - nonexistent: Literal["shift_forward", "shift_backward", "NaT", "raise"] - | Timedelta = ..., - ) -> Series: ... - def ceil( - self, - freq: str | BaseOffset | None, - ambiguous: Literal["raise", "infer", "NaT"] | np_ndarray_bool = ..., - nonexistent: Literal["shift_forward", "shift_backward", "NaT", "raise"] - | Timedelta = ..., - ) -> Series: ... -class PeriodProperties(DatetimeAndPeriodProperties): +class TimedeltaProperties( + Properties, + _TimedeltaPropertiesNoRounding, + _DatetimeRoundingMethods[TimedeltaSeries], +): ... + +class _PeriodProperties: @property def start_time(self) -> TimestampSeries: ... @property @@ -192,7 +314,65 @@ class PeriodProperties(DatetimeAndPeriodProperties): how: Literal["E", "END", "FINISH", "S", "START", "BEGIN"] = ..., ) -> PeriodArray: ... +class PeriodProperties( + Properties, + _PeriodProperties, + _DatetimeFieldOps[Series[int]], + _IsLeapYearProperty, + _FreqProperty[BaseOffset], +): ... + class CombinedDatetimelikeProperties( - DatetimeProperties, TimedeltaProperties, PeriodProperties + DatetimeProperties[ + Series[int], + Series[bool], + Series, + Series[dt.date], + Series[dt.time], + str, + TimestampSeries, + Series[str], + PeriodSeries, + ], + _TimedeltaPropertiesNoRounding, + _PeriodProperties, ): def __new__(cls, data: Series): ... + +class TimestampProperties( + DatetimeProperties[ + Series[int], + Series[bool], + TimestampSeries, + Series[dt.date], + Series[dt.time], + str, + TimestampSeries, + Series[str], + PeriodSeries, + ] +): ... + +class DatetimeIndexProperties( + Properties, + _DatetimeNoTZProperties[ + IntegerIndex, + np_ndarray_bool, + DatetimeIndex, + np.ndarray, + np.ndarray, + BaseOffset, + DatetimeIndex, + Index, + PeriodIndex, + ], + _TZProperty, +): + @property + def is_normalized(self) -> bool: ... + @property + def tzinfo(self) -> tzinfo | None: ... + def to_pydatetime(self) -> npt.NDArray[np.object_]: ... + def std( + self, axis: int | None = ..., ddof: int = ..., skipna: bool = ... + ) -> Timedelta: ... diff --git a/pandas-stubs/core/indexes/datetimelike.pyi b/pandas-stubs/core/indexes/datetimelike.pyi index a4e3d1cb9..71dae2792 100644 --- a/pandas-stubs/core/indexes/datetimelike.pyi +++ b/pandas-stubs/core/indexes/datetimelike.pyi @@ -1,10 +1,11 @@ from pandas.core.indexes.extension import ExtensionIndex from pandas.core.indexes.numeric import Int64Index -from pandas.tseries.frequencies import DateOffset +from pandas._libs.tslibs import BaseOffset class DatetimeIndexOpsMixin(ExtensionIndex): - freq: DateOffset | None + @property + def freq(self) -> BaseOffset | None: ... freqstr: str | None @property def is_all_dates(self) -> bool: ... diff --git a/pandas-stubs/core/indexes/datetimes.pyi b/pandas-stubs/core/indexes/datetimes.pyi index 360ab223f..d16f6cfdf 100644 --- a/pandas-stubs/core/indexes/datetimes.pyi +++ b/pandas-stubs/core/indexes/datetimes.pyi @@ -7,10 +7,8 @@ from pandas import ( Timedelta, Timestamp, ) -from pandas.core.indexes.api import ( - Float64Index, - PeriodIndex, -) +from pandas.core.indexes.accessors import DatetimeIndexProperties +from pandas.core.indexes.api import Float64Index from pandas.core.indexes.datetimelike import DatetimeTimedeltaMixin from pandas.core.indexes.timedeltas import TimedeltaIndex from pandas.core.series import ( @@ -18,13 +16,19 @@ from pandas.core.series import ( TimestampSeries, ) -from pandas._typing import np_ndarray_bool +from pandas._typing import ( + AnyArrayLike, + ArrayLike, + np_ndarray_bool, +) + +from pandas.core.dtypes.dtypes import DatetimeTZDtype -class DatetimeIndex(DatetimeTimedeltaMixin): +class DatetimeIndex(DatetimeTimedeltaMixin, DatetimeIndexProperties): tz: tzinfo | None def __init__( self, - data=..., + data: ArrayLike | AnyArrayLike | list | tuple, freq=..., tz=..., normalize: bool = ..., @@ -59,10 +63,6 @@ class DatetimeIndex(DatetimeTimedeltaMixin): def indexer_between_time( self, start_time, end_time, include_start: bool = ..., include_end: bool = ... ): ... - def strftime(self, date_format: str = ...) -> np.ndarray: ... - def tz_convert(self, tz) -> DatetimeIndex: ... - def tz_localize(self, tz, ambiguous=..., nonexistent=...) -> DatetimeIndex: ... - def to_period(self, freq) -> PeriodIndex: ... def to_perioddelta(self, freq) -> TimedeltaIndex: ... def to_julian_date(self) -> Float64Index: ... def isocalendar(self) -> DataFrame: ... @@ -72,6 +72,9 @@ class DatetimeIndex(DatetimeTimedeltaMixin): def __le__(self, other: Timestamp) -> np_ndarray_bool: ... def __gt__(self, other: Timestamp) -> np_ndarray_bool: ... def __ge__(self, other: Timestamp) -> np_ndarray_bool: ... + # ignore for mypy because we know dtype of a DatetimeIndex + @property + def dtype(self) -> np.dtype | DatetimeTZDtype: ... # type: ignore[misc] def date_range( start=..., diff --git a/pandas-stubs/core/series.pyi b/pandas-stubs/core/series.pyi index 1662e0a8d..498cb7adc 100644 --- a/pandas-stubs/core/series.pyi +++ b/pandas-stubs/core/series.pyi @@ -35,8 +35,9 @@ from pandas.core.groupby.generic import ( ) from pandas.core.indexes.accessors import ( CombinedDatetimelikeProperties, - DatetimeProperties, + PeriodProperties, TimedeltaProperties, + TimestampProperties, ) from pandas.core.indexes.base import Index from pandas.core.indexes.datetimes import DatetimeIndex @@ -1788,7 +1789,7 @@ class Series(IndexOpsMixin, NDFrame, Generic[S1]): class TimestampSeries(Series[Timestamp]): # ignore needed because of mypy @property - def dt(self) -> DatetimeProperties: ... # type: ignore[override] + def dt(self) -> TimestampProperties: ... # type: ignore[override] class TimedeltaSeries(Series[Timedelta]): # ignore needed because of mypy @@ -1799,3 +1800,8 @@ class TimedeltaSeries(Series[Timedelta]): # ignore needed because of mypy @property def dt(self) -> TimedeltaProperties: ... # type: ignore[override] + +class PeriodSeries(Series[Period]): + # ignore needed because of mypy + @property + def dt(self) -> PeriodProperties: ... # type: ignore[override] diff --git a/tests/test_timefuncs.py b/tests/test_timefuncs.py index 78598c886..786d4c35d 100644 --- a/tests/test_timefuncs.py +++ b/tests/test_timefuncs.py @@ -11,16 +11,18 @@ import numpy as np from numpy import typing as npt import pandas as pd -import pytest +from pandas.core.indexes.numeric import IntegerIndex from pytz.tzinfo import BaseTzInfo from typing_extensions import assert_type from pandas._libs import NaTType +from pandas._libs.tslibs import BaseOffset from tests import check if TYPE_CHECKING: from pandas.core.series import ( + PeriodSeries, TimedeltaSeries, TimestampSeries, ) @@ -255,7 +257,7 @@ def test_to_datetime_nat() -> None: ) -def test_dt_accessors() -> None: +def test_series_dt_accessors() -> None: # GH 131 i0 = pd.date_range(start="2022-06-01", periods=10) check(assert_type(i0, pd.DatetimeIndex), pd.DatetimeIndex, pd.Timestamp) @@ -275,16 +277,6 @@ def test_dt_accessors() -> None: check(assert_type(s0.dt.second, "pd.Series[int]"), pd.Series, int) check(assert_type(s0.dt.microsecond, "pd.Series[int]"), pd.Series, int) check(assert_type(s0.dt.nanosecond, "pd.Series[int]"), pd.Series, int) - with pytest.warns( - FutureWarning, - match="Series.dt.weekofyear and Series.dt.week have been deprecated", - ): - check(assert_type(s0.dt.week, "pd.Series[int]"), pd.Series, int) - with pytest.warns( - FutureWarning, - match="Series.dt.weekofyear and Series.dt.week have been deprecated", - ): - check(assert_type(s0.dt.weekofyear, "pd.Series[int]"), pd.Series, int) check(assert_type(s0.dt.dayofweek, "pd.Series[int]"), pd.Series, int) check(assert_type(s0.dt.day_of_week, "pd.Series[int]"), pd.Series, int) check(assert_type(s0.dt.weekday, "pd.Series[int]"), pd.Series, int) @@ -303,9 +295,7 @@ def test_dt_accessors() -> None: assert assert_type(s0.dt.tz, Optional[Union[dt.tzinfo, BaseTzInfo]]) is None check(assert_type(s0.dt.freq, Optional[str]), str) check(assert_type(s0.dt.isocalendar(), pd.DataFrame), pd.DataFrame) - check( - assert_type(s0.dt.to_period("D"), "pd.Series[pd.Period]"), pd.Series, pd.Period - ) + check(assert_type(s0.dt.to_period("D"), "PeriodSeries"), pd.Series, pd.Period) check(assert_type(s0.dt.to_pydatetime(), np.ndarray), np.ndarray, dt.datetime) local_dtarray = s0.dt.tz_localize("UTC") slocal = pd.Series(local_dtarray) @@ -317,9 +307,9 @@ def test_dt_accessors() -> None: check(assert_type(slocal.dt.tz, Optional[Union[dt.tzinfo, BaseTzInfo]]), BaseTzInfo) check(assert_type(s0.dt.normalize(), "TimestampSeries"), pd.Series, pd.Timestamp) check(assert_type(s0.dt.strftime("%Y"), "pd.Series[str]"), pd.Series, str) - check(assert_type(s0.dt.round("D"), pd.Series), pd.Series, pd.Timestamp) - check(assert_type(s0.dt.floor("D"), pd.Series), pd.Series, pd.Timestamp) - check(assert_type(s0.dt.ceil("D"), pd.Series), pd.Series, pd.Timestamp) + check(assert_type(s0.dt.round("D"), "TimestampSeries"), pd.Series, pd.Timestamp) + check(assert_type(s0.dt.floor("D"), "TimestampSeries"), pd.Series, pd.Timestamp) + check(assert_type(s0.dt.ceil("D"), "TimestampSeries"), pd.Series, pd.Timestamp) check(assert_type(s0.dt.month_name(), "pd.Series[str]"), pd.Series, str) check(assert_type(s0.dt.day_name(), "pd.Series[str]"), pd.Series, str) @@ -349,3 +339,64 @@ def test_dt_accessors() -> None: check(assert_type(s2.dt.components, pd.DataFrame), pd.DataFrame) check(assert_type(s2.dt.to_pytimedelta(), np.ndarray), np.ndarray) check(assert_type(s2.dt.total_seconds(), "pd.Series[float]"), pd.Series, float) + + +def test_datetimeindex_accessors() -> None: + # GH 194 + x = pd.DatetimeIndex(["2022-08-14", "2022-08-20"]) + check(assert_type(x.month, IntegerIndex), IntegerIndex) + + i0 = pd.date_range(start="2022-06-01", periods=10) + check(assert_type(i0, pd.DatetimeIndex), pd.DatetimeIndex, pd.Timestamp) + + check(assert_type(i0.date, np.ndarray), np.ndarray, dt.date) + check(assert_type(i0.time, np.ndarray), np.ndarray, dt.time) + check(assert_type(i0.timetz, np.ndarray), np.ndarray, dt.time) + check(assert_type(i0.year, IntegerIndex), IntegerIndex, int) + check(assert_type(i0.month, IntegerIndex), IntegerIndex, int) + check(assert_type(i0.day, IntegerIndex), IntegerIndex, int) + check(assert_type(i0.hour, IntegerIndex), IntegerIndex, int) + check(assert_type(i0.minute, IntegerIndex), IntegerIndex, int) + check(assert_type(i0.second, IntegerIndex), IntegerIndex, int) + check(assert_type(i0.microsecond, IntegerIndex), IntegerIndex, int) + check(assert_type(i0.nanosecond, IntegerIndex), IntegerIndex, int) + check(assert_type(i0.dayofweek, IntegerIndex), IntegerIndex, int) + check(assert_type(i0.day_of_week, IntegerIndex), IntegerIndex, int) + check(assert_type(i0.weekday, IntegerIndex), IntegerIndex, int) + check(assert_type(i0.dayofyear, IntegerIndex), IntegerIndex, int) + check(assert_type(i0.day_of_year, IntegerIndex), IntegerIndex, int) + check(assert_type(i0.quarter, IntegerIndex), IntegerIndex, int) + check(assert_type(i0.is_month_start, npt.NDArray[np.bool_]), np.ndarray, np.bool_) + check(assert_type(i0.is_month_end, npt.NDArray[np.bool_]), np.ndarray, np.bool_) + check(assert_type(i0.is_quarter_start, npt.NDArray[np.bool_]), np.ndarray, np.bool_) + check(assert_type(i0.is_quarter_end, npt.NDArray[np.bool_]), np.ndarray, np.bool_) + check(assert_type(i0.is_year_start, npt.NDArray[np.bool_]), np.ndarray, np.bool_) + check(assert_type(i0.is_year_end, npt.NDArray[np.bool_]), np.ndarray, np.bool_) + check(assert_type(i0.is_leap_year, npt.NDArray[np.bool_]), np.ndarray, np.bool_) + check(assert_type(i0.daysinmonth, IntegerIndex), IntegerIndex, int) + check(assert_type(i0.days_in_month, IntegerIndex), IntegerIndex, int) + assert assert_type(i0.tz, Optional[dt.tzinfo]) is None + check(assert_type(i0.freq, Optional[BaseOffset]), BaseOffset) + check(assert_type(i0.isocalendar(), pd.DataFrame), pd.DataFrame) + check(assert_type(i0.to_period("D"), pd.PeriodIndex), pd.PeriodIndex, pd.Period) + check( + assert_type(i0.to_pydatetime(), npt.NDArray[np.object_]), + np.ndarray, + dt.datetime, + ) + local_dtarray = i0.tz_localize("UTC") + slocal = pd.Series(local_dtarray) + check( + assert_type(slocal.dt.tz_convert("EST"), "TimestampSeries"), + pd.Series, + pd.Timestamp, + ) + check(assert_type(slocal.dt.tz, Optional[Union[dt.tzinfo, BaseTzInfo]]), BaseTzInfo) + check(assert_type(i0.normalize(), pd.DatetimeIndex), pd.DatetimeIndex, pd.Timestamp) + check(assert_type(i0.strftime("%Y"), pd.Index), pd.Index, str) + check(assert_type(i0.round("D"), pd.DatetimeIndex), pd.DatetimeIndex, pd.Timestamp) + check(assert_type(i0.floor("D"), pd.DatetimeIndex), pd.DatetimeIndex, pd.Timestamp) + check(assert_type(i0.ceil("D"), pd.DatetimeIndex), pd.DatetimeIndex, pd.Timestamp) + check(assert_type(i0.month_name(), pd.Index), pd.Index, str) + check(assert_type(i0.day_name(), pd.Index), pd.Index, str) + check(assert_type(i0.is_normalized, bool), bool)