Skip to content

Commit 2ca04fa

Browse files
committed
Add unit property and as_unit method to TimestampSeries and TimedeltaSeries
1 parent f571b68 commit 2ca04fa

File tree

2 files changed

+57
-14
lines changed

2 files changed

+57
-14
lines changed

pandas-stubs/core/indexes/accessors.pyi

Lines changed: 22 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -154,16 +154,16 @@ class _DatetimeLikeOps(
154154
# type of the series, we don't know which kind of series was ...ed
155155
# in to the dt accessor
156156

157-
_DTRoundingMethodReturnType = TypeVar(
158-
"_DTRoundingMethodReturnType",
157+
_DTTimestampTimedeltaReturnType = TypeVar(
158+
"_DTTimestampTimedeltaReturnType",
159159
Series,
160-
TimedeltaSeries,
161160
TimestampSeries,
161+
TimedeltaSeries,
162162
DatetimeIndex,
163163
TimedeltaIndex,
164164
)
165165

166-
class _DatetimeRoundingMethods(Generic[_DTRoundingMethodReturnType]):
166+
class _DatetimeRoundingMethods(Generic[_DTTimestampTimedeltaReturnType]):
167167
def round(
168168
self,
169169
freq: str | BaseOffset | None,
@@ -173,7 +173,7 @@ class _DatetimeRoundingMethods(Generic[_DTRoundingMethodReturnType]):
173173
| timedelta
174174
| Timedelta
175175
) = ...,
176-
) -> _DTRoundingMethodReturnType: ...
176+
) -> _DTTimestampTimedeltaReturnType: ...
177177
def floor(
178178
self,
179179
freq: str | BaseOffset | None,
@@ -183,7 +183,7 @@ class _DatetimeRoundingMethods(Generic[_DTRoundingMethodReturnType]):
183183
| timedelta
184184
| Timedelta
185185
) = ...,
186-
) -> _DTRoundingMethodReturnType: ...
186+
) -> _DTTimestampTimedeltaReturnType: ...
187187
def ceil(
188188
self,
189189
freq: str | BaseOffset | None,
@@ -193,7 +193,7 @@ class _DatetimeRoundingMethods(Generic[_DTRoundingMethodReturnType]):
193193
| timedelta
194194
| Timedelta
195195
) = ...,
196-
) -> _DTRoundingMethodReturnType: ...
196+
) -> _DTTimestampTimedeltaReturnType: ...
197197

