Skip to content

Commit cb56bfa

Browse files
bashtageKevin Sheppard
and
Kevin Sheppard
authored
ENH: Improve general datetime functions (#352)
* TYP: Improve infer_freq * TYP: Imrprove timedelta_range * TYP: Imrprove period_range * TYP: Improve date_range and bdate_range * TYP: Improve to_timedelta * TYP: Improve to_datetime * Small fixes * TST: Add tests for to_timedelta * TST/ENH: Add tests and overload for bdate_range * TST/ENH: Add tests and improve period_range * TST: Add tests * TST: Add check and assert type, add more tests * CLN: Remove unnecessary TODO * ENH: Improve timestamp convertible Co-authored-by: Kevin Sheppard <kevin.sheppard@gmail.com>
1 parent 635733c commit cb56bfa

File tree

9 files changed

+519
-58
lines changed

9 files changed

+519
-58
lines changed

pandas-stubs/_libs/tslibs/timedeltas.pyi

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ from typing import (
33
ClassVar,
44
Literal,
55
TypeVar,
6+
Union,
67
overload,
78
)
89

@@ -17,10 +18,7 @@ from pandas._typing import npt
1718

1819
# This should be kept consistent with the keys in the dict timedelta_abbrevs
1920
# in pandas/_libs/tslibs/timedeltas.pyx
20-
UnitChoices: TypeAlias = Literal[
21-
"Y",
22-
"y",
23-
"M",
21+
TimeDeltaUnitChoices: TypeAlias = Literal[
2422
"W",
2523
"w",
2624
"D",
@@ -60,6 +58,16 @@ UnitChoices: TypeAlias = Literal[
6058
"nanosecond",
6159
"n",
6260
]
61+
62+
UnitChoices: TypeAlias = Union[
63+
TimeDeltaUnitChoices,
64+
Literal[
65+
"Y",
66+
"y",
67+
"M",
68+
],
69+
]
70+
6371
_S = TypeVar("_S", bound=timedelta)
6472

6573
def ints_to_pytimedelta(

pandas-stubs/_typing.pyi

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ from typing import (
1919
import numpy as np
2020
from numpy import typing as npt
2121
from pandas.core.arrays import ExtensionArray
22+
from pandas.core.frame import DataFrame
2223
from pandas.core.generic import NDFrame
2324
from pandas.core.groupby.grouper import Grouper
2425
from pandas.core.indexes.base import Index
@@ -46,6 +47,27 @@ PandasScalar: TypeAlias = Union[
4647

4748
DatetimeLike: TypeAlias = Union[datetime.datetime, np.datetime64, Timestamp]
4849

50+
DatetimeDictArg: TypeAlias = Union[
51+
Sequence[int], Sequence[float], list[str], tuple[Scalar, ...], AnyArrayLike
52+
]
53+
DictConvertible: TypeAlias = Union[FulldatetimeDict, DataFrame]
54+
55+
class YearMonthDayDict(TypedDict, total=True):
56+
year: DatetimeDictArg
57+
month: DatetimeDictArg
58+
day: DatetimeDictArg
59+
60+
class FulldatetimeDict(YearMonthDayDict, total=False):
61+
hour: DatetimeDictArg
62+
hours: DatetimeDictArg
63+
minute: DatetimeDictArg
64+
minutes: DatetimeDictArg
65+
second: DatetimeDictArg
66+
seconds: DatetimeDictArg
67+
ms: DatetimeDictArg
68+
us: DatetimeDictArg
69+
ns: DatetimeDictArg
70+
4971
# dtypes
5072
NpDtype: TypeAlias = Union[
5173
str, np.dtype[np.generic], type[Union[str, complex, bool, object]]
@@ -178,7 +200,7 @@ IndexingInt: TypeAlias = Union[
178200
int, np.int_, np.integer, np.unsignedinteger, np.signedinteger, np.int8
179201
]
180202
TimestampConvertibleTypes: TypeAlias = Union[
181-
Timestamp, datetime.datetime, np.datetime64, np.int64, float, str
203+
Timestamp, datetime.datetime, datetime.date, np.datetime64, np.int64, float, str
182204
]
183205
TimedeltaConvertibleTypes: TypeAlias = Union[
184206
Timedelta, datetime.timedelta, np.timedelta64, np.int64, float, str

pandas-stubs/core/indexes/datetimes.pyi

Lines changed: 24 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,13 @@
11
from datetime import (
2+
date,
23
timedelta,
34
tzinfo,
45
)
5-
from typing import overload
6+
from typing import (
7+
Hashable,
8+
Sequence,
9+
overload,
10+
)
611

712
import numpy as np
813
from pandas import (
@@ -90,20 +95,33 @@ def date_range(
9095
freq: str | timedelta | Timedelta | BaseOffset = ...,
9196
tz: str | tzinfo = ...,
9297
normalize: bool = ...,
93-
name: str | None = ...,
98+
name: Hashable | None = ...,
9499
inclusive: IntervalClosedType = ...,
95-
**kwargs,
96100
) -> DatetimeIndex: ...
101+
@overload
97102
def bdate_range(
98103
start: str | DatetimeLike | None = ...,
99104
end: str | DatetimeLike | None = ...,
100105
periods: int | None = ...,
101106
freq: str | timedelta | Timedelta | BaseOffset = ...,
102107
tz: str | tzinfo = ...,
103108
normalize: bool = ...,
104-
name: str | None = ...,
109+
name: Hashable | None = ...,
110+
weekmask: str | None = ...,
111+
holidays: None = ...,
112+
inclusive: IntervalClosedType = ...,
113+
) -> DatetimeIndex: ...
114+
@overload
115+
def bdate_range(
116+
start: str | DatetimeLike | None = ...,
117+
end: str | DatetimeLike | None = ...,
118+
periods: int | None = ...,
119+
*,
120+
freq: str | timedelta | Timedelta | BaseOffset,
121+
tz: str | tzinfo = ...,
122+
normalize: bool = ...,
123+
name: Hashable | None = ...,
105124
weekmask: str | None = ...,
106-
holidays: list | None = ...,
125+
holidays: Sequence[str | DatetimeLike | date],
107126
inclusive: IntervalClosedType = ...,
108-
**kwargs,
109127
) -> DatetimeIndex: ...

pandas-stubs/core/indexes/period.pyi

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,14 @@
1+
from typing import Hashable
2+
13
import numpy as np
4+
import pandas as pd
25
from pandas.core.indexes.datetimelike import (
36
DatetimeIndexOpsMixin as DatetimeIndexOpsMixin,
47
)
58
from pandas.core.indexes.numeric import Int64Index
69

10+
from pandas._libs.tslibs import BaseOffset
11+
712
class PeriodIndex(DatetimeIndexOpsMixin, Int64Index):
813
def __new__(
914
cls,
@@ -46,5 +51,9 @@ class PeriodIndex(DatetimeIndexOpsMixin, Int64Index):
4651
def memory_usage(self, deep: bool = ...): ...
4752

4853
def period_range(
49-
start=..., end=..., periods=..., freq=..., name=...
54+
start: str | pd.Period | None = ...,
55+
end: str | pd.Period | None = ...,
56+
periods: int | None = ...,
57+
freq: str | BaseOffset | None = ...,
58+
name: Hashable | None = ...,
5059
) -> PeriodIndex: ...

pandas-stubs/core/indexes/timedeltas.pyi

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,10 @@
1-
from typing import overload
1+
from typing import (
2+
Hashable,
3+
Literal,
4+
overload,
5+
)
26

7+
from pandas import DateOffset
38
from pandas.core.indexes.accessors import TimedeltaIndexProperties
49
from pandas.core.indexes.datetimelike import DatetimeTimedeltaMixin
510
from pandas.core.indexes.datetimes import DatetimeIndex
@@ -9,7 +14,10 @@ from pandas._libs import (
914
Timedelta,
1015
Timestamp,
1116
)
12-
from pandas._typing import num
17+
from pandas._typing import (
18+
TimedeltaConvertibleTypes,
19+
num,
20+
)
1321

1422
class TimedeltaIndex(DatetimeTimedeltaMixin, TimedeltaIndexProperties):
1523
def __new__(
@@ -42,5 +50,10 @@ class TimedeltaIndex(DatetimeTimedeltaMixin, TimedeltaIndexProperties):
4250
def to_series(self, index=..., name=...) -> TimedeltaSeries: ...
4351

4452
def timedelta_range(
45-
start=..., end=..., periods=..., freq=..., name=..., closed=...
53+
start: TimedeltaConvertibleTypes = ...,
54+
end: TimedeltaConvertibleTypes = ...,
55+
periods: int | None = ...,
56+
freq: str | DateOffset | None = ...,
57+
name: Hashable | None = ...,
58+
closed: Literal["left", "right"] | None = ...,
4659
) -> TimedeltaIndex: ...

pandas-stubs/core/tools/datetimes.pyi

Lines changed: 22 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,21 @@
1-
from datetime import datetime
1+
from datetime import (
2+
date,
3+
datetime,
4+
)
25
from typing import (
36
Literal,
4-
TypedDict,
7+
Sequence,
58
Union,
69
overload,
710
)
811

912
import numpy as np
13+
import pandas as pd
1014
from pandas import (
1115
Index,
1216
Timestamp,
1317
)
1418
from pandas.core.arrays import ExtensionArray
15-
from pandas.core.frame import DataFrame
1619
from pandas.core.indexes.datetimes import DatetimeIndex
1720
from pandas.core.series import (
1821
Series,
@@ -24,38 +27,18 @@ from pandas._libs.tslibs import NaTType
2427
from pandas._typing import (
2528
AnyArrayLike,
2629
DateTimeErrorChoices,
30+
DictConvertible,
2731
IgnoreRaise,
32+
TimestampConvertibleTypes,
33+
npt,
2834
)
2935

3036
ArrayConvertible: TypeAlias = Union[list, tuple, AnyArrayLike]
3137
Scalar: TypeAlias = Union[float, str]
32-
DatetimeScalar: TypeAlias = Union[Scalar, datetime, np.datetime64]
38+
DatetimeScalar: TypeAlias = Union[Scalar, datetime, np.datetime64, date]
3339

3440
DatetimeScalarOrArrayConvertible: TypeAlias = Union[DatetimeScalar, ArrayConvertible]
3541

36-
DatetimeDictArg: TypeAlias = Union[list[Scalar], tuple[Scalar, ...], AnyArrayLike]
37-
38-
class YearMonthDayDict(TypedDict, total=True):
39-
year: DatetimeDictArg
40-
month: DatetimeDictArg
41-
day: DatetimeDictArg
42-
43-
class FulldatetimeDict(YearMonthDayDict, total=False):
44-
hour: DatetimeDictArg
45-
hours: DatetimeDictArg
46-
minute: DatetimeDictArg
47-
minutes: DatetimeDictArg
48-
second: DatetimeDictArg
49-
seconds: DatetimeDictArg
50-
ms: DatetimeDictArg
51-
us: DatetimeDictArg
52-
ns: DatetimeDictArg
53-
54-
DictConvertible: TypeAlias = Union[FulldatetimeDict, DataFrame]
55-
56-
def should_cache(
57-
arg: ArrayConvertible, unique_share: float = ..., check_count: int | None = ...
58-
) -> bool: ...
5942
@overload
6043
def to_datetime(
6144
arg: DatetimeScalar,
@@ -67,7 +50,7 @@ def to_datetime(
6750
exact: bool = ...,
6851
unit: str | None = ...,
6952
infer_datetime_format: bool = ...,
70-
origin=...,
53+
origin: Literal["julian", "unix"] | TimestampConvertibleTypes = ...,
7154
cache: bool = ...,
7255
) -> Timestamp: ...
7356
@overload
@@ -81,7 +64,7 @@ def to_datetime(
8164
exact: bool = ...,
8265
unit: str | None = ...,
8366
infer_datetime_format: bool = ...,
84-
origin=...,
67+
origin: Literal["julian", "unix"] | TimestampConvertibleTypes = ...,
8568
cache: bool = ...,
8669
) -> Timestamp | NaTType: ...
8770
@overload
@@ -95,12 +78,19 @@ def to_datetime(
9578
exact: bool = ...,
9679
unit: str | None = ...,
9780
infer_datetime_format: bool = ...,
98-
origin=...,
81+
origin: Literal["julian", "unix"] | TimestampConvertibleTypes = ...,
9982
cache: bool = ...,
10083
) -> TimestampSeries: ...
10184
@overload
10285
def to_datetime(
103-
arg: list | tuple | np.ndarray | Index | ExtensionArray,
86+
arg: Sequence[int | float | datetime]
87+
| list[str]
88+
| tuple[int | float | str | datetime, ...]
89+
| npt.NDArray[np.datetime64]
90+
| npt.NDArray[np.str_]
91+
| npt.NDArray[np.int_]
92+
| Index
93+
| ExtensionArray,
10494
errors: DateTimeErrorChoices = ...,
10595
dayfirst: bool = ...,
10696
yearfirst: bool = ...,
@@ -109,7 +99,6 @@ def to_datetime(
10999
exact: bool = ...,
110100
unit: str | None = ...,
111101
infer_datetime_format: bool = ...,
112-
origin=...,
102+
origin: Literal["julian", "unix"] | TimestampConvertibleTypes = ...,
113103
cache: bool = ...,
114104
) -> DatetimeIndex: ...
115-
def to_time(arg, format=..., infer_time_format: bool = ..., errors: str = ...): ...
Lines changed: 15 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
1-
# def to_timedelta(arg, unit: str = ..., errors: str = ...): ...
21
from datetime import timedelta
3-
from typing import overload
2+
from typing import (
3+
Sequence,
4+
overload,
5+
)
46

7+
import pandas as pd
58
from pandas import Index
69
from pandas.core.indexes.timedeltas import TimedeltaIndex
710
from pandas.core.series import (
@@ -10,29 +13,32 @@ from pandas.core.series import (
1013
)
1114

1215
from pandas._libs.tslibs import Timedelta
13-
from pandas._libs.tslibs.timedeltas import UnitChoices
16+
from pandas._libs.tslibs.timedeltas import TimeDeltaUnitChoices
1417
from pandas._typing import (
1518
ArrayLike,
1619
DateTimeErrorChoices,
1720
)
1821

19-
# Copied from pandas/_libs/tslibs/timedeltas.pyx
20-
2122
@overload
2223
def to_timedelta(
2324
arg: str | float | timedelta,
24-
unit: UnitChoices | None = ...,
25+
unit: TimeDeltaUnitChoices | None = ...,
2526
errors: DateTimeErrorChoices = ...,
2627
) -> Timedelta: ...
2728
@overload
2829
def to_timedelta(
2930
arg: Series,
30-
unit: UnitChoices | None = ...,
31+
unit: TimeDeltaUnitChoices | None = ...,
3132
errors: DateTimeErrorChoices = ...,
3233
) -> TimedeltaSeries: ...
3334
@overload
3435
def to_timedelta(
35-
arg: list | tuple | range | ArrayLike | Index,
36-
unit: UnitChoices | None = ...,
36+
arg: Sequence[float | timedelta]
37+
| list[str | float | timedelta]
38+
| tuple[str | float | timedelta, ...]
39+
| range
40+
| ArrayLike
41+
| Index,
42+
unit: TimeDeltaUnitChoices | None = ...,
3743
errors: DateTimeErrorChoices = ...,
3844
) -> TimedeltaIndex: ...

pandas-stubs/tseries/frequencies.pyi

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,12 @@
1+
from pandas import (
2+
DatetimeIndex,
3+
Series,
4+
TimedeltaIndex,
5+
)
6+
17
from pandas.tseries.offsets import DateOffset as DateOffset
28

39
def get_period_alias(offset_str: str) -> str | None: ...
410
def to_offset(freq) -> DateOffset | None: ...
511
def get_offset(name: str) -> DateOffset: ...
6-
def infer_freq(index) -> str | None: ...
12+
def infer_freq(index: Series | DatetimeIndex | TimedeltaIndex) -> str | None: ...

0 commit comments

Comments
 (0)