Skip to content

Commit 5faa34c

Browse files
authored
TYP: timestamps.pyi (#40945)
1 parent 7c1f454 commit 5faa34c

File tree

9 files changed

+252
-30
lines changed

9 files changed

+252
-30
lines changed

pandas/_libs/tslibs/timestamps.pyi

+205
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,205 @@
1+
from datetime import (
2+
date as _date,
3+
datetime,
4+
time as _time,
5+
timedelta,
6+
tzinfo as _tzinfo,
7+
)
8+
import sys
9+
from time import struct_time
10+
from typing import (
11+
ClassVar,
12+
Optional,
13+
Type,
14+
TypeVar,
15+
overload,
16+
)
17+
18+
import numpy as np
19+
20+
from pandas._libs.tslibs import (
21+
NaT,
22+
NaTType,
23+
Period,
24+
Timedelta,
25+
)
26+
27+
_S = TypeVar("_S")
28+
29+
30+
def integer_op_not_supported(obj) -> None: ...
31+
32+
33+
class Timestamp(datetime):
34+
min: ClassVar[Timestamp]
35+
max: ClassVar[Timestamp]
36+
37+
resolution: ClassVar[Timedelta]
38+
value: int # np.int64
39+
40+
# error: "__new__" must return a class instance (got "Union[Timestamp, NaTType]")
41+
def __new__( # type: ignore[misc]
42+
cls: Type[_S],
43+
ts_input: int | np.integer | float | str | _date | datetime | np.datetime64 = ...,
44+
freq=...,
45+
tz: str | _tzinfo | None | int= ...,
46+
unit=...,
47+
year: int | None = ...,
48+
month: int | None = ...,
49+
day: int | None = ...,
50+
hour: int | None = ...,
51+
minute: int | None = ...,
52+
second: int | None = ...,
53+
microsecond: int | None = ...,
54+
nanosecond: int | None = ...,
55+
tzinfo: _tzinfo | None = ...,
56+
*,
57+
fold: int | None= ...,
58+
) -> _S | NaTType: ...
59+
60+
@property
61+
def year(self) -> int: ...
62+
@property
63+
def month(self) -> int: ...
64+
@property
65+
def day(self) -> int: ...
66+
@property
67+
def hour(self) -> int: ...
68+
@property
69+
def minute(self) -> int: ...
70+
@property
71+
def second(self) -> int: ...
72+
@property
73+
def microsecond(self) -> int: ...
74+
@property
75+
def tzinfo(self) -> Optional[_tzinfo]: ...
76+
@property
77+
def tz(self) -> Optional[_tzinfo]: ...
78+
79+
@property
80+
def fold(self) -> int: ...
81+
82+
@classmethod
83+
def fromtimestamp(cls: Type[_S], t: float, tz: Optional[_tzinfo] = ...) -> _S: ...
84+
@classmethod
85+
def utcfromtimestamp(cls: Type[_S], t: float) -> _S: ...
86+
@classmethod
87+
def today(cls: Type[_S]) -> _S: ...
88+
@classmethod
89+
def fromordinal(cls: Type[_S], n: int) -> _S: ...
90+
91+
if sys.version_info >= (3, 8):
92+
@classmethod
93+
def now(cls: Type[_S], tz: _tzinfo | str | None = ...) -> _S: ...
94+
else:
95+
@overload
96+
@classmethod
97+
def now(cls: Type[_S], tz: None = ...) -> _S: ...
98+
@overload
99+
@classmethod
100+
def now(cls, tz: _tzinfo) -> datetime: ...
101+
102+
@classmethod
103+
def utcnow(cls: Type[_S]) -> _S: ...
104+
@classmethod
105+
def combine(cls, date: _date, time: _time, tzinfo: Optional[_tzinfo] = ...) -> datetime: ...
106+
107+
@classmethod
108+
def fromisoformat(cls: Type[_S], date_string: str) -> _S: ...
109+
110+
def strftime(self, fmt: str) -> str: ...
111+
def __format__(self, fmt: str) -> str: ...
112+
113+
def toordinal(self) -> int: ...
114+
def timetuple(self) -> struct_time: ...
115+
116+
def timestamp(self) -> float: ...
117+
118+
def utctimetuple(self) -> struct_time: ...
119+
def date(self) -> _date: ...
120+
def time(self) -> _time: ...
121+
def timetz(self) -> _time: ...
122+
123+
def replace(
124+
self,
125+
year: int = ...,
126+
month: int = ...,
127+
day: int = ...,
128+
hour: int = ...,
129+
minute: int = ...,
130+
second: int = ...,
131+
microsecond: int = ...,
132+
tzinfo: Optional[_tzinfo] = ...,
133+
*,
134+
fold: int = ...,
135+
) -> datetime: ...
136+
137+
if sys.version_info >= (3, 8):
138+
def astimezone(self: _S, tz: Optional[_tzinfo] = ...) -> _S: ...
139+
else:
140+
def astimezone(self, tz: Optional[_tzinfo] = ...) -> datetime: ...
141+
142+
def ctime(self) -> str: ...
143+
def isoformat(self, sep: str = ..., timespec: str = ...) -> str: ...
144+
145+
@classmethod
146+
def strptime(cls, date_string: str, format: str) -> datetime: ...
147+
148+
def utcoffset(self) -> Optional[timedelta]: ...
149+
def tzname(self) -> Optional[str]: ...
150+
def dst(self) -> Optional[timedelta]: ...
151+
152+
def __le__(self, other: datetime) -> bool: ... # type: ignore
153+
def __lt__(self, other: datetime) -> bool: ... # type: ignore
154+
def __ge__(self, other: datetime) -> bool: ... # type: ignore
155+
def __gt__(self, other: datetime) -> bool: ... # type: ignore
156+
if sys.version_info >= (3, 8):
157+
def __add__(self: _S, other: timedelta) -> _S: ...
158+
def __radd__(self: _S, other: timedelta) -> _S: ...
159+
else:
160+
def __add__(self, other: timedelta) -> datetime: ...
161+
def __radd__(self, other: timedelta) -> datetime: ...
162+
@overload # type: ignore
163+
def __sub__(self, other: datetime) -> timedelta: ...
164+
@overload
165+
def __sub__(self, other: timedelta) -> datetime: ...
166+
167+
def __hash__(self) -> int: ...
168+
def weekday(self) -> int: ...
169+
def isoweekday(self) -> int: ...
170+
def isocalendar(self) -> tuple[int, int, int]: ...
171+
172+
@property
173+
def is_leap_year(self) -> bool: ...
174+
@property
175+
def is_month_start(self) -> bool: ...
176+
@property
177+
def is_quarter_start(self) -> bool: ...
178+
@property
179+
def is_year_start(self) -> bool: ...
180+
@property
181+
def is_month_end(self) -> bool: ...
182+
@property
183+
def is_quarter_end(self) -> bool: ...
184+
@property
185+
def is_year_end(self) -> bool: ...
186+
187+
def to_pydatetime(self, warn: bool = ...) -> datetime: ...
188+
def to_datetime64(self) -> np.datetime64: ...
189+
def to_period(self, freq) -> Period: ...
190+
def to_julian_date(self) -> np.float64: ...
191+
192+
@property
193+
def asm8(self) -> np.datetime64: ...
194+
195+
def tz_convert(self: _S, tz) -> _S: ...
196+
197+
# TODO: could return NaT?
198+
def tz_localize(self: _S, tz, ambiguous: str = ..., nonexistent: str = ...) -> _S: ...
199+
200+
def normalize(self: _S) -> _S: ...
201+
202+
# TODO: round/floor/ceil could return NaT?
203+
def round(self: _S, freq, ambiguous: bool | str = ..., nonexistent: str = ...) -> _S: ...
204+
def floor(self: _S, freq, ambiguous: bool | str = ..., nonexistent: str = ...) -> _S: ...
205+
def ceil(self: _S, freq, ambiguous: bool | str = ..., nonexistent: str = ...) -> _S: ...

pandas/core/arrays/_ranges.py

+8-8
Original file line numberDiff line numberDiff line change
@@ -41,20 +41,20 @@ def generate_regular_range(
4141
-------
4242
ndarray[np.int64] Representing nanoseconds.
4343
"""
44-
start = start.value if start is not None else None
45-
end = end.value if end is not None else None
44+
istart = start.value if start is not None else None
45+
iend = end.value if end is not None else None
4646
stride = freq.nanos
4747

4848
if periods is None:
49-
b = start
49+
b = istart
5050
# cannot just use e = Timestamp(end) + 1 because arange breaks when
5151
# stride is too large, see GH10887
52-
e = b + (end - b) // stride * stride + stride // 2 + 1
53-
elif start is not None:
54-
b = start
52+
e = b + (iend - b) // stride * stride + stride // 2 + 1
53+
elif istart is not None:
54+
b = istart
5555
e = _generate_range_overflow_safe(b, periods, stride, side="start")
56-
elif end is not None:
57-
e = end + stride
56+
elif iend is not None:
57+
e = iend + stride
5858
b = _generate_range_overflow_safe(e, periods, stride, side="end")
5959
else:
6060
raise ValueError(

pandas/core/arrays/datetimes.py

+3-1
Original file line numberDiff line numberDiff line change
@@ -742,7 +742,9 @@ def _sub_datetimelike_scalar(self, other):
742742
assert isinstance(other, (datetime, np.datetime64))
743743
assert other is not NaT
744744
other = Timestamp(other)
745-
if other is NaT:
745+
# error: Non-overlapping identity check (left operand type: "Timestamp",
746+
# right operand type: "NaTType")
747+
if other is NaT: # type: ignore[comparison-overlap]
746748
return self - NaT
747749

748750
if not self._has_same_tz(other):

pandas/core/dtypes/cast.py

+7-5
Original file line numberDiff line numberDiff line change
@@ -189,13 +189,13 @@ def maybe_box_native(value: Scalar) -> Scalar:
189189
value = maybe_box_datetimelike(value)
190190
elif is_float(value):
191191
# error: Argument 1 to "float" has incompatible type
192-
# "Union[Union[str, int, float, bool], Union[Any, Any, Timedelta, Any]]";
192+
# "Union[Union[str, int, float, bool], Union[Any, Timestamp, Timedelta, Any]]";
193193
# expected "Union[SupportsFloat, _SupportsIndex, str]"
194194
value = float(value) # type: ignore[arg-type]
195195
elif is_integer(value):
196196
# error: Argument 1 to "int" has incompatible type
197-
# "Union[Union[str, int, float, bool], Union[Any, Any, Timedelta, Any]]";
198-
# pected "Union[str, SupportsInt, _SupportsIndex, _SupportsTrunc]"
197+
# "Union[Union[str, int, float, bool], Union[Any, Timestamp, Timedelta, Any]]";
198+
# expected "Union[str, SupportsInt, _SupportsIndex, _SupportsTrunc]"
199199
value = int(value) # type: ignore[arg-type]
200200
elif is_bool(value):
201201
value = bool(value)
@@ -729,7 +729,9 @@ def infer_dtype_from_scalar(val, pandas_dtype: bool = False) -> tuple[DtypeObj,
729729
except OutOfBoundsDatetime:
730730
return np.dtype(object), val
731731

732-
if val is NaT or val.tz is None:
732+
# error: Non-overlapping identity check (left operand type: "Timestamp",
733+
# right operand type: "NaTType")
734+
if val is NaT or val.tz is None: # type: ignore[comparison-overlap]
733735
dtype = np.dtype("M8[ns]")
734736
val = val.to_datetime64()
735737
else:
@@ -2056,7 +2058,7 @@ def validate_numeric_casting(dtype: np.dtype, value: Scalar) -> None:
20562058
ValueError
20572059
"""
20582060
# error: Argument 1 to "__call__" of "ufunc" has incompatible type
2059-
# "Union[Union[str, int, float, bool], Union[Any, Any, Timedelta, Any]]";
2061+
# "Union[Union[str, int, float, bool], Union[Any, Timestamp, Timedelta, Any]]";
20602062
# expected "Union[Union[int, float, complex, str, bytes, generic],
20612063
# Sequence[Union[int, float, complex, str, bytes, generic]],
20622064
# Sequence[Sequence[Any]], _SupportsArray]"

pandas/core/internals/blocks.py

+3-1
Original file line numberDiff line numberDiff line change
@@ -1892,7 +1892,9 @@ def get_block_type(values, dtype: Dtype | None = None):
18921892
cls = ExtensionBlock
18931893
elif isinstance(dtype, CategoricalDtype):
18941894
cls = CategoricalBlock
1895-
elif vtype is Timestamp:
1895+
# error: Non-overlapping identity check (left operand type: "Type[generic]",
1896+
# right operand type: "Type[Timestamp]")
1897+
elif vtype is Timestamp: # type: ignore[comparison-overlap]
18961898
cls = DatetimeTZBlock
18971899
elif isinstance(dtype, ExtensionDtype):
18981900
# Note: need to be sure PandasArray is unwrapped before we get here

pandas/core/tools/datetimes.py

+13-6
Original file line numberDiff line numberDiff line change
@@ -628,16 +628,16 @@ def _adjust_to_origin(arg, origin, unit):
628628

629629
if offset.tz is not None:
630630
raise ValueError(f"origin offset {offset} must be tz-naive")
631-
offset -= Timestamp(0)
631+
td_offset = offset - Timestamp(0)
632632

633633
# convert the offset to the unit of the arg
634634
# this should be lossless in terms of precision
635-
offset = offset // Timedelta(1, unit=unit)
635+
ioffset = td_offset // Timedelta(1, unit=unit)
636636

637637
# scalars & ndarray-like can handle the addition
638638
if is_list_like(arg) and not isinstance(arg, (ABCSeries, Index, np.ndarray)):
639639
arg = np.asarray(arg)
640-
arg = arg + offset
640+
arg = arg + ioffset
641641
return arg
642642

643643

@@ -887,13 +887,17 @@ def to_datetime(
887887
infer_datetime_format=infer_datetime_format,
888888
)
889889

890+
result: Timestamp | NaTType | Series | Index
891+
890892
if isinstance(arg, Timestamp):
891893
result = arg
892894
if tz is not None:
893895
if arg.tz is not None:
894-
result = result.tz_convert(tz)
896+
# error: Too many arguments for "tz_convert" of "NaTType"
897+
result = result.tz_convert(tz) # type: ignore[call-arg]
895898
else:
896-
result = result.tz_localize(tz)
899+
# error: Too many arguments for "tz_localize" of "NaTType"
900+
result = result.tz_localize(tz) # type: ignore[call-arg]
897901
elif isinstance(arg, ABCSeries):
898902
cache_array = _maybe_cache(arg, format, cache, convert_listlike)
899903
if not cache_array.empty:
@@ -928,7 +932,10 @@ def to_datetime(
928932
else:
929933
result = convert_listlike(np.array([arg]), format)[0]
930934

931-
return result
935+
# error: Incompatible return value type (got "Union[Timestamp, NaTType,
936+
# Series, Index]", expected "Union[DatetimeIndex, Series, float, str,
937+
# NaTType, None]")
938+
return result # type: ignore[return-value]
932939

933940

934941
# mappings for assembling units

pandas/io/excel/_odfreader.py

+3-7
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,4 @@
1-
from typing import (
2-
List,
3-
cast,
4-
)
1+
from typing import List
52

63
import numpy as np
74

@@ -200,10 +197,9 @@ def _get_cell_value(self, cell, convert_float: bool) -> Scalar:
200197
cell_value = cell.attributes.get((OFFICENS, "date-value"))
201198
return pd.to_datetime(cell_value)
202199
elif cell_type == "time":
203-
result = pd.to_datetime(str(cell))
204-
result = cast(pd.Timestamp, result)
200+
stamp = pd.to_datetime(str(cell))
205201
# error: Item "str" of "Union[float, str, NaTType]" has no attribute "time"
206-
return result.time() # type: ignore[union-attr]
202+
return stamp.time() # type: ignore[union-attr]
207203
else:
208204
self.close()
209205
raise ValueError(f"Unrecognized type {cell_type}")

pandas/tests/indexes/test_engines.py

+7-1
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,13 @@ class TestTimedeltaEngine:
6161
@pytest.mark.parametrize(
6262
"scalar",
6363
[
64-
pd.Timestamp(pd.Timedelta(days=42).asm8.view("datetime64[ns]")),
64+
# error: Argument 1 to "Timestamp" has incompatible type "timedelta64";
65+
# expected "Union[integer[Any], float, str, date, datetime64]"
66+
pd.Timestamp(
67+
pd.Timedelta(days=42).asm8.view(
68+
"datetime64[ns]"
69+
) # type: ignore[arg-type]
70+
),
6571
pd.Timedelta(days=42).value,
6672
pd.Timedelta(days=42).to_pytimedelta(),
6773
pd.Timedelta(days=42).to_timedelta64(),

pandas/tests/scalar/timestamp/test_constructors.py

+3-1
Original file line numberDiff line numberDiff line change
@@ -331,7 +331,9 @@ def test_constructor_fromordinal(self):
331331
tz="UTC",
332332
),
333333
Timestamp(2000, 1, 2, 3, 4, 5, 6, 1, None),
334-
Timestamp(2000, 1, 2, 3, 4, 5, 6, 1, pytz.UTC),
334+
# error: Argument 9 to "Timestamp" has incompatible type "_UTCclass";
335+
# expected "Optional[int]"
336+
Timestamp(2000, 1, 2, 3, 4, 5, 6, 1, pytz.UTC), # type: ignore[arg-type]
335337
],
336338
)
337339
def test_constructor_nanosecond(self, result):

0 commit comments

Comments
 (0)