198198
_DTNormalizeReturnType = TypeVar(
199199
"_DTNormalizeReturnType", TimestampSeries, DatetimeIndex
@@ -202,9 +202,9 @@ _DTStrKindReturnType = TypeVar("_DTStrKindReturnType", Series[str], Index)
202202
_DTToPeriodReturnType = TypeVar("_DTToPeriodReturnType", PeriodSeries, PeriodIndex)
203203

204204
class _DatetimeLikeNoTZMethods(
205-
_DatetimeRoundingMethods[_DTRoundingMethodReturnType],
205+
_DatetimeRoundingMethods[_DTTimestampTimedeltaReturnType],
206206
Generic[
207-
_DTRoundingMethodReturnType,
207+
_DTTimestampTimedeltaReturnType,
208208
_DTNormalizeReturnType,
209209
_DTStrKindReturnType,
210210
_DTToPeriodReturnType,
@@ -238,15 +238,15 @@ class _DatetimeNoTZProperties(
238238
_DTFreqReturnType,
239239
],
240240
_DatetimeLikeNoTZMethods[
241-
_DTRoundingMethodReturnType,
241+
_DTTimestampTimedeltaReturnType,
242242
_DTNormalizeReturnType,
243243
_DTStrKindReturnType,
244244
_DTToPeriodReturnType,
245245
],
246246
Generic[
247247
_DTFieldOpsReturnType,
248248
_DTBoolOpsReturnType,
249-
_DTRoundingMethodReturnType,
249+
_DTTimestampTimedeltaReturnType,
250250
_DTOtherOpsDateReturnType,
251251
_DTOtherOpsTimeReturnType,
252252
_DTFreqReturnType,
@@ -261,7 +261,7 @@ class DatetimeProperties(
261261
_DatetimeNoTZProperties[
262262
_DTFieldOpsReturnType,
263263
_DTBoolOpsReturnType,
264-
_DTRoundingMethodReturnType,
264+
_DTTimestampTimedeltaReturnType,
265265
_DTOtherOpsDateReturnType,
266266
_DTOtherOpsTimeReturnType,
267267
_DTFreqReturnType,
@@ -272,7 +272,7 @@ class DatetimeProperties(
272272
Generic[
273273
_DTFieldOpsReturnType,
274274
_DTBoolOpsReturnType,
275-
_DTRoundingMethodReturnType,
275+
_DTTimestampTimedeltaReturnType,
276276
_DTOtherOpsDateReturnType,
277277
_DTOtherOpsTimeReturnType,
278278
_DTFreqReturnType,
@@ -283,6 +283,11 @@ class DatetimeProperties(
283283
):
284284
def to_pydatetime(self) -> np.ndarray: ...
285285
def isocalendar(self) -> DataFrame: ...
286+
@property
287+
def unit(self) -> str: ...
288+
def as_unit(
289+
self, unit: Literal["s", "ms", "us", "ns"]
290+
) -> _DTTimestampTimedeltaReturnType: ...
286291

287292
_TDNoRoundingMethodReturnType = TypeVar(
288293
"_TDNoRoundingMethodReturnType", Series[int], Index
@@ -309,7 +314,10 @@ class TimedeltaProperties(
309314
Properties,
310315
_TimedeltaPropertiesNoRounding[Series[int], Series[float]],
311316
_DatetimeRoundingMethods[TimedeltaSeries],
312-
): ...
317+
):
318+
@property
319+
def unit(self) -> str: ...
320+
def as_unit(self, unit: Literal["s", "ms", "us", "ns"]) -> TimedeltaSeries: ...
313321

314322
_PeriodDTReturnTypes = TypeVar("_PeriodDTReturnTypes", TimestampSeries, DatetimeIndex)
315323
_PeriodIntReturnTypes = TypeVar("_PeriodIntReturnTypes", Series[int], Index[int])

tests/test_timefuncs.py

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
TYPE_CHECKING,
66
Any,
77
Optional,
8+
cast,
89
)
910

1011
import numpy as np
@@ -428,6 +429,11 @@ def test_series_dt_accessors() -> None:
428429
)
429430
check(assert_type(s0.dt.month_name(), "pd.Series[str]"), pd.Series, str)
430431
check(assert_type(s0.dt.day_name(), "pd.Series[str]"), pd.Series, str)
432+
check(assert_type(s0.dt.unit, str), str)
433+
check(assert_type(s0.dt.as_unit("s"), "TimestampSeries"), pd.Series, pd.Timestamp)
434+
check(assert_type(s0.dt.as_unit("ms"), "TimestampSeries"), pd.Series, pd.Timestamp)
435+
check(assert_type(s0.dt.as_unit("us"), "TimestampSeries"), pd.Series, pd.Timestamp)
436+
check(assert_type(s0.dt.as_unit("ns"), "TimestampSeries"), pd.Series, pd.Timestamp)
431437

432438
i1 = pd.period_range(start="2022-06-01", periods=10)
433439

@@ -455,6 +461,35 @@ def test_series_dt_accessors() -> None:
455461
check(assert_type(s2.dt.components, pd.DataFrame), pd.DataFrame)
456462
check(assert_type(s2.dt.to_pytimedelta(), np.ndarray), np.ndarray)
457463
check(assert_type(s2.dt.total_seconds(), "pd.Series[float]"), pd.Series, float)
464+
check(assert_type(s2.dt.unit, str), str)
465+
check(assert_type(s2.dt.as_unit("s"), "TimedeltaSeries"), pd.Series, pd.Timedelta)
466+
check(assert_type(s2.dt.as_unit("ms"), "TimedeltaSeries"), pd.Series, pd.Timedelta)
467+
check(assert_type(s2.dt.as_unit("us"), "TimedeltaSeries"), pd.Series, pd.Timedelta)
468+
check(assert_type(s2.dt.as_unit("ns"), "TimedeltaSeries"), pd.Series, pd.Timedelta)
469+
470+
# Checks for general Series other than TimestampSeries and TimedeltaSeries
471+
472+
s4 = cast(
473+
"pd.Series[pd.Timestamp]",
474+
pd.Series([pd.Timestamp("2024-01-01"), pd.Timestamp("2024-01-02")]),
475+
)
476+
477+
check(assert_type(s4.dt.unit, str), str)
478+
check(assert_type(s4.dt.as_unit("s"), pd.Series), pd.Series, pd.Timestamp)
479+
check(assert_type(s4.dt.as_unit("ms"), pd.Series), pd.Series, pd.Timestamp)
480+
check(assert_type(s4.dt.as_unit("us"), pd.Series), pd.Series, pd.Timestamp)
481+
check(assert_type(s4.dt.as_unit("ns"), pd.Series), pd.Series, pd.Timestamp)
482+
483+
s5 = cast(
484+
"pd.Series[pd.Timedelta]",
485+
pd.Series([pd.Timedelta("1 day"), pd.Timedelta("2 days")]),
486+
)
487+
488+
check(assert_type(s5.dt.unit, str), str)
489+
check(assert_type(s5.dt.as_unit("s"), pd.Series), pd.Series, pd.Timedelta)
490+
check(assert_type(s5.dt.as_unit("ms"), pd.Series), pd.Series, pd.Timedelta)
491+
check(assert_type(s5.dt.as_unit("us"), pd.Series), pd.Series, pd.Timedelta)
492+
check(assert_type(s5.dt.as_unit("ns"), pd.Series), pd.Series, pd.Timedelta)
458493

459494

460495
def test_datetimeindex_accessors() -> None:

0 commit comments

Comments
 (0)