JustinTX commited on
Commit
3a8a63a
·
verified ·
1 Parent(s): 2fb2e00

Add files using upload-large-folder tool

Browse files
Files changed (50) hide show
  1. py311/lib/python3.11/site-packages/pandas/tests/frame/constructors/__init__.py +0 -0
  2. py311/lib/python3.11/site-packages/pandas/tests/frame/constructors/test_from_dict.py +223 -0
  3. py311/lib/python3.11/site-packages/pandas/tests/frame/constructors/test_from_records.py +503 -0
  4. py311/lib/python3.11/site-packages/pandas/tests/frame/methods/test_add_prefix_suffix.py +49 -0
  5. py311/lib/python3.11/site-packages/pandas/tests/frame/methods/test_align.py +484 -0
  6. py311/lib/python3.11/site-packages/pandas/tests/frame/methods/test_at_time.py +132 -0
  7. py311/lib/python3.11/site-packages/pandas/tests/frame/methods/test_between_time.py +227 -0
  8. py311/lib/python3.11/site-packages/pandas/tests/frame/methods/test_combine.py +47 -0
  9. py311/lib/python3.11/site-packages/pandas/tests/frame/methods/test_combine_first.py +556 -0
  10. py311/lib/python3.11/site-packages/pandas/tests/frame/methods/test_droplevel.py +36 -0
  11. py311/lib/python3.11/site-packages/pandas/tests/frame/methods/test_fillna.py +916 -0
  12. py311/lib/python3.11/site-packages/pandas/tests/frame/methods/test_filter.py +153 -0
  13. py311/lib/python3.11/site-packages/pandas/tests/frame/methods/test_iterrows.py +16 -0
  14. py311/lib/python3.11/site-packages/pandas/tests/frame/methods/test_join.py +576 -0
  15. py311/lib/python3.11/site-packages/pandas/tests/frame/methods/test_reindex.py +1327 -0
  16. py311/lib/python3.11/site-packages/pandas/tests/frame/methods/test_rename.py +415 -0
  17. py311/lib/python3.11/site-packages/pandas/tests/frame/methods/test_reorder_levels.py +74 -0
  18. py311/lib/python3.11/site-packages/pandas/tests/frame/methods/test_shift.py +764 -0
  19. py311/lib/python3.11/site-packages/pandas/tests/frame/methods/test_swaplevel.py +36 -0
  20. py311/lib/python3.11/site-packages/pandas/tests/frame/methods/test_to_dict_of_blocks.py +79 -0
  21. py311/lib/python3.11/site-packages/pandas/tests/frame/methods/test_tz_convert.py +131 -0
  22. py311/lib/python3.11/site-packages/pandas/tests/frame/methods/test_values.py +280 -0
  23. py311/lib/python3.11/site-packages/pandas/tests/scalar/interval/test_arithmetic.py +192 -0
  24. py311/lib/python3.11/site-packages/pandas/tests/scalar/period/__init__.py +0 -0
  25. py311/lib/python3.11/site-packages/pandas/tests/scalar/period/test_arithmetic.py +486 -0
  26. py311/lib/python3.11/site-packages/pandas/tests/scalar/period/test_asfreq.py +828 -0
  27. py311/lib/python3.11/site-packages/pandas/tests/scalar/period/test_period.py +1158 -0
  28. py311/lib/python3.11/site-packages/pandas/tests/scalar/timedelta/__init__.py +0 -0
  29. py311/lib/python3.11/site-packages/pandas/tests/scalar/timedelta/methods/__init__.py +0 -0
  30. py311/lib/python3.11/site-packages/pandas/tests/scalar/timedelta/methods/test_as_unit.py +80 -0
  31. py311/lib/python3.11/site-packages/pandas/tests/scalar/timedelta/methods/test_round.py +187 -0
  32. py311/lib/python3.11/site-packages/pandas/tests/scalar/timedelta/test_arithmetic.py +1183 -0
  33. py311/lib/python3.11/site-packages/pandas/tests/scalar/timedelta/test_constructors.py +698 -0
  34. py311/lib/python3.11/site-packages/pandas/tests/scalar/timedelta/test_formats.py +109 -0
  35. py311/lib/python3.11/site-packages/pandas/tests/scalar/timedelta/test_timedelta.py +666 -0
  36. py311/lib/python3.11/site-packages/pandas/tests/scalar/timestamp/__init__.py +0 -0
  37. py311/lib/python3.11/site-packages/pandas/tests/scalar/timestamp/methods/__init__.py +0 -0
  38. py311/lib/python3.11/site-packages/pandas/tests/scalar/timestamp/methods/test_as_unit.py +86 -0
  39. py311/lib/python3.11/site-packages/pandas/tests/scalar/timestamp/methods/test_normalize.py +22 -0
  40. py311/lib/python3.11/site-packages/pandas/tests/scalar/timestamp/methods/test_replace.py +193 -0
  41. py311/lib/python3.11/site-packages/pandas/tests/scalar/timestamp/methods/test_round.py +383 -0
  42. py311/lib/python3.11/site-packages/pandas/tests/scalar/timestamp/methods/test_timestamp_method.py +31 -0
  43. py311/lib/python3.11/site-packages/pandas/tests/scalar/timestamp/methods/test_to_julian_date.py +28 -0
  44. py311/lib/python3.11/site-packages/pandas/tests/scalar/timestamp/methods/test_to_pydatetime.py +81 -0
  45. py311/lib/python3.11/site-packages/pandas/tests/scalar/timestamp/methods/test_tz_convert.py +51 -0
  46. py311/lib/python3.11/site-packages/pandas/tests/scalar/timestamp/methods/test_tz_localize.py +351 -0
  47. py311/lib/python3.11/site-packages/pandas/tests/scalar/timestamp/test_arithmetic.py +334 -0
  48. py311/lib/python3.11/site-packages/pandas/tests/scalar/timestamp/test_comparisons.py +313 -0
  49. py311/lib/python3.11/site-packages/pandas/tests/scalar/timestamp/test_constructors.py +1077 -0
  50. py311/lib/python3.11/site-packages/pandas/tests/scalar/timestamp/test_timestamp.py +928 -0
py311/lib/python3.11/site-packages/pandas/tests/frame/constructors/__init__.py ADDED
File without changes
py311/lib/python3.11/site-packages/pandas/tests/frame/constructors/test_from_dict.py ADDED
@@ -0,0 +1,223 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from collections import OrderedDict
2
+
3
+ import numpy as np
4
+ import pytest
5
+
6
+ from pandas import (
7
+ DataFrame,
8
+ Index,
9
+ MultiIndex,
10
+ RangeIndex,
11
+ Series,
12
+ )
13
+ import pandas._testing as tm
14
+
15
+
16
+ class TestFromDict:
17
+ # Note: these tests are specific to the from_dict method, not for
18
+ # passing dictionaries to DataFrame.__init__
19
+
20
+ def test_constructor_list_of_odicts(self):
21
+ data = [
22
+ OrderedDict([["a", 1.5], ["b", 3], ["c", 4], ["d", 6]]),
23
+ OrderedDict([["a", 1.5], ["b", 3], ["d", 6]]),
24
+ OrderedDict([["a", 1.5], ["d", 6]]),
25
+ OrderedDict(),
26
+ OrderedDict([["a", 1.5], ["b", 3], ["c", 4]]),
27
+ OrderedDict([["b", 3], ["c", 4], ["d", 6]]),
28
+ ]
29
+
30
+ result = DataFrame(data)
31
+ expected = DataFrame.from_dict(
32
+ dict(zip(range(len(data)), data)), orient="index"
33
+ )
34
+ tm.assert_frame_equal(result, expected.reindex(result.index))
35
+
36
+ def test_constructor_single_row(self):
37
+ data = [OrderedDict([["a", 1.5], ["b", 3], ["c", 4], ["d", 6]])]
38
+
39
+ result = DataFrame(data)
40
+ expected = DataFrame.from_dict(dict(zip([0], data)), orient="index").reindex(
41
+ result.index
42
+ )
43
+ tm.assert_frame_equal(result, expected)
44
+
45
+ def test_constructor_list_of_series(self):
46
+ data = [
47
+ OrderedDict([["a", 1.5], ["b", 3.0], ["c", 4.0]]),
48
+ OrderedDict([["a", 1.5], ["b", 3.0], ["c", 6.0]]),
49
+ ]
50
+ sdict = OrderedDict(zip(["x", "y"], data))
51
+ idx = Index(["a", "b", "c"])
52
+
53
+ # all named
54
+ data2 = [
55
+ Series([1.5, 3, 4], idx, dtype="O", name="x"),
56
+ Series([1.5, 3, 6], idx, name="y"),
57
+ ]
58
+ result = DataFrame(data2)
59
+ expected = DataFrame.from_dict(sdict, orient="index")
60
+ tm.assert_frame_equal(result, expected)
61
+
62
+ # some unnamed
63
+ data2 = [
64
+ Series([1.5, 3, 4], idx, dtype="O", name="x"),
65
+ Series([1.5, 3, 6], idx),
66
+ ]
67
+ result = DataFrame(data2)
68
+
69
+ sdict = OrderedDict(zip(["x", "Unnamed 0"], data))
70
+ expected = DataFrame.from_dict(sdict, orient="index")
71
+ tm.assert_frame_equal(result, expected)
72
+
73
+ # none named
74
+ data = [
75
+ OrderedDict([["a", 1.5], ["b", 3], ["c", 4], ["d", 6]]),
76
+ OrderedDict([["a", 1.5], ["b", 3], ["d", 6]]),
77
+ OrderedDict([["a", 1.5], ["d", 6]]),
78
+ OrderedDict(),
79
+ OrderedDict([["a", 1.5], ["b", 3], ["c", 4]]),
80
+ OrderedDict([["b", 3], ["c", 4], ["d", 6]]),
81
+ ]
82
+ data = [Series(d) for d in data]
83
+
84
+ result = DataFrame(data)
85
+ sdict = OrderedDict(zip(range(len(data)), data))
86
+ expected = DataFrame.from_dict(sdict, orient="index")
87
+ tm.assert_frame_equal(result, expected.reindex(result.index))
88
+
89
+ result2 = DataFrame(data, index=np.arange(6, dtype=np.int64))
90
+ tm.assert_frame_equal(result, result2)
91
+
92
+ result = DataFrame([Series(dtype=object)])
93
+ expected = DataFrame(index=[0])
94
+ tm.assert_frame_equal(result, expected)
95
+
96
+ data = [
97
+ OrderedDict([["a", 1.5], ["b", 3.0], ["c", 4.0]]),
98
+ OrderedDict([["a", 1.5], ["b", 3.0], ["c", 6.0]]),
99
+ ]
100
+ sdict = OrderedDict(zip(range(len(data)), data))
101
+
102
+ idx = Index(["a", "b", "c"])
103
+ data2 = [Series([1.5, 3, 4], idx, dtype="O"), Series([1.5, 3, 6], idx)]
104
+ result = DataFrame(data2)
105
+ expected = DataFrame.from_dict(sdict, orient="index")
106
+ tm.assert_frame_equal(result, expected)
107
+
108
+ def test_constructor_orient(self, float_string_frame):
109
+ data_dict = float_string_frame.T._series
110
+ recons = DataFrame.from_dict(data_dict, orient="index")
111
+ expected = float_string_frame.reindex(index=recons.index)
112
+ tm.assert_frame_equal(recons, expected)
113
+
114
+ # dict of sequence
115
+ a = {"hi": [32, 3, 3], "there": [3, 5, 3]}
116
+ rs = DataFrame.from_dict(a, orient="index")
117
+ xp = DataFrame.from_dict(a).T.reindex(list(a.keys()))
118
+ tm.assert_frame_equal(rs, xp)
119
+
120
+ def test_constructor_from_ordered_dict(self):
121
+ # GH#8425
122
+ a = OrderedDict(
123
+ [
124
+ ("one", OrderedDict([("col_a", "foo1"), ("col_b", "bar1")])),
125
+ ("two", OrderedDict([("col_a", "foo2"), ("col_b", "bar2")])),
126
+ ("three", OrderedDict([("col_a", "foo3"), ("col_b", "bar3")])),
127
+ ]
128
+ )
129
+ expected = DataFrame.from_dict(a, orient="columns").T
130
+ result = DataFrame.from_dict(a, orient="index")
131
+ tm.assert_frame_equal(result, expected)
132
+
133
+ def test_from_dict_columns_parameter(self):
134
+ # GH#18529
135
+ # Test new columns parameter for from_dict that was added to make
136
+ # from_items(..., orient='index', columns=[...]) easier to replicate
137
+ result = DataFrame.from_dict(
138
+ OrderedDict([("A", [1, 2]), ("B", [4, 5])]),
139
+ orient="index",
140
+ columns=["one", "two"],
141
+ )
142
+ expected = DataFrame([[1, 2], [4, 5]], index=["A", "B"], columns=["one", "two"])
143
+ tm.assert_frame_equal(result, expected)
144
+
145
+ msg = "cannot use columns parameter with orient='columns'"
146
+ with pytest.raises(ValueError, match=msg):
147
+ DataFrame.from_dict(
148
+ {"A": [1, 2], "B": [4, 5]},
149
+ orient="columns",
150
+ columns=["one", "two"],
151
+ )
152
+ with pytest.raises(ValueError, match=msg):
153
+ DataFrame.from_dict({"A": [1, 2], "B": [4, 5]}, columns=["one", "two"])
154
+
155
+ @pytest.mark.parametrize(
156
+ "data_dict, orient, expected",
157
+ [
158
+ ({}, "index", RangeIndex(0)),
159
+ (
160
+ [{("a",): 1}, {("a",): 2}],
161
+ "columns",
162
+ Index([("a",)], tupleize_cols=False),
163
+ ),
164
+ (
165
+ [OrderedDict([(("a",), 1), (("b",), 2)])],
166
+ "columns",
167
+ Index([("a",), ("b",)], tupleize_cols=False),
168
+ ),
169
+ ([{("a", "b"): 1}], "columns", Index([("a", "b")], tupleize_cols=False)),
170
+ ],
171
+ )
172
+ def test_constructor_from_dict_tuples(self, data_dict, orient, expected):
173
+ # GH#16769
174
+ df = DataFrame.from_dict(data_dict, orient)
175
+ result = df.columns
176
+ tm.assert_index_equal(result, expected)
177
+
178
+ def test_frame_dict_constructor_empty_series(self):
179
+ s1 = Series(
180
+ [1, 2, 3, 4], index=MultiIndex.from_tuples([(1, 2), (1, 3), (2, 2), (2, 4)])
181
+ )
182
+ s2 = Series(
183
+ [1, 2, 3, 4], index=MultiIndex.from_tuples([(1, 2), (1, 3), (3, 2), (3, 4)])
184
+ )
185
+ s3 = Series(dtype=object)
186
+
187
+ # it works!
188
+ DataFrame({"foo": s1, "bar": s2, "baz": s3})
189
+ DataFrame.from_dict({"foo": s1, "baz": s3, "bar": s2})
190
+
191
+ def test_from_dict_scalars_requires_index(self):
192
+ msg = "If using all scalar values, you must pass an index"
193
+ with pytest.raises(ValueError, match=msg):
194
+ DataFrame.from_dict(OrderedDict([("b", 8), ("a", 5), ("a", 6)]))
195
+
196
+ def test_from_dict_orient_invalid(self):
197
+ msg = (
198
+ "Expected 'index', 'columns' or 'tight' for orient parameter. "
199
+ "Got 'abc' instead"
200
+ )
201
+ with pytest.raises(ValueError, match=msg):
202
+ DataFrame.from_dict({"foo": 1, "baz": 3, "bar": 2}, orient="abc")
203
+
204
+ def test_from_dict_order_with_single_column(self):
205
+ data = {
206
+ "alpha": {
207
+ "value2": 123,
208
+ "value1": 532,
209
+ "animal": 222,
210
+ "plant": False,
211
+ "name": "test",
212
+ }
213
+ }
214
+ result = DataFrame.from_dict(
215
+ data,
216
+ orient="columns",
217
+ )
218
+ expected = DataFrame(
219
+ [[123], [532], [222], [False], ["test"]],
220
+ index=["value2", "value1", "animal", "plant", "name"],
221
+ columns=["alpha"],
222
+ )
223
+ tm.assert_frame_equal(result, expected)
py311/lib/python3.11/site-packages/pandas/tests/frame/constructors/test_from_records.py ADDED
@@ -0,0 +1,503 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from collections.abc import Iterator
2
+ from datetime import datetime
3
+ from decimal import Decimal
4
+
5
+ import numpy as np
6
+ import pytest
7
+ import pytz
8
+
9
+ from pandas._config import using_string_dtype
10
+
11
+ from pandas.compat import is_platform_little_endian
12
+
13
+ from pandas import (
14
+ CategoricalIndex,
15
+ DataFrame,
16
+ Index,
17
+ Interval,
18
+ RangeIndex,
19
+ Series,
20
+ date_range,
21
+ )
22
+ import pandas._testing as tm
23
+
24
+
25
+ class TestFromRecords:
26
+ def test_from_records_dt64tz_frame(self):
27
+ # GH#51162 don't lose tz when calling from_records with DataFrame input
28
+ dti = date_range("2016-01-01", periods=10, tz="US/Pacific")
29
+ df = DataFrame({i: dti for i in range(4)})
30
+ with tm.assert_produces_warning(FutureWarning):
31
+ res = DataFrame.from_records(df)
32
+ tm.assert_frame_equal(res, df)
33
+
34
+ def test_from_records_with_datetimes(self):
35
+ # this may fail on certain platforms because of a numpy issue
36
+ # related GH#6140
37
+ if not is_platform_little_endian():
38
+ pytest.skip("known failure of test on non-little endian")
39
+
40
+ # construction with a null in a recarray
41
+ # GH#6140
42
+ expected = DataFrame({"EXPIRY": [datetime(2005, 3, 1, 0, 0), None]})
43
+
44
+ arrdata = [np.array([datetime(2005, 3, 1, 0, 0), None])]
45
+ dtypes = [("EXPIRY", "<M8[ns]")]
46
+
47
+ recarray = np.rec.fromarrays(arrdata, dtype=dtypes)
48
+
49
+ result = DataFrame.from_records(recarray)
50
+ tm.assert_frame_equal(result, expected)
51
+
52
+ # coercion should work too
53
+ arrdata = [np.array([datetime(2005, 3, 1, 0, 0), None])]
54
+ dtypes = [("EXPIRY", "<M8[m]")]
55
+ recarray = np.rec.fromarrays(arrdata, dtype=dtypes)
56
+ result = DataFrame.from_records(recarray)
57
+ # we get the closest supported unit, "s"
58
+ expected["EXPIRY"] = expected["EXPIRY"].astype("M8[s]")
59
+ tm.assert_frame_equal(result, expected)
60
+
61
+ @pytest.mark.xfail(using_string_dtype(), reason="dtype checking logic doesn't work")
62
+ def test_from_records_sequencelike(self):
63
+ df = DataFrame(
64
+ {
65
+ "A": np.array(
66
+ np.random.default_rng(2).standard_normal(6), dtype=np.float64
67
+ ),
68
+ "A1": np.array(
69
+ np.random.default_rng(2).standard_normal(6), dtype=np.float64
70
+ ),
71
+ "B": np.array(np.arange(6), dtype=np.int64),
72
+ "C": ["foo"] * 6,
73
+ "D": np.array([True, False] * 3, dtype=bool),
74
+ "E": np.array(
75
+ np.random.default_rng(2).standard_normal(6), dtype=np.float32
76
+ ),
77
+ "E1": np.array(
78
+ np.random.default_rng(2).standard_normal(6), dtype=np.float32
79
+ ),
80
+ "F": np.array(np.arange(6), dtype=np.int32),
81
+ }
82
+ )
83
+
84
+ # this is actually tricky to create the recordlike arrays and
85
+ # have the dtypes be intact
86
+ blocks = df._to_dict_of_blocks()
87
+ tuples = []
88
+ columns = []
89
+ dtypes = []
90
+ for dtype, b in blocks.items():
91
+ columns.extend(b.columns)
92
+ dtypes.extend([(c, np.dtype(dtype).descr[0][1]) for c in b.columns])
93
+ for i in range(len(df.index)):
94
+ tup = []
95
+ for _, b in blocks.items():
96
+ tup.extend(b.iloc[i].values)
97
+ tuples.append(tuple(tup))
98
+
99
+ recarray = np.array(tuples, dtype=dtypes).view(np.rec.recarray)
100
+ recarray2 = df.to_records()
101
+ lists = [list(x) for x in tuples]
102
+
103
+ # tuples (lose the dtype info)
104
+ result = DataFrame.from_records(tuples, columns=columns).reindex(
105
+ columns=df.columns
106
+ )
107
+
108
+ # created recarray and with to_records recarray (have dtype info)
109
+ result2 = DataFrame.from_records(recarray, columns=columns).reindex(
110
+ columns=df.columns
111
+ )
112
+ result3 = DataFrame.from_records(recarray2, columns=columns).reindex(
113
+ columns=df.columns
114
+ )
115
+
116
+ # list of tuples (no dtype info)
117
+ result4 = DataFrame.from_records(lists, columns=columns).reindex(
118
+ columns=df.columns
119
+ )
120
+
121
+ tm.assert_frame_equal(result, df, check_dtype=False)
122
+ tm.assert_frame_equal(result2, df)
123
+ tm.assert_frame_equal(result3, df)
124
+ tm.assert_frame_equal(result4, df, check_dtype=False)
125
+
126
+ # tuples is in the order of the columns
127
+ result = DataFrame.from_records(tuples)
128
+ tm.assert_index_equal(result.columns, RangeIndex(8))
129
+
130
+ # test exclude parameter & we are casting the results here (as we don't
131
+ # have dtype info to recover)
132
+ columns_to_test = [columns.index("C"), columns.index("E1")]
133
+
134
+ exclude = list(set(range(8)) - set(columns_to_test))
135
+ result = DataFrame.from_records(tuples, exclude=exclude)
136
+ result.columns = [columns[i] for i in sorted(columns_to_test)]
137
+ tm.assert_series_equal(result["C"], df["C"])
138
+ tm.assert_series_equal(result["E1"], df["E1"])
139
+
140
+ def test_from_records_sequencelike_empty(self):
141
+ # empty case
142
+ result = DataFrame.from_records([], columns=["foo", "bar", "baz"])
143
+ assert len(result) == 0
144
+ tm.assert_index_equal(result.columns, Index(["foo", "bar", "baz"]))
145
+
146
+ result = DataFrame.from_records([])
147
+ assert len(result) == 0
148
+ assert len(result.columns) == 0
149
+
150
+ def test_from_records_dictlike(self):
151
+ # test the dict methods
152
+ df = DataFrame(
153
+ {
154
+ "A": np.array(
155
+ np.random.default_rng(2).standard_normal(6), dtype=np.float64
156
+ ),
157
+ "A1": np.array(
158
+ np.random.default_rng(2).standard_normal(6), dtype=np.float64
159
+ ),
160
+ "B": np.array(np.arange(6), dtype=np.int64),
161
+ "C": ["foo"] * 6,
162
+ "D": np.array([True, False] * 3, dtype=bool),
163
+ "E": np.array(
164
+ np.random.default_rng(2).standard_normal(6), dtype=np.float32
165
+ ),
166
+ "E1": np.array(
167
+ np.random.default_rng(2).standard_normal(6), dtype=np.float32
168
+ ),
169
+ "F": np.array(np.arange(6), dtype=np.int32),
170
+ }
171
+ )
172
+
173
+ # columns is in a different order here than the actual items iterated
174
+ # from the dict
175
+ blocks = df._to_dict_of_blocks()
176
+ columns = []
177
+ for b in blocks.values():
178
+ columns.extend(b.columns)
179
+
180
+ asdict = dict(df.items())
181
+ asdict2 = {x: y.values for x, y in df.items()}
182
+
183
+ # dict of series & dict of ndarrays (have dtype info)
184
+ results = []
185
+ results.append(DataFrame.from_records(asdict).reindex(columns=df.columns))
186
+ results.append(
187
+ DataFrame.from_records(asdict, columns=columns).reindex(columns=df.columns)
188
+ )
189
+ results.append(
190
+ DataFrame.from_records(asdict2, columns=columns).reindex(columns=df.columns)
191
+ )
192
+
193
+ for r in results:
194
+ tm.assert_frame_equal(r, df)
195
+
196
+ def test_from_records_with_index_data(self):
197
+ df = DataFrame(
198
+ np.random.default_rng(2).standard_normal((10, 3)), columns=["A", "B", "C"]
199
+ )
200
+
201
+ data = np.random.default_rng(2).standard_normal(10)
202
+ with tm.assert_produces_warning(FutureWarning):
203
+ df1 = DataFrame.from_records(df, index=data)
204
+ tm.assert_index_equal(df1.index, Index(data))
205
+
206
+ def test_from_records_bad_index_column(self):
207
+ df = DataFrame(
208
+ np.random.default_rng(2).standard_normal((10, 3)), columns=["A", "B", "C"]
209
+ )
210
+
211
+ # should pass
212
+ with tm.assert_produces_warning(FutureWarning):
213
+ df1 = DataFrame.from_records(df, index=["C"])
214
+ tm.assert_index_equal(df1.index, Index(df.C))
215
+
216
+ with tm.assert_produces_warning(FutureWarning):
217
+ df1 = DataFrame.from_records(df, index="C")
218
+ tm.assert_index_equal(df1.index, Index(df.C))
219
+
220
+ # should fail
221
+ msg = "|".join(
222
+ [
223
+ r"'None of \[2\] are in the columns'",
224
+ ]
225
+ )
226
+ with pytest.raises(KeyError, match=msg):
227
+ with tm.assert_produces_warning(FutureWarning):
228
+ DataFrame.from_records(df, index=[2])
229
+ with pytest.raises(KeyError, match=msg):
230
+ with tm.assert_produces_warning(FutureWarning):
231
+ DataFrame.from_records(df, index=2)
232
+
233
+ def test_from_records_non_tuple(self):
234
+ class Record:
235
+ def __init__(self, *args) -> None:
236
+ self.args = args
237
+
238
+ def __getitem__(self, i):
239
+ return self.args[i]
240
+
241
+ def __iter__(self) -> Iterator:
242
+ return iter(self.args)
243
+
244
+ recs = [Record(1, 2, 3), Record(4, 5, 6), Record(7, 8, 9)]
245
+ tups = [tuple(rec) for rec in recs]
246
+
247
+ result = DataFrame.from_records(recs)
248
+ expected = DataFrame.from_records(tups)
249
+ tm.assert_frame_equal(result, expected)
250
+
251
+ def test_from_records_len0_with_columns(self):
252
+ # GH#2633
253
+ result = DataFrame.from_records([], index="foo", columns=["foo", "bar"])
254
+ expected = Index(["bar"])
255
+
256
+ assert len(result) == 0
257
+ assert result.index.name == "foo"
258
+ tm.assert_index_equal(result.columns, expected)
259
+
260
+ def test_from_records_series_list_dict(self):
261
+ # GH#27358
262
+ expected = DataFrame([[{"a": 1, "b": 2}, {"a": 3, "b": 4}]]).T
263
+ data = Series([[{"a": 1, "b": 2}], [{"a": 3, "b": 4}]])
264
+ result = DataFrame.from_records(data)
265
+ tm.assert_frame_equal(result, expected)
266
+
267
+ def test_from_records_series_categorical_index(self):
268
+ # GH#32805
269
+ index = CategoricalIndex(
270
+ [Interval(-20, -10), Interval(-10, 0), Interval(0, 10)]
271
+ )
272
+ series_of_dicts = Series([{"a": 1}, {"a": 2}, {"b": 3}], index=index)
273
+ frame = DataFrame.from_records(series_of_dicts, index=index)
274
+ expected = DataFrame(
275
+ {"a": [1, 2, np.nan], "b": [np.nan, np.nan, 3]}, index=index
276
+ )
277
+ tm.assert_frame_equal(frame, expected)
278
+
279
+ def test_frame_from_records_utc(self):
280
+ rec = {"datum": 1.5, "begin_time": datetime(2006, 4, 27, tzinfo=pytz.utc)}
281
+
282
+ # it works
283
+ DataFrame.from_records([rec], index="begin_time")
284
+
285
+ def test_from_records_to_records(self):
286
+ # from numpy documentation
287
+ arr = np.zeros((2,), dtype=("i4,f4,S10"))
288
+ arr[:] = [(1, 2.0, "Hello"), (2, 3.0, "World")]
289
+
290
+ DataFrame.from_records(arr)
291
+
292
+ index = Index(np.arange(len(arr))[::-1])
293
+ indexed_frame = DataFrame.from_records(arr, index=index)
294
+ tm.assert_index_equal(indexed_frame.index, index)
295
+
296
+ # without names, it should go to last ditch
297
+ arr2 = np.zeros((2, 3))
298
+ tm.assert_frame_equal(DataFrame.from_records(arr2), DataFrame(arr2))
299
+
300
+ # wrong length
301
+ msg = "|".join(
302
+ [
303
+ r"Length of values \(2\) does not match length of index \(1\)",
304
+ ]
305
+ )
306
+ with pytest.raises(ValueError, match=msg):
307
+ DataFrame.from_records(arr, index=index[:-1])
308
+
309
+ indexed_frame = DataFrame.from_records(arr, index="f1")
310
+
311
+ # what to do?
312
+ records = indexed_frame.to_records()
313
+ assert len(records.dtype.names) == 3
314
+
315
+ records = indexed_frame.to_records(index=False)
316
+ assert len(records.dtype.names) == 2
317
+ assert "index" not in records.dtype.names
318
+
319
+ def test_from_records_nones(self):
320
+ tuples = [(1, 2, None, 3), (1, 2, None, 3), (None, 2, 5, 3)]
321
+
322
+ df = DataFrame.from_records(tuples, columns=["a", "b", "c", "d"])
323
+ assert np.isnan(df["c"][0])
324
+
325
+ def test_from_records_iterator(self):
326
+ arr = np.array(
327
+ [(1.0, 1.0, 2, 2), (3.0, 3.0, 4, 4), (5.0, 5.0, 6, 6), (7.0, 7.0, 8, 8)],
328
+ dtype=[
329
+ ("x", np.float64),
330
+ ("u", np.float32),
331
+ ("y", np.int64),
332
+ ("z", np.int32),
333
+ ],
334
+ )
335
+ df = DataFrame.from_records(iter(arr), nrows=2)
336
+ xp = DataFrame(
337
+ {
338
+ "x": np.array([1.0, 3.0], dtype=np.float64),
339
+ "u": np.array([1.0, 3.0], dtype=np.float32),
340
+ "y": np.array([2, 4], dtype=np.int64),
341
+ "z": np.array([2, 4], dtype=np.int32),
342
+ }
343
+ )
344
+ tm.assert_frame_equal(df.reindex_like(xp), xp)
345
+
346
+ # no dtypes specified here, so just compare with the default
347
+ arr = [(1.0, 2), (3.0, 4), (5.0, 6), (7.0, 8)]
348
+ df = DataFrame.from_records(iter(arr), columns=["x", "y"], nrows=2)
349
+ tm.assert_frame_equal(df, xp.reindex(columns=["x", "y"]), check_dtype=False)
350
+
351
+ def test_from_records_tuples_generator(self):
352
+ def tuple_generator(length):
353
+ for i in range(length):
354
+ letters = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
355
+ yield (i, letters[i % len(letters)], i / length)
356
+
357
+ columns_names = ["Integer", "String", "Float"]
358
+ columns = [
359
+ [i[j] for i in tuple_generator(10)] for j in range(len(columns_names))
360
+ ]
361
+ data = {"Integer": columns[0], "String": columns[1], "Float": columns[2]}
362
+ expected = DataFrame(data, columns=columns_names)
363
+
364
+ generator = tuple_generator(10)
365
+ result = DataFrame.from_records(generator, columns=columns_names)
366
+ tm.assert_frame_equal(result, expected)
367
+
368
+ def test_from_records_lists_generator(self):
369
+ def list_generator(length):
370
+ for i in range(length):
371
+ letters = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
372
+ yield [i, letters[i % len(letters)], i / length]
373
+
374
+ columns_names = ["Integer", "String", "Float"]
375
+ columns = [
376
+ [i[j] for i in list_generator(10)] for j in range(len(columns_names))
377
+ ]
378
+ data = {"Integer": columns[0], "String": columns[1], "Float": columns[2]}
379
+ expected = DataFrame(data, columns=columns_names)
380
+
381
+ generator = list_generator(10)
382
+ result = DataFrame.from_records(generator, columns=columns_names)
383
+ tm.assert_frame_equal(result, expected)
384
+
385
+ def test_from_records_columns_not_modified(self):
386
+ tuples = [(1, 2, 3), (1, 2, 3), (2, 5, 3)]
387
+
388
+ columns = ["a", "b", "c"]
389
+ original_columns = list(columns)
390
+
391
+ DataFrame.from_records(tuples, columns=columns, index="a")
392
+
393
+ assert columns == original_columns
394
+
395
+ def test_from_records_decimal(self):
396
+ tuples = [(Decimal("1.5"),), (Decimal("2.5"),), (None,)]
397
+
398
+ df = DataFrame.from_records(tuples, columns=["a"])
399
+ assert df["a"].dtype == object
400
+
401
+ df = DataFrame.from_records(tuples, columns=["a"], coerce_float=True)
402
+ assert df["a"].dtype == np.float64
403
+ assert np.isnan(df["a"].values[-1])
404
+
405
+ def test_from_records_duplicates(self):
406
+ result = DataFrame.from_records([(1, 2, 3), (4, 5, 6)], columns=["a", "b", "a"])
407
+
408
+ expected = DataFrame([(1, 2, 3), (4, 5, 6)], columns=["a", "b", "a"])
409
+
410
+ tm.assert_frame_equal(result, expected)
411
+
412
+ def test_from_records_set_index_name(self):
413
+ def create_dict(order_id):
414
+ return {
415
+ "order_id": order_id,
416
+ "quantity": np.random.default_rng(2).integers(1, 10),
417
+ "price": np.random.default_rng(2).integers(1, 10),
418
+ }
419
+
420
+ documents = [create_dict(i) for i in range(10)]
421
+ # demo missing data
422
+ documents.append({"order_id": 10, "quantity": 5})
423
+
424
+ result = DataFrame.from_records(documents, index="order_id")
425
+ assert result.index.name == "order_id"
426
+
427
+ # MultiIndex
428
+ result = DataFrame.from_records(documents, index=["order_id", "quantity"])
429
+ assert result.index.names == ("order_id", "quantity")
430
+
431
+ def test_from_records_misc_brokenness(self):
432
+ # GH#2179
433
+
434
+ data = {1: ["foo"], 2: ["bar"]}
435
+
436
+ result = DataFrame.from_records(data, columns=["a", "b"])
437
+ exp = DataFrame(data, columns=["a", "b"])
438
+ tm.assert_frame_equal(result, exp)
439
+
440
+ # overlap in index/index_names
441
+
442
+ data = {"a": [1, 2, 3], "b": [4, 5, 6]}
443
+
444
+ result = DataFrame.from_records(data, index=["a", "b", "c"])
445
+ exp = DataFrame(data, index=["a", "b", "c"])
446
+ tm.assert_frame_equal(result, exp)
447
+
448
+ def test_from_records_misc_brokenness2(self):
449
+ # GH#2623
450
+ rows = []
451
+ rows.append([datetime(2010, 1, 1), 1])
452
+ rows.append([datetime(2010, 1, 2), "hi"]) # test col upconverts to obj
453
+ result = DataFrame.from_records(rows, columns=["date", "test"])
454
+ expected = DataFrame(
455
+ {"date": [row[0] for row in rows], "test": [row[1] for row in rows]}
456
+ )
457
+ tm.assert_frame_equal(result, expected)
458
+ assert result.dtypes["test"] == np.dtype(object)
459
+
460
+ def test_from_records_misc_brokenness3(self):
461
+ rows = []
462
+ rows.append([datetime(2010, 1, 1), 1])
463
+ rows.append([datetime(2010, 1, 2), 1])
464
+ result = DataFrame.from_records(rows, columns=["date", "test"])
465
+ expected = DataFrame(
466
+ {"date": [row[0] for row in rows], "test": [row[1] for row in rows]}
467
+ )
468
+ tm.assert_frame_equal(result, expected)
469
+
470
+ def test_from_records_empty(self):
471
+ # GH#3562
472
+ result = DataFrame.from_records([], columns=["a", "b", "c"])
473
+ expected = DataFrame(columns=["a", "b", "c"])
474
+ tm.assert_frame_equal(result, expected)
475
+
476
+ result = DataFrame.from_records([], columns=["a", "b", "b"])
477
+ expected = DataFrame(columns=["a", "b", "b"])
478
+ tm.assert_frame_equal(result, expected)
479
+
480
+ def test_from_records_empty_with_nonempty_fields_gh3682(self):
481
+ a = np.array([(1, 2)], dtype=[("id", np.int64), ("value", np.int64)])
482
+ df = DataFrame.from_records(a, index="id")
483
+
484
+ ex_index = Index([1], name="id")
485
+ expected = DataFrame({"value": [2]}, index=ex_index, columns=["value"])
486
+ tm.assert_frame_equal(df, expected)
487
+
488
+ b = a[:0]
489
+ df2 = DataFrame.from_records(b, index="id")
490
+ tm.assert_frame_equal(df2, df.iloc[:0])
491
+
492
+ def test_from_records_empty2(self):
493
+ # GH#42456
494
+ dtype = [("prop", int)]
495
+ shape = (0, len(dtype))
496
+ arr = np.empty(shape, dtype=dtype)
497
+
498
+ result = DataFrame.from_records(arr)
499
+ expected = DataFrame({"prop": np.array([], dtype=int)})
500
+ tm.assert_frame_equal(result, expected)
501
+
502
+ alt = DataFrame(arr)
503
+ tm.assert_frame_equal(alt, expected)
py311/lib/python3.11/site-packages/pandas/tests/frame/methods/test_add_prefix_suffix.py ADDED
@@ -0,0 +1,49 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import pytest
2
+
3
+ from pandas import Index
4
+ import pandas._testing as tm
5
+
6
+
7
+ def test_add_prefix_suffix(float_frame):
8
+ with_prefix = float_frame.add_prefix("foo#")
9
+ expected = Index([f"foo#{c}" for c in float_frame.columns])
10
+ tm.assert_index_equal(with_prefix.columns, expected)
11
+
12
+ with_suffix = float_frame.add_suffix("#foo")
13
+ expected = Index([f"{c}#foo" for c in float_frame.columns])
14
+ tm.assert_index_equal(with_suffix.columns, expected)
15
+
16
+ with_pct_prefix = float_frame.add_prefix("%")
17
+ expected = Index([f"%{c}" for c in float_frame.columns])
18
+ tm.assert_index_equal(with_pct_prefix.columns, expected)
19
+
20
+ with_pct_suffix = float_frame.add_suffix("%")
21
+ expected = Index([f"{c}%" for c in float_frame.columns])
22
+ tm.assert_index_equal(with_pct_suffix.columns, expected)
23
+
24
+
25
+ def test_add_prefix_suffix_axis(float_frame):
26
+ # GH 47819
27
+ with_prefix = float_frame.add_prefix("foo#", axis=0)
28
+ expected = Index([f"foo#{c}" for c in float_frame.index])
29
+ tm.assert_index_equal(with_prefix.index, expected)
30
+
31
+ with_prefix = float_frame.add_prefix("foo#", axis=1)
32
+ expected = Index([f"foo#{c}" for c in float_frame.columns])
33
+ tm.assert_index_equal(with_prefix.columns, expected)
34
+
35
+ with_pct_suffix = float_frame.add_suffix("#foo", axis=0)
36
+ expected = Index([f"{c}#foo" for c in float_frame.index])
37
+ tm.assert_index_equal(with_pct_suffix.index, expected)
38
+
39
+ with_pct_suffix = float_frame.add_suffix("#foo", axis=1)
40
+ expected = Index([f"{c}#foo" for c in float_frame.columns])
41
+ tm.assert_index_equal(with_pct_suffix.columns, expected)
42
+
43
+
44
+ def test_add_prefix_suffix_invalid_axis(float_frame):
45
+ with pytest.raises(ValueError, match="No axis named 2 for object type DataFrame"):
46
+ float_frame.add_prefix("foo#", axis=2)
47
+
48
+ with pytest.raises(ValueError, match="No axis named 2 for object type DataFrame"):
49
+ float_frame.add_suffix("foo#", axis=2)
py311/lib/python3.11/site-packages/pandas/tests/frame/methods/test_align.py ADDED
@@ -0,0 +1,484 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from datetime import timezone
2
+
3
+ import numpy as np
4
+ import pytest
5
+
6
+ import pandas as pd
7
+ from pandas import (
8
+ DataFrame,
9
+ Index,
10
+ Series,
11
+ date_range,
12
+ )
13
+ import pandas._testing as tm
14
+
15
+
16
+ class TestDataFrameAlign:
17
+ def test_align_asfreq_method_raises(self):
18
+ df = DataFrame({"A": [1, np.nan, 2]})
19
+ msg = "Invalid fill method"
20
+ msg2 = "The 'method', 'limit', and 'fill_axis' keywords"
21
+ with pytest.raises(ValueError, match=msg):
22
+ with tm.assert_produces_warning(FutureWarning, match=msg2):
23
+ df.align(df.iloc[::-1], method="asfreq")
24
+
25
+ def test_frame_align_aware(self):
26
+ idx1 = date_range("2001", periods=5, freq="h", tz="US/Eastern")
27
+ idx2 = date_range("2001", periods=5, freq="2h", tz="US/Eastern")
28
+ df1 = DataFrame(np.random.default_rng(2).standard_normal((len(idx1), 3)), idx1)
29
+ df2 = DataFrame(np.random.default_rng(2).standard_normal((len(idx2), 3)), idx2)
30
+ new1, new2 = df1.align(df2)
31
+ assert df1.index.tz == new1.index.tz
32
+ assert df2.index.tz == new2.index.tz
33
+
34
+ # different timezones convert to UTC
35
+
36
+ # frame with frame
37
+ df1_central = df1.tz_convert("US/Central")
38
+ new1, new2 = df1.align(df1_central)
39
+ assert new1.index.tz is timezone.utc
40
+ assert new2.index.tz is timezone.utc
41
+
42
+ # frame with Series
43
+ new1, new2 = df1.align(df1_central[0], axis=0)
44
+ assert new1.index.tz is timezone.utc
45
+ assert new2.index.tz is timezone.utc
46
+
47
+ df1[0].align(df1_central, axis=0)
48
+ assert new1.index.tz is timezone.utc
49
+ assert new2.index.tz is timezone.utc
50
+
51
+ def test_align_float(self, float_frame, using_copy_on_write):
52
+ af, bf = float_frame.align(float_frame)
53
+ assert af._mgr is not float_frame._mgr
54
+
55
+ af, bf = float_frame.align(float_frame, copy=False)
56
+ if not using_copy_on_write:
57
+ assert af._mgr is float_frame._mgr
58
+ else:
59
+ assert af._mgr is not float_frame._mgr
60
+
61
+ # axis = 0
62
+ other = float_frame.iloc[:-5, :3]
63
+ af, bf = float_frame.align(other, axis=0, fill_value=-1)
64
+
65
+ tm.assert_index_equal(bf.columns, other.columns)
66
+
67
+ # test fill value
68
+ join_idx = float_frame.index.join(other.index)
69
+ diff_a = float_frame.index.difference(join_idx)
70
+ diff_a_vals = af.reindex(diff_a).values
71
+ assert (diff_a_vals == -1).all()
72
+
73
+ af, bf = float_frame.align(other, join="right", axis=0)
74
+ tm.assert_index_equal(bf.columns, other.columns)
75
+ tm.assert_index_equal(bf.index, other.index)
76
+ tm.assert_index_equal(af.index, other.index)
77
+
78
+ # axis = 1
79
+ other = float_frame.iloc[:-5, :3].copy()
80
+ af, bf = float_frame.align(other, axis=1)
81
+ tm.assert_index_equal(bf.columns, float_frame.columns)
82
+ tm.assert_index_equal(bf.index, other.index)
83
+
84
+ # test fill value
85
+ join_idx = float_frame.index.join(other.index)
86
+ diff_a = float_frame.index.difference(join_idx)
87
+ diff_a_vals = af.reindex(diff_a).values
88
+
89
+ assert (diff_a_vals == -1).all()
90
+
91
+ af, bf = float_frame.align(other, join="inner", axis=1)
92
+ tm.assert_index_equal(bf.columns, other.columns)
93
+
94
+ msg = (
95
+ "The 'method', 'limit', and 'fill_axis' keywords in DataFrame.align "
96
+ "are deprecated"
97
+ )
98
+ with tm.assert_produces_warning(FutureWarning, match=msg):
99
+ af, bf = float_frame.align(other, join="inner", axis=1, method="pad")
100
+ tm.assert_index_equal(bf.columns, other.columns)
101
+
102
+ msg = (
103
+ "The 'method', 'limit', and 'fill_axis' keywords in DataFrame.align "
104
+ "are deprecated"
105
+ )
106
+ with tm.assert_produces_warning(FutureWarning, match=msg):
107
+ af, bf = float_frame.align(
108
+ other.iloc[:, 0], join="inner", axis=1, method=None, fill_value=None
109
+ )
110
+ tm.assert_index_equal(bf.index, Index([]).astype(bf.index.dtype))
111
+
112
+ msg = (
113
+ "The 'method', 'limit', and 'fill_axis' keywords in DataFrame.align "
114
+ "are deprecated"
115
+ )
116
+ with tm.assert_produces_warning(FutureWarning, match=msg):
117
+ af, bf = float_frame.align(
118
+ other.iloc[:, 0], join="inner", axis=1, method=None, fill_value=0
119
+ )
120
+ tm.assert_index_equal(bf.index, Index([]).astype(bf.index.dtype))
121
+
122
+ # Try to align DataFrame to Series along bad axis
123
+ msg = "No axis named 2 for object type DataFrame"
124
+ with pytest.raises(ValueError, match=msg):
125
+ float_frame.align(af.iloc[0, :3], join="inner", axis=2)
126
+
127
+ def test_align_frame_with_series(self, float_frame):
128
+ # align dataframe to series with broadcast or not
129
+ idx = float_frame.index
130
+ s = Series(range(len(idx)), index=idx)
131
+
132
+ left, right = float_frame.align(s, axis=0)
133
+ tm.assert_index_equal(left.index, float_frame.index)
134
+ tm.assert_index_equal(right.index, float_frame.index)
135
+ assert isinstance(right, Series)
136
+
137
+ msg = "The 'broadcast_axis' keyword in DataFrame.align is deprecated"
138
+ with tm.assert_produces_warning(FutureWarning, match=msg):
139
+ left, right = float_frame.align(s, broadcast_axis=1)
140
+ tm.assert_index_equal(left.index, float_frame.index)
141
+ expected = {c: s for c in float_frame.columns}
142
+ expected = DataFrame(
143
+ expected, index=float_frame.index, columns=float_frame.columns
144
+ )
145
+ tm.assert_frame_equal(right, expected)
146
+
147
+ def test_align_series_condition(self):
148
+ # see gh-9558
149
+ df = DataFrame({"a": [1, 2, 3], "b": [4, 5, 6]})
150
+ result = df[df["a"] == 2]
151
+ expected = DataFrame([[2, 5]], index=[1], columns=["a", "b"])
152
+ tm.assert_frame_equal(result, expected)
153
+
154
+ result = df.where(df["a"] == 2, 0)
155
+ expected = DataFrame({"a": [0, 2, 0], "b": [0, 5, 0]})
156
+ tm.assert_frame_equal(result, expected)
157
+
158
+ def test_align_int(self, int_frame):
159
+ # test other non-float types
160
+ other = DataFrame(index=range(5), columns=["A", "B", "C"])
161
+
162
+ msg = (
163
+ "The 'method', 'limit', and 'fill_axis' keywords in DataFrame.align "
164
+ "are deprecated"
165
+ )
166
+ with tm.assert_produces_warning(FutureWarning, match=msg):
167
+ af, bf = int_frame.align(other, join="inner", axis=1, method="pad")
168
+ tm.assert_index_equal(bf.columns, other.columns)
169
+
170
+ def test_align_mixed_type(self, float_string_frame):
171
+ msg = (
172
+ "The 'method', 'limit', and 'fill_axis' keywords in DataFrame.align "
173
+ "are deprecated"
174
+ )
175
+ with tm.assert_produces_warning(FutureWarning, match=msg):
176
+ af, bf = float_string_frame.align(
177
+ float_string_frame, join="inner", axis=1, method="pad"
178
+ )
179
+ tm.assert_index_equal(bf.columns, float_string_frame.columns)
180
+
181
+ def test_align_mixed_float(self, mixed_float_frame):
182
+ # mixed floats/ints
183
+ other = DataFrame(index=range(5), columns=["A", "B", "C"])
184
+
185
+ msg = (
186
+ "The 'method', 'limit', and 'fill_axis' keywords in DataFrame.align "
187
+ "are deprecated"
188
+ )
189
+ with tm.assert_produces_warning(FutureWarning, match=msg):
190
+ af, bf = mixed_float_frame.align(
191
+ other.iloc[:, 0], join="inner", axis=1, method=None, fill_value=0
192
+ )
193
+ tm.assert_index_equal(bf.index, Index([]))
194
+
195
+ def test_align_mixed_int(self, mixed_int_frame):
196
+ other = DataFrame(index=range(5), columns=["A", "B", "C"])
197
+
198
+ msg = (
199
+ "The 'method', 'limit', and 'fill_axis' keywords in DataFrame.align "
200
+ "are deprecated"
201
+ )
202
+ with tm.assert_produces_warning(FutureWarning, match=msg):
203
+ af, bf = mixed_int_frame.align(
204
+ other.iloc[:, 0], join="inner", axis=1, method=None, fill_value=0
205
+ )
206
+ tm.assert_index_equal(bf.index, Index([]))
207
+
208
+ @pytest.mark.parametrize(
209
+ "l_ordered,r_ordered,expected",
210
+ [
211
+ [True, True, pd.CategoricalIndex],
212
+ [True, False, Index],
213
+ [False, True, Index],
214
+ [False, False, pd.CategoricalIndex],
215
+ ],
216
+ )
217
+ def test_align_categorical(self, l_ordered, r_ordered, expected):
218
+ # GH-28397
219
+ df_1 = DataFrame(
220
+ {
221
+ "A": np.arange(6, dtype="int64"),
222
+ "B": Series(list("aabbca")).astype(
223
+ pd.CategoricalDtype(list("cab"), ordered=l_ordered)
224
+ ),
225
+ }
226
+ ).set_index("B")
227
+ df_2 = DataFrame(
228
+ {
229
+ "A": np.arange(5, dtype="int64"),
230
+ "B": Series(list("babca")).astype(
231
+ pd.CategoricalDtype(list("cab"), ordered=r_ordered)
232
+ ),
233
+ }
234
+ ).set_index("B")
235
+
236
+ aligned_1, aligned_2 = df_1.align(df_2)
237
+ assert isinstance(aligned_1.index, expected)
238
+ assert isinstance(aligned_2.index, expected)
239
+ tm.assert_index_equal(aligned_1.index, aligned_2.index)
240
+
241
+ def test_align_multiindex(self):
242
+ # GH#10665
243
+ # same test cases as test_align_multiindex in test_series.py
244
+
245
+ midx = pd.MultiIndex.from_product(
246
+ [range(2), range(3), range(2)], names=("a", "b", "c")
247
+ )
248
+ idx = Index(range(2), name="b")
249
+ df1 = DataFrame(np.arange(12, dtype="int64"), index=midx)
250
+ df2 = DataFrame(np.arange(2, dtype="int64"), index=idx)
251
+
252
+ # these must be the same results (but flipped)
253
+ res1l, res1r = df1.align(df2, join="left")
254
+ res2l, res2r = df2.align(df1, join="right")
255
+
256
+ expl = df1
257
+ tm.assert_frame_equal(expl, res1l)
258
+ tm.assert_frame_equal(expl, res2r)
259
+ expr = DataFrame([0, 0, 1, 1, np.nan, np.nan] * 2, index=midx)
260
+ tm.assert_frame_equal(expr, res1r)
261
+ tm.assert_frame_equal(expr, res2l)
262
+
263
+ res1l, res1r = df1.align(df2, join="right")
264
+ res2l, res2r = df2.align(df1, join="left")
265
+
266
+ exp_idx = pd.MultiIndex.from_product(
267
+ [range(2), range(2), range(2)], names=("a", "b", "c")
268
+ )
269
+ expl = DataFrame([0, 1, 2, 3, 6, 7, 8, 9], index=exp_idx)
270
+ tm.assert_frame_equal(expl, res1l)
271
+ tm.assert_frame_equal(expl, res2r)
272
+ expr = DataFrame([0, 0, 1, 1] * 2, index=exp_idx)
273
+ tm.assert_frame_equal(expr, res1r)
274
+ tm.assert_frame_equal(expr, res2l)
275
+
276
+ def test_align_series_combinations(self):
277
+ df = DataFrame({"a": [1, 3, 5], "b": [1, 3, 5]}, index=list("ACE"))
278
+ s = Series([1, 2, 4], index=list("ABD"), name="x")
279
+
280
+ # frame + series
281
+ res1, res2 = df.align(s, axis=0)
282
+ exp1 = DataFrame(
283
+ {"a": [1, np.nan, 3, np.nan, 5], "b": [1, np.nan, 3, np.nan, 5]},
284
+ index=list("ABCDE"),
285
+ )
286
+ exp2 = Series([1, 2, np.nan, 4, np.nan], index=list("ABCDE"), name="x")
287
+
288
+ tm.assert_frame_equal(res1, exp1)
289
+ tm.assert_series_equal(res2, exp2)
290
+
291
+ # series + frame
292
+ res1, res2 = s.align(df)
293
+ tm.assert_series_equal(res1, exp2)
294
+ tm.assert_frame_equal(res2, exp1)
295
+
296
+ def test_multiindex_align_to_series_with_common_index_level(self):
297
+ # GH-46001
298
+ foo_index = Index([1, 2, 3], name="foo")
299
+ bar_index = Index([1, 2], name="bar")
300
+
301
+ series = Series([1, 2], index=bar_index, name="foo_series")
302
+ df = DataFrame(
303
+ {"col": np.arange(6)},
304
+ index=pd.MultiIndex.from_product([foo_index, bar_index]),
305
+ )
306
+
307
+ expected_r = Series([1, 2] * 3, index=df.index, name="foo_series")
308
+ result_l, result_r = df.align(series, axis=0)
309
+
310
+ tm.assert_frame_equal(result_l, df)
311
+ tm.assert_series_equal(result_r, expected_r)
312
+
313
+ def test_multiindex_align_to_series_with_common_index_level_missing_in_left(self):
314
+ # GH-46001
315
+ foo_index = Index([1, 2, 3], name="foo")
316
+ bar_index = Index([1, 2], name="bar")
317
+
318
+ series = Series(
319
+ [1, 2, 3, 4], index=Index([1, 2, 3, 4], name="bar"), name="foo_series"
320
+ )
321
+ df = DataFrame(
322
+ {"col": np.arange(6)},
323
+ index=pd.MultiIndex.from_product([foo_index, bar_index]),
324
+ )
325
+
326
+ expected_r = Series([1, 2] * 3, index=df.index, name="foo_series")
327
+ result_l, result_r = df.align(series, axis=0)
328
+
329
+ tm.assert_frame_equal(result_l, df)
330
+ tm.assert_series_equal(result_r, expected_r)
331
+
332
+ def test_multiindex_align_to_series_with_common_index_level_missing_in_right(self):
333
+ # GH-46001
334
+ foo_index = Index([1, 2, 3], name="foo")
335
+ bar_index = Index([1, 2, 3, 4], name="bar")
336
+
337
+ series = Series([1, 2], index=Index([1, 2], name="bar"), name="foo_series")
338
+ df = DataFrame(
339
+ {"col": np.arange(12)},
340
+ index=pd.MultiIndex.from_product([foo_index, bar_index]),
341
+ )
342
+
343
+ expected_r = Series(
344
+ [1, 2, np.nan, np.nan] * 3, index=df.index, name="foo_series"
345
+ )
346
+ result_l, result_r = df.align(series, axis=0)
347
+
348
+ tm.assert_frame_equal(result_l, df)
349
+ tm.assert_series_equal(result_r, expected_r)
350
+
351
+ def test_multiindex_align_to_series_with_common_index_level_missing_in_both(self):
352
+ # GH-46001
353
+ foo_index = Index([1, 2, 3], name="foo")
354
+ bar_index = Index([1, 3, 4], name="bar")
355
+
356
+ series = Series(
357
+ [1, 2, 3], index=Index([1, 2, 4], name="bar"), name="foo_series"
358
+ )
359
+ df = DataFrame(
360
+ {"col": np.arange(9)},
361
+ index=pd.MultiIndex.from_product([foo_index, bar_index]),
362
+ )
363
+
364
+ expected_r = Series([1, np.nan, 3] * 3, index=df.index, name="foo_series")
365
+ result_l, result_r = df.align(series, axis=0)
366
+
367
+ tm.assert_frame_equal(result_l, df)
368
+ tm.assert_series_equal(result_r, expected_r)
369
+
370
+ def test_multiindex_align_to_series_with_common_index_level_non_unique_cols(self):
371
+ # GH-46001
372
+ foo_index = Index([1, 2, 3], name="foo")
373
+ bar_index = Index([1, 2], name="bar")
374
+
375
+ series = Series([1, 2], index=bar_index, name="foo_series")
376
+ df = DataFrame(
377
+ np.arange(18).reshape(6, 3),
378
+ index=pd.MultiIndex.from_product([foo_index, bar_index]),
379
+ )
380
+ df.columns = ["cfoo", "cbar", "cfoo"]
381
+
382
+ expected = Series([1, 2] * 3, index=df.index, name="foo_series")
383
+ result_left, result_right = df.align(series, axis=0)
384
+
385
+ tm.assert_series_equal(result_right, expected)
386
+ tm.assert_index_equal(result_left.columns, df.columns)
387
+
388
+ def test_missing_axis_specification_exception(self):
389
+ df = DataFrame(np.arange(50).reshape((10, 5)))
390
+ series = Series(np.arange(5))
391
+
392
+ with pytest.raises(ValueError, match=r"axis=0 or 1"):
393
+ df.align(series)
394
+
395
+ @pytest.mark.parametrize("method", ["pad", "bfill"])
396
+ @pytest.mark.parametrize("axis", [0, 1, None])
397
+ @pytest.mark.parametrize("fill_axis", [0, 1])
398
+ @pytest.mark.parametrize("how", ["inner", "outer", "left", "right"])
399
+ @pytest.mark.parametrize(
400
+ "left_slice",
401
+ [
402
+ [slice(4), slice(10)],
403
+ [slice(0), slice(0)],
404
+ ],
405
+ )
406
+ @pytest.mark.parametrize(
407
+ "right_slice",
408
+ [
409
+ [slice(2, None), slice(6, None)],
410
+ [slice(0), slice(0)],
411
+ ],
412
+ )
413
+ @pytest.mark.parametrize("limit", [1, None])
414
+ def test_align_fill_method(
415
+ self, how, method, axis, fill_axis, float_frame, left_slice, right_slice, limit
416
+ ):
417
+ frame = float_frame
418
+ left = frame.iloc[left_slice[0], left_slice[1]]
419
+ right = frame.iloc[right_slice[0], right_slice[1]]
420
+
421
+ msg = (
422
+ "The 'method', 'limit', and 'fill_axis' keywords in DataFrame.align "
423
+ "are deprecated"
424
+ )
425
+
426
+ with tm.assert_produces_warning(FutureWarning, match=msg):
427
+ aa, ab = left.align(
428
+ right,
429
+ axis=axis,
430
+ join=how,
431
+ method=method,
432
+ limit=limit,
433
+ fill_axis=fill_axis,
434
+ )
435
+
436
+ join_index, join_columns = None, None
437
+
438
+ ea, eb = left, right
439
+ if axis is None or axis == 0:
440
+ join_index = left.index.join(right.index, how=how)
441
+ ea = ea.reindex(index=join_index)
442
+ eb = eb.reindex(index=join_index)
443
+
444
+ if axis is None or axis == 1:
445
+ join_columns = left.columns.join(right.columns, how=how)
446
+ ea = ea.reindex(columns=join_columns)
447
+ eb = eb.reindex(columns=join_columns)
448
+
449
+ msg = "DataFrame.fillna with 'method' is deprecated"
450
+ with tm.assert_produces_warning(FutureWarning, match=msg):
451
+ ea = ea.fillna(axis=fill_axis, method=method, limit=limit)
452
+ eb = eb.fillna(axis=fill_axis, method=method, limit=limit)
453
+
454
+ tm.assert_frame_equal(aa, ea)
455
+ tm.assert_frame_equal(ab, eb)
456
+
457
+ def test_align_series_check_copy(self):
458
+ # GH#
459
+ df = DataFrame({0: [1, 2]})
460
+ ser = Series([1], name=0)
461
+ expected = ser.copy()
462
+ result, other = df.align(ser, axis=1)
463
+ ser.iloc[0] = 100
464
+ tm.assert_series_equal(other, expected)
465
+
466
+ def test_align_identical_different_object(self):
467
+ # GH#51032
468
+ df = DataFrame({"a": [1, 2]})
469
+ ser = Series([3, 4])
470
+ result, result2 = df.align(ser, axis=0)
471
+ tm.assert_frame_equal(result, df)
472
+ tm.assert_series_equal(result2, ser)
473
+ assert df is not result
474
+ assert ser is not result2
475
+
476
+ def test_align_identical_different_object_columns(self):
477
+ # GH#51032
478
+ df = DataFrame({"a": [1, 2]})
479
+ ser = Series([1], index=["a"])
480
+ result, result2 = df.align(ser, axis=1)
481
+ tm.assert_frame_equal(result, df)
482
+ tm.assert_series_equal(result2, ser)
483
+ assert df is not result
484
+ assert ser is not result2
py311/lib/python3.11/site-packages/pandas/tests/frame/methods/test_at_time.py ADDED
@@ -0,0 +1,132 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from datetime import time
2
+
3
+ import numpy as np
4
+ import pytest
5
+ import pytz
6
+
7
+ from pandas._libs.tslibs import timezones
8
+
9
+ from pandas import (
10
+ DataFrame,
11
+ date_range,
12
+ )
13
+ import pandas._testing as tm
14
+
15
+
16
+ class TestAtTime:
17
+ @pytest.mark.parametrize("tzstr", ["US/Eastern", "dateutil/US/Eastern"])
18
+ def test_localized_at_time(self, tzstr, frame_or_series):
19
+ tz = timezones.maybe_get_tz(tzstr)
20
+
21
+ rng = date_range("4/16/2012", "5/1/2012", freq="h")
22
+ ts = frame_or_series(
23
+ np.random.default_rng(2).standard_normal(len(rng)), index=rng
24
+ )
25
+
26
+ ts_local = ts.tz_localize(tzstr)
27
+
28
+ result = ts_local.at_time(time(10, 0))
29
+ expected = ts.at_time(time(10, 0)).tz_localize(tzstr)
30
+ tm.assert_equal(result, expected)
31
+ assert timezones.tz_compare(result.index.tz, tz)
32
+
33
+ def test_at_time(self, frame_or_series):
34
+ rng = date_range("1/1/2000", "1/5/2000", freq="5min")
35
+ ts = DataFrame(
36
+ np.random.default_rng(2).standard_normal((len(rng), 2)), index=rng
37
+ )
38
+ ts = tm.get_obj(ts, frame_or_series)
39
+ rs = ts.at_time(rng[1])
40
+ assert (rs.index.hour == rng[1].hour).all()
41
+ assert (rs.index.minute == rng[1].minute).all()
42
+ assert (rs.index.second == rng[1].second).all()
43
+
44
+ result = ts.at_time("9:30")
45
+ expected = ts.at_time(time(9, 30))
46
+ tm.assert_equal(result, expected)
47
+
48
+ def test_at_time_midnight(self, frame_or_series):
49
+ # midnight, everything
50
+ rng = date_range("1/1/2000", "1/31/2000")
51
+ ts = DataFrame(
52
+ np.random.default_rng(2).standard_normal((len(rng), 3)), index=rng
53
+ )
54
+ ts = tm.get_obj(ts, frame_or_series)
55
+
56
+ result = ts.at_time(time(0, 0))
57
+ tm.assert_equal(result, ts)
58
+
59
+ def test_at_time_nonexistent(self, frame_or_series):
60
+ # time doesn't exist
61
+ rng = date_range("1/1/2012", freq="23Min", periods=384)
62
+ ts = DataFrame(np.random.default_rng(2).standard_normal(len(rng)), rng)
63
+ ts = tm.get_obj(ts, frame_or_series)
64
+ rs = ts.at_time("16:00")
65
+ assert len(rs) == 0
66
+
67
+ @pytest.mark.parametrize(
68
+ "hour", ["1:00", "1:00AM", time(1), time(1, tzinfo=pytz.UTC)]
69
+ )
70
+ def test_at_time_errors(self, hour):
71
+ # GH#24043
72
+ dti = date_range("2018", periods=3, freq="h")
73
+ df = DataFrame(list(range(len(dti))), index=dti)
74
+ if getattr(hour, "tzinfo", None) is None:
75
+ result = df.at_time(hour)
76
+ expected = df.iloc[1:2]
77
+ tm.assert_frame_equal(result, expected)
78
+ else:
79
+ with pytest.raises(ValueError, match="Index must be timezone"):
80
+ df.at_time(hour)
81
+
82
+ def test_at_time_tz(self):
83
+ # GH#24043
84
+ dti = date_range("2018", periods=3, freq="h", tz="US/Pacific")
85
+ df = DataFrame(list(range(len(dti))), index=dti)
86
+ result = df.at_time(time(4, tzinfo=pytz.timezone("US/Eastern")))
87
+ expected = df.iloc[1:2]
88
+ tm.assert_frame_equal(result, expected)
89
+
90
+ def test_at_time_raises(self, frame_or_series):
91
+ # GH#20725
92
+ obj = DataFrame([[1, 2, 3], [4, 5, 6]])
93
+ obj = tm.get_obj(obj, frame_or_series)
94
+ msg = "Index must be DatetimeIndex"
95
+ with pytest.raises(TypeError, match=msg): # index is not a DatetimeIndex
96
+ obj.at_time("00:00")
97
+
98
+ @pytest.mark.parametrize("axis", ["index", "columns", 0, 1])
99
+ def test_at_time_axis(self, axis):
100
+ # issue 8839
101
+ rng = date_range("1/1/2000", "1/5/2000", freq="5min")
102
+ ts = DataFrame(np.random.default_rng(2).standard_normal((len(rng), len(rng))))
103
+ ts.index, ts.columns = rng, rng
104
+
105
+ indices = rng[(rng.hour == 9) & (rng.minute == 30) & (rng.second == 0)]
106
+
107
+ if axis in ["index", 0]:
108
+ expected = ts.loc[indices, :]
109
+ elif axis in ["columns", 1]:
110
+ expected = ts.loc[:, indices]
111
+
112
+ result = ts.at_time("9:30", axis=axis)
113
+
114
+ # Without clearing freq, result has freq 1440T and expected 5T
115
+ result.index = result.index._with_freq(None)
116
+ expected.index = expected.index._with_freq(None)
117
+ tm.assert_frame_equal(result, expected)
118
+
119
+ def test_at_time_datetimeindex(self):
120
+ index = date_range("2012-01-01", "2012-01-05", freq="30min")
121
+ df = DataFrame(
122
+ np.random.default_rng(2).standard_normal((len(index), 5)), index=index
123
+ )
124
+ akey = time(12, 0, 0)
125
+ ainds = [24, 72, 120, 168]
126
+
127
+ result = df.at_time(akey)
128
+ expected = df.loc[akey]
129
+ expected2 = df.iloc[ainds]
130
+ tm.assert_frame_equal(result, expected)
131
+ tm.assert_frame_equal(result, expected2)
132
+ assert len(result) == 4
py311/lib/python3.11/site-packages/pandas/tests/frame/methods/test_between_time.py ADDED
@@ -0,0 +1,227 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from datetime import (
2
+ datetime,
3
+ time,
4
+ )
5
+
6
+ import numpy as np
7
+ import pytest
8
+
9
+ from pandas._libs.tslibs import timezones
10
+ import pandas.util._test_decorators as td
11
+
12
+ from pandas import (
13
+ DataFrame,
14
+ Series,
15
+ date_range,
16
+ )
17
+ import pandas._testing as tm
18
+
19
+
20
+ class TestBetweenTime:
21
+ @td.skip_if_not_us_locale
22
+ def test_between_time_formats(self, frame_or_series):
23
+ # GH#11818
24
+ rng = date_range("1/1/2000", "1/5/2000", freq="5min")
25
+ ts = DataFrame(
26
+ np.random.default_rng(2).standard_normal((len(rng), 2)), index=rng
27
+ )
28
+ ts = tm.get_obj(ts, frame_or_series)
29
+
30
+ strings = [
31
+ ("2:00", "2:30"),
32
+ ("0200", "0230"),
33
+ ("2:00am", "2:30am"),
34
+ ("0200am", "0230am"),
35
+ ("2:00:00", "2:30:00"),
36
+ ("020000", "023000"),
37
+ ("2:00:00am", "2:30:00am"),
38
+ ("020000am", "023000am"),
39
+ ]
40
+ expected_length = 28
41
+
42
+ for time_string in strings:
43
+ assert len(ts.between_time(*time_string)) == expected_length
44
+
45
+ @pytest.mark.parametrize("tzstr", ["US/Eastern", "dateutil/US/Eastern"])
46
+ def test_localized_between_time(self, tzstr, frame_or_series):
47
+ tz = timezones.maybe_get_tz(tzstr)
48
+
49
+ rng = date_range("4/16/2012", "5/1/2012", freq="h")
50
+ ts = Series(np.random.default_rng(2).standard_normal(len(rng)), index=rng)
51
+ if frame_or_series is DataFrame:
52
+ ts = ts.to_frame()
53
+
54
+ ts_local = ts.tz_localize(tzstr)
55
+
56
+ t1, t2 = time(10, 0), time(11, 0)
57
+ result = ts_local.between_time(t1, t2)
58
+ expected = ts.between_time(t1, t2).tz_localize(tzstr)
59
+ tm.assert_equal(result, expected)
60
+ assert timezones.tz_compare(result.index.tz, tz)
61
+
62
+ def test_between_time_types(self, frame_or_series):
63
+ # GH11818
64
+ rng = date_range("1/1/2000", "1/5/2000", freq="5min")
65
+ obj = DataFrame({"A": 0}, index=rng)
66
+ obj = tm.get_obj(obj, frame_or_series)
67
+
68
+ msg = r"Cannot convert arg \[datetime\.datetime\(2010, 1, 2, 1, 0\)\] to a time"
69
+ with pytest.raises(ValueError, match=msg):
70
+ obj.between_time(datetime(2010, 1, 2, 1), datetime(2010, 1, 2, 5))
71
+
72
+ def test_between_time(self, inclusive_endpoints_fixture, frame_or_series):
73
+ rng = date_range("1/1/2000", "1/5/2000", freq="5min")
74
+ ts = DataFrame(
75
+ np.random.default_rng(2).standard_normal((len(rng), 2)), index=rng
76
+ )
77
+ ts = tm.get_obj(ts, frame_or_series)
78
+
79
+ stime = time(0, 0)
80
+ etime = time(1, 0)
81
+ inclusive = inclusive_endpoints_fixture
82
+
83
+ filtered = ts.between_time(stime, etime, inclusive=inclusive)
84
+ exp_len = 13 * 4 + 1
85
+
86
+ if inclusive in ["right", "neither"]:
87
+ exp_len -= 5
88
+ if inclusive in ["left", "neither"]:
89
+ exp_len -= 4
90
+
91
+ assert len(filtered) == exp_len
92
+ for rs in filtered.index:
93
+ t = rs.time()
94
+ if inclusive in ["left", "both"]:
95
+ assert t >= stime
96
+ else:
97
+ assert t > stime
98
+
99
+ if inclusive in ["right", "both"]:
100
+ assert t <= etime
101
+ else:
102
+ assert t < etime
103
+
104
+ result = ts.between_time("00:00", "01:00")
105
+ expected = ts.between_time(stime, etime)
106
+ tm.assert_equal(result, expected)
107
+
108
+ # across midnight
109
+ rng = date_range("1/1/2000", "1/5/2000", freq="5min")
110
+ ts = DataFrame(
111
+ np.random.default_rng(2).standard_normal((len(rng), 2)), index=rng
112
+ )
113
+ ts = tm.get_obj(ts, frame_or_series)
114
+ stime = time(22, 0)
115
+ etime = time(9, 0)
116
+
117
+ filtered = ts.between_time(stime, etime, inclusive=inclusive)
118
+ exp_len = (12 * 11 + 1) * 4 + 1
119
+ if inclusive in ["right", "neither"]:
120
+ exp_len -= 4
121
+ if inclusive in ["left", "neither"]:
122
+ exp_len -= 4
123
+
124
+ assert len(filtered) == exp_len
125
+ for rs in filtered.index:
126
+ t = rs.time()
127
+ if inclusive in ["left", "both"]:
128
+ assert (t >= stime) or (t <= etime)
129
+ else:
130
+ assert (t > stime) or (t <= etime)
131
+
132
+ if inclusive in ["right", "both"]:
133
+ assert (t <= etime) or (t >= stime)
134
+ else:
135
+ assert (t < etime) or (t >= stime)
136
+
137
+ def test_between_time_raises(self, frame_or_series):
138
+ # GH#20725
139
+ obj = DataFrame([[1, 2, 3], [4, 5, 6]])
140
+ obj = tm.get_obj(obj, frame_or_series)
141
+
142
+ msg = "Index must be DatetimeIndex"
143
+ with pytest.raises(TypeError, match=msg): # index is not a DatetimeIndex
144
+ obj.between_time(start_time="00:00", end_time="12:00")
145
+
146
+ def test_between_time_axis(self, frame_or_series):
147
+ # GH#8839
148
+ rng = date_range("1/1/2000", periods=100, freq="10min")
149
+ ts = Series(np.random.default_rng(2).standard_normal(len(rng)), index=rng)
150
+ if frame_or_series is DataFrame:
151
+ ts = ts.to_frame()
152
+
153
+ stime, etime = ("08:00:00", "09:00:00")
154
+ expected_length = 7
155
+
156
+ assert len(ts.between_time(stime, etime)) == expected_length
157
+ assert len(ts.between_time(stime, etime, axis=0)) == expected_length
158
+ msg = f"No axis named {ts.ndim} for object type {type(ts).__name__}"
159
+ with pytest.raises(ValueError, match=msg):
160
+ ts.between_time(stime, etime, axis=ts.ndim)
161
+
162
+ def test_between_time_axis_aliases(self, axis):
163
+ # GH#8839
164
+ rng = date_range("1/1/2000", periods=100, freq="10min")
165
+ ts = DataFrame(np.random.default_rng(2).standard_normal((len(rng), len(rng))))
166
+ stime, etime = ("08:00:00", "09:00:00")
167
+ exp_len = 7
168
+
169
+ if axis in ["index", 0]:
170
+ ts.index = rng
171
+ assert len(ts.between_time(stime, etime)) == exp_len
172
+ assert len(ts.between_time(stime, etime, axis=0)) == exp_len
173
+
174
+ if axis in ["columns", 1]:
175
+ ts.columns = rng
176
+ selected = ts.between_time(stime, etime, axis=1).columns
177
+ assert len(selected) == exp_len
178
+
179
+ def test_between_time_axis_raises(self, axis):
180
+ # issue 8839
181
+ rng = date_range("1/1/2000", periods=100, freq="10min")
182
+ mask = np.arange(0, len(rng))
183
+ rand_data = np.random.default_rng(2).standard_normal((len(rng), len(rng)))
184
+ ts = DataFrame(rand_data, index=rng, columns=rng)
185
+ stime, etime = ("08:00:00", "09:00:00")
186
+
187
+ msg = "Index must be DatetimeIndex"
188
+ if axis in ["columns", 1]:
189
+ ts.index = mask
190
+ with pytest.raises(TypeError, match=msg):
191
+ ts.between_time(stime, etime)
192
+ with pytest.raises(TypeError, match=msg):
193
+ ts.between_time(stime, etime, axis=0)
194
+
195
+ if axis in ["index", 0]:
196
+ ts.columns = mask
197
+ with pytest.raises(TypeError, match=msg):
198
+ ts.between_time(stime, etime, axis=1)
199
+
200
+ def test_between_time_datetimeindex(self):
201
+ index = date_range("2012-01-01", "2012-01-05", freq="30min")
202
+ df = DataFrame(
203
+ np.random.default_rng(2).standard_normal((len(index), 5)), index=index
204
+ )
205
+ bkey = slice(time(13, 0, 0), time(14, 0, 0))
206
+ binds = [26, 27, 28, 74, 75, 76, 122, 123, 124, 170, 171, 172]
207
+
208
+ result = df.between_time(bkey.start, bkey.stop)
209
+ expected = df.loc[bkey]
210
+ expected2 = df.iloc[binds]
211
+ tm.assert_frame_equal(result, expected)
212
+ tm.assert_frame_equal(result, expected2)
213
+ assert len(result) == 12
214
+
215
+ def test_between_time_incorrect_arg_inclusive(self):
216
+ # GH40245
217
+ rng = date_range("1/1/2000", "1/5/2000", freq="5min")
218
+ ts = DataFrame(
219
+ np.random.default_rng(2).standard_normal((len(rng), 2)), index=rng
220
+ )
221
+
222
+ stime = time(0, 0)
223
+ etime = time(1, 0)
224
+ inclusive = "bad_string"
225
+ msg = "Inclusive has to be either 'both', 'neither', 'left' or 'right'"
226
+ with pytest.raises(ValueError, match=msg):
227
+ ts.between_time(stime, etime, inclusive=inclusive)
py311/lib/python3.11/site-packages/pandas/tests/frame/methods/test_combine.py ADDED
@@ -0,0 +1,47 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import numpy as np
2
+ import pytest
3
+
4
+ import pandas as pd
5
+ import pandas._testing as tm
6
+
7
+
8
+ class TestCombine:
9
+ @pytest.mark.parametrize(
10
+ "data",
11
+ [
12
+ pd.date_range("2000", periods=4),
13
+ pd.date_range("2000", periods=4, tz="US/Central"),
14
+ pd.period_range("2000", periods=4),
15
+ pd.timedelta_range(0, periods=4),
16
+ ],
17
+ )
18
+ def test_combine_datetlike_udf(self, data):
19
+ # GH#23079
20
+ df = pd.DataFrame({"A": data})
21
+ other = df.copy()
22
+ df.iloc[1, 0] = None
23
+
24
+ def combiner(a, b):
25
+ return b
26
+
27
+ result = df.combine(other, combiner)
28
+ tm.assert_frame_equal(result, other)
29
+
30
+ def test_combine_generic(self, float_frame):
31
+ df1 = float_frame
32
+ df2 = float_frame.loc[float_frame.index[:-5], ["A", "B", "C"]]
33
+
34
+ combined = df1.combine(df2, np.add)
35
+ combined2 = df2.combine(df1, np.add)
36
+ assert combined["D"].isna().all()
37
+ assert combined2["D"].isna().all()
38
+
39
+ chunk = combined.loc[combined.index[:-5], ["A", "B", "C"]]
40
+ chunk2 = combined2.loc[combined2.index[:-5], ["A", "B", "C"]]
41
+
42
+ exp = (
43
+ float_frame.loc[float_frame.index[:-5], ["A", "B", "C"]].reindex_like(chunk)
44
+ * 2
45
+ )
46
+ tm.assert_frame_equal(chunk, exp)
47
+ tm.assert_frame_equal(chunk2, exp)
py311/lib/python3.11/site-packages/pandas/tests/frame/methods/test_combine_first.py ADDED
@@ -0,0 +1,556 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from datetime import datetime
2
+
3
+ import numpy as np
4
+ import pytest
5
+
6
+ from pandas.core.dtypes.cast import find_common_type
7
+ from pandas.core.dtypes.common import is_dtype_equal
8
+
9
+ import pandas as pd
10
+ from pandas import (
11
+ DataFrame,
12
+ Index,
13
+ MultiIndex,
14
+ Series,
15
+ )
16
+ import pandas._testing as tm
17
+
18
+
19
+ class TestDataFrameCombineFirst:
20
+ def test_combine_first_mixed(self):
21
+ a = Series(["a", "b"], index=range(2))
22
+ b = Series(range(2), index=range(2))
23
+ f = DataFrame({"A": a, "B": b})
24
+
25
+ a = Series(["a", "b"], index=range(5, 7))
26
+ b = Series(range(2), index=range(5, 7))
27
+ g = DataFrame({"A": a, "B": b})
28
+
29
+ exp = DataFrame({"A": list("abab"), "B": [0, 1, 0, 1]}, index=[0, 1, 5, 6])
30
+ combined = f.combine_first(g)
31
+ tm.assert_frame_equal(combined, exp)
32
+
33
+ def test_combine_first(self, float_frame, using_infer_string):
34
+ # disjoint
35
+ head, tail = float_frame[:5], float_frame[5:]
36
+
37
+ combined = head.combine_first(tail)
38
+ reordered_frame = float_frame.reindex(combined.index)
39
+ tm.assert_frame_equal(combined, reordered_frame)
40
+ tm.assert_index_equal(combined.columns, float_frame.columns)
41
+ tm.assert_series_equal(combined["A"], reordered_frame["A"])
42
+
43
+ # same index
44
+ fcopy = float_frame.copy()
45
+ fcopy["A"] = 1
46
+ del fcopy["C"]
47
+
48
+ fcopy2 = float_frame.copy()
49
+ fcopy2["B"] = 0
50
+ del fcopy2["D"]
51
+
52
+ combined = fcopy.combine_first(fcopy2)
53
+
54
+ assert (combined["A"] == 1).all()
55
+ tm.assert_series_equal(combined["B"], fcopy["B"])
56
+ tm.assert_series_equal(combined["C"], fcopy2["C"])
57
+ tm.assert_series_equal(combined["D"], fcopy["D"])
58
+
59
+ # overlap
60
+ head, tail = reordered_frame[:10].copy(), reordered_frame
61
+ head["A"] = 1
62
+
63
+ combined = head.combine_first(tail)
64
+ assert (combined["A"][:10] == 1).all()
65
+
66
+ # reverse overlap
67
+ tail.iloc[:10, tail.columns.get_loc("A")] = 0
68
+ combined = tail.combine_first(head)
69
+ assert (combined["A"][:10] == 0).all()
70
+
71
+ # no overlap
72
+ f = float_frame[:10]
73
+ g = float_frame[10:]
74
+ combined = f.combine_first(g)
75
+ tm.assert_series_equal(combined["A"].reindex(f.index), f["A"])
76
+ tm.assert_series_equal(combined["A"].reindex(g.index), g["A"])
77
+
78
+ # corner cases
79
+ warning = FutureWarning if using_infer_string else None
80
+ with tm.assert_produces_warning(warning, match="empty entries"):
81
+ comb = float_frame.combine_first(DataFrame())
82
+ tm.assert_frame_equal(comb, float_frame)
83
+
84
+ comb = DataFrame().combine_first(float_frame)
85
+ tm.assert_frame_equal(comb, float_frame.sort_index())
86
+
87
+ comb = float_frame.combine_first(DataFrame(index=["faz", "boo"]))
88
+ assert "faz" in comb.index
89
+
90
+ # #2525
91
+ df = DataFrame({"a": [1]}, index=[datetime(2012, 1, 1)])
92
+ df2 = DataFrame(columns=["b"])
93
+ result = df.combine_first(df2)
94
+ assert "b" in result
95
+
96
+ def test_combine_first_mixed_bug(self):
97
+ idx = Index(["a", "b", "c", "e"])
98
+ ser1 = Series([5.0, -9.0, 4.0, 100.0], index=idx)
99
+ ser2 = Series(["a", "b", "c", "e"], index=idx)
100
+ ser3 = Series([12, 4, 5, 97], index=idx)
101
+
102
+ frame1 = DataFrame({"col0": ser1, "col2": ser2, "col3": ser3})
103
+
104
+ idx = Index(["a", "b", "c", "f"])
105
+ ser1 = Series([5.0, -9.0, 4.0, 100.0], index=idx)
106
+ ser2 = Series(["a", "b", "c", "f"], index=idx)
107
+ ser3 = Series([12, 4, 5, 97], index=idx)
108
+
109
+ frame2 = DataFrame({"col1": ser1, "col2": ser2, "col5": ser3})
110
+
111
+ combined = frame1.combine_first(frame2)
112
+ assert len(combined.columns) == 5
113
+
114
+ def test_combine_first_same_as_in_update(self):
115
+ # gh 3016 (same as in update)
116
+ df = DataFrame(
117
+ [[1.0, 2.0, False, True], [4.0, 5.0, True, False]],
118
+ columns=["A", "B", "bool1", "bool2"],
119
+ )
120
+
121
+ other = DataFrame([[45, 45]], index=[0], columns=["A", "B"])
122
+ result = df.combine_first(other)
123
+ tm.assert_frame_equal(result, df)
124
+
125
+ df.loc[0, "A"] = np.nan
126
+ result = df.combine_first(other)
127
+ df.loc[0, "A"] = 45
128
+ tm.assert_frame_equal(result, df)
129
+
130
+ def test_combine_first_doc_example(self):
131
+ # doc example
132
+ df1 = DataFrame(
133
+ {"A": [1.0, np.nan, 3.0, 5.0, np.nan], "B": [np.nan, 2.0, 3.0, np.nan, 6.0]}
134
+ )
135
+
136
+ df2 = DataFrame(
137
+ {
138
+ "A": [5.0, 2.0, 4.0, np.nan, 3.0, 7.0],
139
+ "B": [np.nan, np.nan, 3.0, 4.0, 6.0, 8.0],
140
+ }
141
+ )
142
+
143
+ result = df1.combine_first(df2)
144
+ expected = DataFrame({"A": [1, 2, 3, 5, 3, 7.0], "B": [np.nan, 2, 3, 4, 6, 8]})
145
+ tm.assert_frame_equal(result, expected)
146
+
147
+ def test_combine_first_return_obj_type_with_bools(self):
148
+ # GH3552
149
+
150
+ df1 = DataFrame(
151
+ [[np.nan, 3.0, True], [-4.6, np.nan, True], [np.nan, 7.0, False]]
152
+ )
153
+ df2 = DataFrame([[-42.6, np.nan, True], [-5.0, 1.6, False]], index=[1, 2])
154
+
155
+ expected = Series([True, True, False], name=2, dtype=bool)
156
+
157
+ result_12 = df1.combine_first(df2)[2]
158
+ tm.assert_series_equal(result_12, expected)
159
+
160
+ result_21 = df2.combine_first(df1)[2]
161
+ tm.assert_series_equal(result_21, expected)
162
+
163
+ @pytest.mark.parametrize(
164
+ "data1, data2, data_expected",
165
+ (
166
+ (
167
+ [datetime(2000, 1, 1), datetime(2000, 1, 2), datetime(2000, 1, 3)],
168
+ [pd.NaT, pd.NaT, pd.NaT],
169
+ [datetime(2000, 1, 1), datetime(2000, 1, 2), datetime(2000, 1, 3)],
170
+ ),
171
+ (
172
+ [pd.NaT, pd.NaT, pd.NaT],
173
+ [datetime(2000, 1, 1), datetime(2000, 1, 2), datetime(2000, 1, 3)],
174
+ [datetime(2000, 1, 1), datetime(2000, 1, 2), datetime(2000, 1, 3)],
175
+ ),
176
+ (
177
+ [datetime(2000, 1, 2), pd.NaT, pd.NaT],
178
+ [datetime(2000, 1, 1), datetime(2000, 1, 2), datetime(2000, 1, 3)],
179
+ [datetime(2000, 1, 2), datetime(2000, 1, 2), datetime(2000, 1, 3)],
180
+ ),
181
+ (
182
+ [datetime(2000, 1, 1), datetime(2000, 1, 2), datetime(2000, 1, 3)],
183
+ [datetime(2000, 1, 2), pd.NaT, pd.NaT],
184
+ [datetime(2000, 1, 1), datetime(2000, 1, 2), datetime(2000, 1, 3)],
185
+ ),
186
+ ),
187
+ )
188
+ def test_combine_first_convert_datatime_correctly(
189
+ self, data1, data2, data_expected
190
+ ):
191
+ # GH 3593
192
+
193
+ df1, df2 = DataFrame({"a": data1}), DataFrame({"a": data2})
194
+ result = df1.combine_first(df2)
195
+ expected = DataFrame({"a": data_expected})
196
+ tm.assert_frame_equal(result, expected)
197
+
198
+ def test_combine_first_align_nan(self):
199
+ # GH 7509 (not fixed)
200
+ dfa = DataFrame([[pd.Timestamp("2011-01-01"), 2]], columns=["a", "b"])
201
+ dfb = DataFrame([[4], [5]], columns=["b"])
202
+ assert dfa["a"].dtype == "datetime64[ns]"
203
+ assert dfa["b"].dtype == "int64"
204
+
205
+ res = dfa.combine_first(dfb)
206
+ exp = DataFrame(
207
+ {"a": [pd.Timestamp("2011-01-01"), pd.NaT], "b": [2, 5]},
208
+ columns=["a", "b"],
209
+ )
210
+ tm.assert_frame_equal(res, exp)
211
+ assert res["a"].dtype == "datetime64[ns]"
212
+ # TODO: this must be int64
213
+ assert res["b"].dtype == "int64"
214
+
215
+ res = dfa.iloc[:0].combine_first(dfb)
216
+ exp = DataFrame({"a": [np.nan, np.nan], "b": [4, 5]}, columns=["a", "b"])
217
+ tm.assert_frame_equal(res, exp)
218
+ # TODO: this must be datetime64
219
+ assert res["a"].dtype == "float64"
220
+ # TODO: this must be int64
221
+ assert res["b"].dtype == "int64"
222
+
223
+ def test_combine_first_timezone(self, unit):
224
+ # see gh-7630
225
+ data1 = pd.to_datetime("20100101 01:01").tz_localize("UTC").as_unit(unit)
226
+ df1 = DataFrame(
227
+ columns=["UTCdatetime", "abc"],
228
+ data=data1,
229
+ index=pd.date_range("20140627", periods=1),
230
+ )
231
+ data2 = pd.to_datetime("20121212 12:12").tz_localize("UTC").as_unit(unit)
232
+ df2 = DataFrame(
233
+ columns=["UTCdatetime", "xyz"],
234
+ data=data2,
235
+ index=pd.date_range("20140628", periods=1),
236
+ )
237
+ res = df2[["UTCdatetime"]].combine_first(df1)
238
+ exp = DataFrame(
239
+ {
240
+ "UTCdatetime": [
241
+ pd.Timestamp("2010-01-01 01:01", tz="UTC"),
242
+ pd.Timestamp("2012-12-12 12:12", tz="UTC"),
243
+ ],
244
+ "abc": [pd.Timestamp("2010-01-01 01:01:00", tz="UTC"), pd.NaT],
245
+ },
246
+ columns=["UTCdatetime", "abc"],
247
+ index=pd.date_range("20140627", periods=2, freq="D"),
248
+ dtype=f"datetime64[{unit}, UTC]",
249
+ )
250
+ assert res["UTCdatetime"].dtype == f"datetime64[{unit}, UTC]"
251
+ assert res["abc"].dtype == f"datetime64[{unit}, UTC]"
252
+
253
+ tm.assert_frame_equal(res, exp)
254
+
255
+ def test_combine_first_timezone2(self, unit):
256
+ # see gh-10567
257
+ dts1 = pd.date_range("2015-01-01", "2015-01-05", tz="UTC", unit=unit)
258
+ df1 = DataFrame({"DATE": dts1})
259
+ dts2 = pd.date_range("2015-01-03", "2015-01-05", tz="UTC", unit=unit)
260
+ df2 = DataFrame({"DATE": dts2})
261
+
262
+ res = df1.combine_first(df2)
263
+ tm.assert_frame_equal(res, df1)
264
+ assert res["DATE"].dtype == f"datetime64[{unit}, UTC]"
265
+
266
+ def test_combine_first_timezone3(self, unit):
267
+ dts1 = pd.DatetimeIndex(
268
+ ["2011-01-01", "NaT", "2011-01-03", "2011-01-04"], tz="US/Eastern"
269
+ ).as_unit(unit)
270
+ df1 = DataFrame({"DATE": dts1}, index=[1, 3, 5, 7])
271
+ dts2 = pd.DatetimeIndex(
272
+ ["2012-01-01", "2012-01-02", "2012-01-03"], tz="US/Eastern"
273
+ ).as_unit(unit)
274
+ df2 = DataFrame({"DATE": dts2}, index=[2, 4, 5])
275
+
276
+ res = df1.combine_first(df2)
277
+ exp_dts = pd.DatetimeIndex(
278
+ [
279
+ "2011-01-01",
280
+ "2012-01-01",
281
+ "NaT",
282
+ "2012-01-02",
283
+ "2011-01-03",
284
+ "2011-01-04",
285
+ ],
286
+ tz="US/Eastern",
287
+ ).as_unit(unit)
288
+ exp = DataFrame({"DATE": exp_dts}, index=[1, 2, 3, 4, 5, 7])
289
+ tm.assert_frame_equal(res, exp)
290
+
291
+ # FIXME: parametrizing over unit breaks on non-nano
292
+ def test_combine_first_timezone4(self):
293
+ # different tz
294
+ dts1 = pd.date_range("2015-01-01", "2015-01-05", tz="US/Eastern")
295
+ df1 = DataFrame({"DATE": dts1})
296
+ dts2 = pd.date_range("2015-01-03", "2015-01-05")
297
+ df2 = DataFrame({"DATE": dts2})
298
+
299
+ # if df1 doesn't have NaN, keep its dtype
300
+ res = df1.combine_first(df2)
301
+ tm.assert_frame_equal(res, df1)
302
+ assert res["DATE"].dtype == "datetime64[ns, US/Eastern]"
303
+
304
+ def test_combine_first_timezone5(self, unit):
305
+ dts1 = pd.date_range("2015-01-01", "2015-01-02", tz="US/Eastern", unit=unit)
306
+ df1 = DataFrame({"DATE": dts1})
307
+ dts2 = pd.date_range("2015-01-01", "2015-01-03", unit=unit)
308
+ df2 = DataFrame({"DATE": dts2})
309
+
310
+ res = df1.combine_first(df2)
311
+ exp_dts = [
312
+ pd.Timestamp("2015-01-01", tz="US/Eastern"),
313
+ pd.Timestamp("2015-01-02", tz="US/Eastern"),
314
+ pd.Timestamp("2015-01-03"),
315
+ ]
316
+ exp = DataFrame({"DATE": exp_dts})
317
+ tm.assert_frame_equal(res, exp)
318
+ assert res["DATE"].dtype == "object"
319
+
320
+ def test_combine_first_timedelta(self):
321
+ data1 = pd.TimedeltaIndex(["1 day", "NaT", "3 day", "4day"])
322
+ df1 = DataFrame({"TD": data1}, index=[1, 3, 5, 7])
323
+ data2 = pd.TimedeltaIndex(["10 day", "11 day", "12 day"])
324
+ df2 = DataFrame({"TD": data2}, index=[2, 4, 5])
325
+
326
+ res = df1.combine_first(df2)
327
+ exp_dts = pd.TimedeltaIndex(
328
+ ["1 day", "10 day", "NaT", "11 day", "3 day", "4 day"]
329
+ )
330
+ exp = DataFrame({"TD": exp_dts}, index=[1, 2, 3, 4, 5, 7])
331
+ tm.assert_frame_equal(res, exp)
332
+ assert res["TD"].dtype == "timedelta64[ns]"
333
+
334
+ def test_combine_first_period(self):
335
+ data1 = pd.PeriodIndex(["2011-01", "NaT", "2011-03", "2011-04"], freq="M")
336
+ df1 = DataFrame({"P": data1}, index=[1, 3, 5, 7])
337
+ data2 = pd.PeriodIndex(["2012-01-01", "2012-02", "2012-03"], freq="M")
338
+ df2 = DataFrame({"P": data2}, index=[2, 4, 5])
339
+
340
+ res = df1.combine_first(df2)
341
+ exp_dts = pd.PeriodIndex(
342
+ ["2011-01", "2012-01", "NaT", "2012-02", "2011-03", "2011-04"], freq="M"
343
+ )
344
+ exp = DataFrame({"P": exp_dts}, index=[1, 2, 3, 4, 5, 7])
345
+ tm.assert_frame_equal(res, exp)
346
+ assert res["P"].dtype == data1.dtype
347
+
348
+ # different freq
349
+ dts2 = pd.PeriodIndex(["2012-01-01", "2012-01-02", "2012-01-03"], freq="D")
350
+ df2 = DataFrame({"P": dts2}, index=[2, 4, 5])
351
+
352
+ res = df1.combine_first(df2)
353
+ exp_dts = [
354
+ pd.Period("2011-01", freq="M"),
355
+ pd.Period("2012-01-01", freq="D"),
356
+ pd.NaT,
357
+ pd.Period("2012-01-02", freq="D"),
358
+ pd.Period("2011-03", freq="M"),
359
+ pd.Period("2011-04", freq="M"),
360
+ ]
361
+ exp = DataFrame({"P": exp_dts}, index=[1, 2, 3, 4, 5, 7])
362
+ tm.assert_frame_equal(res, exp)
363
+ assert res["P"].dtype == "object"
364
+
365
+ def test_combine_first_int(self):
366
+ # GH14687 - integer series that do no align exactly
367
+
368
+ df1 = DataFrame({"a": [0, 1, 3, 5]}, dtype="int64")
369
+ df2 = DataFrame({"a": [1, 4]}, dtype="int64")
370
+
371
+ result_12 = df1.combine_first(df2)
372
+ expected_12 = DataFrame({"a": [0, 1, 3, 5]})
373
+ tm.assert_frame_equal(result_12, expected_12)
374
+
375
+ result_21 = df2.combine_first(df1)
376
+ expected_21 = DataFrame({"a": [1, 4, 3, 5]})
377
+ tm.assert_frame_equal(result_21, expected_21)
378
+
379
+ @pytest.mark.parametrize("val", [1, 1.0])
380
+ def test_combine_first_with_asymmetric_other(self, val):
381
+ # see gh-20699
382
+ df1 = DataFrame({"isNum": [val]})
383
+ df2 = DataFrame({"isBool": [True]})
384
+
385
+ res = df1.combine_first(df2)
386
+ exp = DataFrame({"isBool": [True], "isNum": [val]})
387
+
388
+ tm.assert_frame_equal(res, exp)
389
+
390
+ def test_combine_first_string_dtype_only_na(self, nullable_string_dtype):
391
+ # GH: 37519
392
+ df = DataFrame(
393
+ {"a": ["962", "85"], "b": [pd.NA] * 2}, dtype=nullable_string_dtype
394
+ )
395
+ df2 = DataFrame({"a": ["85"], "b": [pd.NA]}, dtype=nullable_string_dtype)
396
+ df.set_index(["a", "b"], inplace=True)
397
+ df2.set_index(["a", "b"], inplace=True)
398
+ result = df.combine_first(df2)
399
+ expected = DataFrame(
400
+ {"a": ["962", "85"], "b": [pd.NA] * 2}, dtype=nullable_string_dtype
401
+ ).set_index(["a", "b"])
402
+ tm.assert_frame_equal(result, expected)
403
+
404
+
405
+ @pytest.mark.parametrize(
406
+ "scalar1, scalar2",
407
+ [
408
+ (datetime(2020, 1, 1), datetime(2020, 1, 2)),
409
+ (pd.Period("2020-01-01", "D"), pd.Period("2020-01-02", "D")),
410
+ (pd.Timedelta("89 days"), pd.Timedelta("60 min")),
411
+ (pd.Interval(left=0, right=1), pd.Interval(left=2, right=3, closed="left")),
412
+ ],
413
+ )
414
+ def test_combine_first_timestamp_bug(scalar1, scalar2, nulls_fixture):
415
+ # GH28481
416
+ na_value = nulls_fixture
417
+
418
+ frame = DataFrame([[na_value, na_value]], columns=["a", "b"])
419
+ other = DataFrame([[scalar1, scalar2]], columns=["b", "c"])
420
+
421
+ common_dtype = find_common_type([frame.dtypes["b"], other.dtypes["b"]])
422
+
423
+ if is_dtype_equal(common_dtype, "object") or frame.dtypes["b"] == other.dtypes["b"]:
424
+ val = scalar1
425
+ else:
426
+ val = na_value
427
+
428
+ result = frame.combine_first(other)
429
+
430
+ expected = DataFrame([[na_value, val, scalar2]], columns=["a", "b", "c"])
431
+
432
+ expected["b"] = expected["b"].astype(common_dtype)
433
+
434
+ tm.assert_frame_equal(result, expected)
435
+
436
+
437
+ def test_combine_first_timestamp_bug_NaT():
438
+ # GH28481
439
+ frame = DataFrame([[pd.NaT, pd.NaT]], columns=["a", "b"])
440
+ other = DataFrame(
441
+ [[datetime(2020, 1, 1), datetime(2020, 1, 2)]], columns=["b", "c"]
442
+ )
443
+
444
+ result = frame.combine_first(other)
445
+ expected = DataFrame(
446
+ [[pd.NaT, datetime(2020, 1, 1), datetime(2020, 1, 2)]], columns=["a", "b", "c"]
447
+ )
448
+
449
+ tm.assert_frame_equal(result, expected)
450
+
451
+
452
+ def test_combine_first_with_nan_multiindex():
453
+ # gh-36562
454
+
455
+ mi1 = MultiIndex.from_arrays(
456
+ [["b", "b", "c", "a", "b", np.nan], [1, 2, 3, 4, 5, 6]], names=["a", "b"]
457
+ )
458
+ df = DataFrame({"c": [1, 1, 1, 1, 1, 1]}, index=mi1)
459
+ mi2 = MultiIndex.from_arrays(
460
+ [["a", "b", "c", "a", "b", "d"], [1, 1, 1, 1, 1, 1]], names=["a", "b"]
461
+ )
462
+ s = Series([1, 2, 3, 4, 5, 6], index=mi2)
463
+ res = df.combine_first(DataFrame({"d": s}))
464
+ mi_expected = MultiIndex.from_arrays(
465
+ [
466
+ ["a", "a", "a", "b", "b", "b", "b", "c", "c", "d", np.nan],
467
+ [1, 1, 4, 1, 1, 2, 5, 1, 3, 1, 6],
468
+ ],
469
+ names=["a", "b"],
470
+ )
471
+ expected = DataFrame(
472
+ {
473
+ "c": [np.nan, np.nan, 1, 1, 1, 1, 1, np.nan, 1, np.nan, 1],
474
+ "d": [1.0, 4.0, np.nan, 2.0, 5.0, np.nan, np.nan, 3.0, np.nan, 6.0, np.nan],
475
+ },
476
+ index=mi_expected,
477
+ )
478
+ tm.assert_frame_equal(res, expected)
479
+
480
+
481
+ def test_combine_preserve_dtypes():
482
+ # GH7509
483
+ a_column = Series(["a", "b"], index=range(2))
484
+ b_column = Series(range(2), index=range(2))
485
+ df1 = DataFrame({"A": a_column, "B": b_column})
486
+
487
+ c_column = Series(["a", "b"], index=range(5, 7))
488
+ b_column = Series(range(-1, 1), index=range(5, 7))
489
+ df2 = DataFrame({"B": b_column, "C": c_column})
490
+
491
+ expected = DataFrame(
492
+ {
493
+ "A": ["a", "b", np.nan, np.nan],
494
+ "B": [0, 1, -1, 0],
495
+ "C": [np.nan, np.nan, "a", "b"],
496
+ },
497
+ index=[0, 1, 5, 6],
498
+ )
499
+ combined = df1.combine_first(df2)
500
+ tm.assert_frame_equal(combined, expected)
501
+
502
+
503
+ def test_combine_first_duplicates_rows_for_nan_index_values():
504
+ # GH39881
505
+ df1 = DataFrame(
506
+ {"x": [9, 10, 11]},
507
+ index=MultiIndex.from_arrays([[1, 2, 3], [np.nan, 5, 6]], names=["a", "b"]),
508
+ )
509
+
510
+ df2 = DataFrame(
511
+ {"y": [12, 13, 14]},
512
+ index=MultiIndex.from_arrays([[1, 2, 4], [np.nan, 5, 7]], names=["a", "b"]),
513
+ )
514
+
515
+ expected = DataFrame(
516
+ {
517
+ "x": [9.0, 10.0, 11.0, np.nan],
518
+ "y": [12.0, 13.0, np.nan, 14.0],
519
+ },
520
+ index=MultiIndex.from_arrays(
521
+ [[1, 2, 3, 4], [np.nan, 5, 6, 7]], names=["a", "b"]
522
+ ),
523
+ )
524
+ combined = df1.combine_first(df2)
525
+ tm.assert_frame_equal(combined, expected)
526
+
527
+
528
+ def test_combine_first_int64_not_cast_to_float64():
529
+ # GH 28613
530
+ df_1 = DataFrame({"A": [1, 2, 3], "B": [4, 5, 6]})
531
+ df_2 = DataFrame({"A": [1, 20, 30], "B": [40, 50, 60], "C": [12, 34, 65]})
532
+ result = df_1.combine_first(df_2)
533
+ expected = DataFrame({"A": [1, 2, 3], "B": [4, 5, 6], "C": [12, 34, 65]})
534
+ tm.assert_frame_equal(result, expected)
535
+
536
+
537
+ def test_midx_losing_dtype():
538
+ # GH#49830
539
+ midx = MultiIndex.from_arrays([[0, 0], [np.nan, np.nan]])
540
+ midx2 = MultiIndex.from_arrays([[1, 1], [np.nan, np.nan]])
541
+ df1 = DataFrame({"a": [None, 4]}, index=midx)
542
+ df2 = DataFrame({"a": [3, 3]}, index=midx2)
543
+ result = df1.combine_first(df2)
544
+ expected_midx = MultiIndex.from_arrays(
545
+ [[0, 0, 1, 1], [np.nan, np.nan, np.nan, np.nan]]
546
+ )
547
+ expected = DataFrame({"a": [np.nan, 4, 3, 3]}, index=expected_midx)
548
+ tm.assert_frame_equal(result, expected)
549
+
550
+
551
+ def test_combine_first_empty_columns():
552
+ left = DataFrame(columns=["a", "b"])
553
+ right = DataFrame(columns=["a", "c"])
554
+ result = left.combine_first(right)
555
+ expected = DataFrame(columns=["a", "b", "c"])
556
+ tm.assert_frame_equal(result, expected)
py311/lib/python3.11/site-packages/pandas/tests/frame/methods/test_droplevel.py ADDED
@@ -0,0 +1,36 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import pytest
2
+
3
+ from pandas import (
4
+ DataFrame,
5
+ Index,
6
+ MultiIndex,
7
+ )
8
+ import pandas._testing as tm
9
+
10
+
11
+ class TestDropLevel:
12
+ def test_droplevel(self, frame_or_series):
13
+ # GH#20342
14
+ cols = MultiIndex.from_tuples(
15
+ [("c", "e"), ("d", "f")], names=["level_1", "level_2"]
16
+ )
17
+ mi = MultiIndex.from_tuples([(1, 2), (5, 6), (9, 10)], names=["a", "b"])
18
+ df = DataFrame([[3, 4], [7, 8], [11, 12]], index=mi, columns=cols)
19
+ if frame_or_series is not DataFrame:
20
+ df = df.iloc[:, 0]
21
+
22
+ # test that dropping of a level in index works
23
+ expected = df.reset_index("a", drop=True)
24
+ result = df.droplevel("a", axis="index")
25
+ tm.assert_equal(result, expected)
26
+
27
+ if frame_or_series is DataFrame:
28
+ # test that dropping of a level in columns works
29
+ expected = df.copy()
30
+ expected.columns = Index(["c", "d"], name="level_1")
31
+ result = df.droplevel("level_2", axis="columns")
32
+ tm.assert_equal(result, expected)
33
+ else:
34
+ # test that droplevel raises ValueError on axis != 0
35
+ with pytest.raises(ValueError, match="No axis named columns"):
36
+ df.droplevel(1, axis="columns")
py311/lib/python3.11/site-packages/pandas/tests/frame/methods/test_fillna.py ADDED
@@ -0,0 +1,916 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import numpy as np
2
+ import pytest
3
+
4
+ from pandas.compat import WARNING_CHECK_DISABLED
5
+ import pandas.util._test_decorators as td
6
+
7
+ from pandas import (
8
+ Categorical,
9
+ DataFrame,
10
+ DatetimeIndex,
11
+ NaT,
12
+ PeriodIndex,
13
+ Series,
14
+ TimedeltaIndex,
15
+ Timestamp,
16
+ date_range,
17
+ to_datetime,
18
+ )
19
+ import pandas._testing as tm
20
+ from pandas.tests.frame.common import _check_mixed_float
21
+
22
+
23
+ class TestFillNA:
24
+ def test_fillna_dict_inplace_nonunique_columns(
25
+ self, using_copy_on_write, warn_copy_on_write
26
+ ):
27
+ df = DataFrame(
28
+ {"A": [np.nan] * 3, "B": [NaT, Timestamp(1), NaT], "C": [np.nan, "foo", 2]}
29
+ )
30
+ df.columns = ["A", "A", "A"]
31
+ orig = df[:]
32
+
33
+ # TODO(CoW-warn) better warning message
34
+ with tm.assert_cow_warning(warn_copy_on_write):
35
+ df.fillna({"A": 2}, inplace=True)
36
+ # The first and third columns can be set inplace, while the second cannot.
37
+
38
+ expected = DataFrame(
39
+ {"A": [2.0] * 3, "B": [2, Timestamp(1), 2], "C": [2, "foo", 2]}
40
+ )
41
+ expected.columns = ["A", "A", "A"]
42
+ tm.assert_frame_equal(df, expected)
43
+
44
+ # TODO: what's the expected/desired behavior with CoW?
45
+ if not using_copy_on_write:
46
+ assert tm.shares_memory(df.iloc[:, 0], orig.iloc[:, 0])
47
+ assert not tm.shares_memory(df.iloc[:, 1], orig.iloc[:, 1])
48
+ if not using_copy_on_write:
49
+ assert tm.shares_memory(df.iloc[:, 2], orig.iloc[:, 2])
50
+
51
+ @td.skip_array_manager_not_yet_implemented
52
+ def test_fillna_on_column_view(self, using_copy_on_write):
53
+ # GH#46149 avoid unnecessary copies
54
+ arr = np.full((40, 50), np.nan)
55
+ df = DataFrame(arr, copy=False)
56
+
57
+ if using_copy_on_write:
58
+ with tm.raises_chained_assignment_error():
59
+ df[0].fillna(-1, inplace=True)
60
+ assert np.isnan(arr[:, 0]).all()
61
+ else:
62
+ with tm.assert_produces_warning(
63
+ FutureWarning if not WARNING_CHECK_DISABLED else None,
64
+ match="inplace method",
65
+ ):
66
+ df[0].fillna(-1, inplace=True)
67
+ assert (arr[:, 0] == -1).all()
68
+
69
+ # i.e. we didn't create a new 49-column block
70
+ assert len(df._mgr.arrays) == 1
71
+ assert np.shares_memory(df.values, arr)
72
+
73
+ def test_fillna_datetime(self, datetime_frame):
74
+ tf = datetime_frame
75
+ tf.loc[tf.index[:5], "A"] = np.nan
76
+ tf.loc[tf.index[-5:], "A"] = np.nan
77
+
78
+ zero_filled = datetime_frame.fillna(0)
79
+ assert (zero_filled.loc[zero_filled.index[:5], "A"] == 0).all()
80
+
81
+ msg = "DataFrame.fillna with 'method' is deprecated"
82
+ with tm.assert_produces_warning(FutureWarning, match=msg):
83
+ padded = datetime_frame.fillna(method="pad")
84
+ assert np.isnan(padded.loc[padded.index[:5], "A"]).all()
85
+ assert (
86
+ padded.loc[padded.index[-5:], "A"] == padded.loc[padded.index[-5], "A"]
87
+ ).all()
88
+
89
+ msg = "Must specify a fill 'value' or 'method'"
90
+ with pytest.raises(ValueError, match=msg):
91
+ datetime_frame.fillna()
92
+ msg = "Cannot specify both 'value' and 'method'"
93
+ with pytest.raises(ValueError, match=msg):
94
+ datetime_frame.fillna(5, method="ffill")
95
+
96
+ def test_fillna_mixed_type(self, float_string_frame):
97
+ mf = float_string_frame
98
+ mf.loc[mf.index[5:20], "foo"] = np.nan
99
+ mf.loc[mf.index[-10:], "A"] = np.nan
100
+ # TODO: make stronger assertion here, GH 25640
101
+ mf.fillna(value=0)
102
+ msg = "DataFrame.fillna with 'method' is deprecated"
103
+ with tm.assert_produces_warning(FutureWarning, match=msg):
104
+ mf.fillna(method="pad")
105
+
106
+ def test_fillna_mixed_float(self, mixed_float_frame):
107
+ # mixed numeric (but no float16)
108
+ mf = mixed_float_frame.reindex(columns=["A", "B", "D"])
109
+ mf.loc[mf.index[-10:], "A"] = np.nan
110
+ result = mf.fillna(value=0)
111
+ _check_mixed_float(result, dtype={"C": None})
112
+
113
+ msg = "DataFrame.fillna with 'method' is deprecated"
114
+ with tm.assert_produces_warning(FutureWarning, match=msg):
115
+ result = mf.fillna(method="pad")
116
+ _check_mixed_float(result, dtype={"C": None})
117
+
118
+ def test_fillna_empty(self, using_copy_on_write):
119
+ if using_copy_on_write:
120
+ pytest.skip("condition is unnecessary complex and is deprecated anyway")
121
+ # empty frame (GH#2778)
122
+ df = DataFrame(columns=["x"])
123
+ for m in ["pad", "backfill"]:
124
+ msg = "Series.fillna with 'method' is deprecated"
125
+ with tm.assert_produces_warning(FutureWarning, match=msg):
126
+ df.x.fillna(method=m, inplace=True)
127
+ df.x.fillna(method=m)
128
+
129
+ def test_fillna_different_dtype(self):
130
+ # with different dtype (GH#3386)
131
+ df = DataFrame(
132
+ [["a", "a", np.nan, "a"], ["b", "b", np.nan, "b"], ["c", "c", np.nan, "c"]]
133
+ )
134
+
135
+ result = df.fillna({2: "foo"})
136
+ expected = DataFrame(
137
+ [["a", "a", "foo", "a"], ["b", "b", "foo", "b"], ["c", "c", "foo", "c"]]
138
+ )
139
+ # column is originally float (all-NaN) -> filling with string gives object dtype
140
+ expected[2] = expected[2].astype("object")
141
+ tm.assert_frame_equal(result, expected)
142
+
143
+ return_value = df.fillna({2: "foo"}, inplace=True)
144
+ tm.assert_frame_equal(df, expected)
145
+ assert return_value is None
146
+
147
+ def test_fillna_limit_and_value(self):
148
+ # limit and value
149
+ df = DataFrame(np.random.default_rng(2).standard_normal((10, 3)))
150
+ df.iloc[2:7, 0] = np.nan
151
+ df.iloc[3:5, 2] = np.nan
152
+
153
+ expected = df.copy()
154
+ expected.iloc[2, 0] = 999
155
+ expected.iloc[3, 2] = 999
156
+ result = df.fillna(999, limit=1)
157
+ tm.assert_frame_equal(result, expected)
158
+
159
+ def test_fillna_datelike(self):
160
+ # with datelike
161
+ # GH#6344
162
+ df = DataFrame(
163
+ {
164
+ "Date": [NaT, Timestamp("2014-1-1")],
165
+ "Date2": [Timestamp("2013-1-1"), NaT],
166
+ }
167
+ )
168
+
169
+ expected = df.copy()
170
+ expected["Date"] = expected["Date"].fillna(df.loc[df.index[0], "Date2"])
171
+ result = df.fillna(value={"Date": df["Date2"]})
172
+ tm.assert_frame_equal(result, expected)
173
+
174
+ def test_fillna_tzaware(self):
175
+ # with timezone
176
+ # GH#15855
177
+ df = DataFrame({"A": [Timestamp("2012-11-11 00:00:00+01:00"), NaT]})
178
+ exp = DataFrame(
179
+ {
180
+ "A": [
181
+ Timestamp("2012-11-11 00:00:00+01:00"),
182
+ Timestamp("2012-11-11 00:00:00+01:00"),
183
+ ]
184
+ }
185
+ )
186
+ msg = "DataFrame.fillna with 'method' is deprecated"
187
+ with tm.assert_produces_warning(FutureWarning, match=msg):
188
+ res = df.fillna(method="pad")
189
+ tm.assert_frame_equal(res, exp)
190
+
191
+ df = DataFrame({"A": [NaT, Timestamp("2012-11-11 00:00:00+01:00")]})
192
+ exp = DataFrame(
193
+ {
194
+ "A": [
195
+ Timestamp("2012-11-11 00:00:00+01:00"),
196
+ Timestamp("2012-11-11 00:00:00+01:00"),
197
+ ]
198
+ }
199
+ )
200
+ msg = "DataFrame.fillna with 'method' is deprecated"
201
+ with tm.assert_produces_warning(FutureWarning, match=msg):
202
+ res = df.fillna(method="bfill")
203
+ tm.assert_frame_equal(res, exp)
204
+
205
+ def test_fillna_tzaware_different_column(self):
206
+ # with timezone in another column
207
+ # GH#15522
208
+ df = DataFrame(
209
+ {
210
+ "A": date_range("20130101", periods=4, tz="US/Eastern"),
211
+ "B": [1, 2, np.nan, np.nan],
212
+ }
213
+ )
214
+ msg = "DataFrame.fillna with 'method' is deprecated"
215
+ with tm.assert_produces_warning(FutureWarning, match=msg):
216
+ result = df.fillna(method="pad")
217
+ expected = DataFrame(
218
+ {
219
+ "A": date_range("20130101", periods=4, tz="US/Eastern"),
220
+ "B": [1.0, 2.0, 2.0, 2.0],
221
+ }
222
+ )
223
+ tm.assert_frame_equal(result, expected)
224
+
225
+ def test_na_actions_categorical(self):
226
+ cat = Categorical([1, 2, 3, np.nan], categories=[1, 2, 3])
227
+ vals = ["a", "b", np.nan, "d"]
228
+ df = DataFrame({"cats": cat, "vals": vals})
229
+ cat2 = Categorical([1, 2, 3, 3], categories=[1, 2, 3])
230
+ vals2 = ["a", "b", "b", "d"]
231
+ df_exp_fill = DataFrame({"cats": cat2, "vals": vals2})
232
+ cat3 = Categorical([1, 2, 3], categories=[1, 2, 3])
233
+ vals3 = ["a", "b", np.nan]
234
+ df_exp_drop_cats = DataFrame({"cats": cat3, "vals": vals3})
235
+ cat4 = Categorical([1, 2], categories=[1, 2, 3])
236
+ vals4 = ["a", "b"]
237
+ df_exp_drop_all = DataFrame({"cats": cat4, "vals": vals4})
238
+
239
+ # fillna
240
+ res = df.fillna(value={"cats": 3, "vals": "b"})
241
+ tm.assert_frame_equal(res, df_exp_fill)
242
+
243
+ msg = "Cannot setitem on a Categorical with a new category"
244
+ with pytest.raises(TypeError, match=msg):
245
+ df.fillna(value={"cats": 4, "vals": "c"})
246
+
247
+ msg = "DataFrame.fillna with 'method' is deprecated"
248
+ with tm.assert_produces_warning(FutureWarning, match=msg):
249
+ res = df.fillna(method="pad")
250
+ tm.assert_frame_equal(res, df_exp_fill)
251
+
252
+ # dropna
253
+ res = df.dropna(subset=["cats"])
254
+ tm.assert_frame_equal(res, df_exp_drop_cats)
255
+
256
+ res = df.dropna()
257
+ tm.assert_frame_equal(res, df_exp_drop_all)
258
+
259
+ # make sure that fillna takes missing values into account
260
+ c = Categorical([np.nan, "b", np.nan], categories=["a", "b"])
261
+ df = DataFrame({"cats": c, "vals": [1, 2, 3]})
262
+
263
+ cat_exp = Categorical(["a", "b", "a"], categories=["a", "b"])
264
+ df_exp = DataFrame({"cats": cat_exp, "vals": [1, 2, 3]})
265
+
266
+ res = df.fillna("a")
267
+ tm.assert_frame_equal(res, df_exp)
268
+
269
+ def test_fillna_categorical_nan(self):
270
+ # GH#14021
271
+ # np.nan should always be a valid filler
272
+ cat = Categorical([np.nan, 2, np.nan])
273
+ val = Categorical([np.nan, np.nan, np.nan])
274
+ df = DataFrame({"cats": cat, "vals": val})
275
+
276
+ # GH#32950 df.median() is poorly behaved because there is no
277
+ # Categorical.median
278
+ median = Series({"cats": 2.0, "vals": np.nan})
279
+
280
+ res = df.fillna(median)
281
+ v_exp = [np.nan, np.nan, np.nan]
282
+ df_exp = DataFrame({"cats": [2, 2, 2], "vals": v_exp}, dtype="category")
283
+ tm.assert_frame_equal(res, df_exp)
284
+
285
+ result = df.cats.fillna(np.nan)
286
+ tm.assert_series_equal(result, df.cats)
287
+
288
+ result = df.vals.fillna(np.nan)
289
+ tm.assert_series_equal(result, df.vals)
290
+
291
+ idx = DatetimeIndex(
292
+ ["2011-01-01 09:00", "2016-01-01 23:45", "2011-01-01 09:00", NaT, NaT]
293
+ )
294
+ df = DataFrame({"a": Categorical(idx)})
295
+ tm.assert_frame_equal(df.fillna(value=NaT), df)
296
+
297
+ idx = PeriodIndex(["2011-01", "2011-01", "2011-01", NaT, NaT], freq="M")
298
+ df = DataFrame({"a": Categorical(idx)})
299
+ tm.assert_frame_equal(df.fillna(value=NaT), df)
300
+
301
+ idx = TimedeltaIndex(["1 days", "2 days", "1 days", NaT, NaT])
302
+ df = DataFrame({"a": Categorical(idx)})
303
+ tm.assert_frame_equal(df.fillna(value=NaT), df)
304
+
305
+ def test_fillna_downcast(self):
306
+ # GH#15277
307
+ # infer int64 from float64
308
+ df = DataFrame({"a": [1.0, np.nan]})
309
+ msg = "The 'downcast' keyword in fillna is deprecated"
310
+ with tm.assert_produces_warning(FutureWarning, match=msg):
311
+ result = df.fillna(0, downcast="infer")
312
+ expected = DataFrame({"a": [1, 0]})
313
+ tm.assert_frame_equal(result, expected)
314
+
315
+ # infer int64 from float64 when fillna value is a dict
316
+ df = DataFrame({"a": [1.0, np.nan]})
317
+ with tm.assert_produces_warning(FutureWarning, match=msg):
318
+ result = df.fillna({"a": 0}, downcast="infer")
319
+ expected = DataFrame({"a": [1, 0]})
320
+ tm.assert_frame_equal(result, expected)
321
+
322
+ def test_fillna_downcast_false(self, frame_or_series):
323
+ # GH#45603 preserve object dtype with downcast=False
324
+ obj = frame_or_series([1, 2, 3], dtype="object")
325
+ msg = "The 'downcast' keyword in fillna"
326
+ with tm.assert_produces_warning(FutureWarning, match=msg):
327
+ result = obj.fillna("", downcast=False)
328
+ tm.assert_equal(result, obj)
329
+
330
+ def test_fillna_downcast_noop(self, frame_or_series):
331
+ # GH#45423
332
+ # Two relevant paths:
333
+ # 1) not _can_hold_na (e.g. integer)
334
+ # 2) _can_hold_na + noop + not can_hold_element
335
+
336
+ obj = frame_or_series([1, 2, 3], dtype=np.int64)
337
+
338
+ msg = "The 'downcast' keyword in fillna"
339
+ with tm.assert_produces_warning(FutureWarning, match=msg):
340
+ # GH#40988
341
+ res = obj.fillna("foo", downcast=np.dtype(np.int32))
342
+ expected = obj.astype(np.int32)
343
+ tm.assert_equal(res, expected)
344
+
345
+ obj2 = obj.astype(np.float64)
346
+ with tm.assert_produces_warning(FutureWarning, match=msg):
347
+ res2 = obj2.fillna("foo", downcast="infer")
348
+ expected2 = obj # get back int64
349
+ tm.assert_equal(res2, expected2)
350
+
351
+ with tm.assert_produces_warning(FutureWarning, match=msg):
352
+ # GH#40988
353
+ res3 = obj2.fillna("foo", downcast=np.dtype(np.int32))
354
+ tm.assert_equal(res3, expected)
355
+
356
+ @pytest.mark.parametrize("columns", [["A", "A", "B"], ["A", "A"]])
357
+ def test_fillna_dictlike_value_duplicate_colnames(self, columns):
358
+ # GH#43476
359
+ df = DataFrame(np.nan, index=[0, 1], columns=columns)
360
+ with tm.assert_produces_warning(None):
361
+ result = df.fillna({"A": 0})
362
+
363
+ expected = df.copy()
364
+ expected["A"] = 0.0
365
+ tm.assert_frame_equal(result, expected)
366
+
367
+ def test_fillna_dtype_conversion(self, using_infer_string):
368
+ # make sure that fillna on an empty frame works
369
+ df = DataFrame(index=["A", "B", "C"], columns=[1, 2, 3, 4, 5])
370
+ result = df.dtypes
371
+ expected = Series([np.dtype("object")] * 5, index=[1, 2, 3, 4, 5])
372
+ tm.assert_series_equal(result, expected)
373
+
374
+ msg = "Downcasting object dtype arrays"
375
+ with tm.assert_produces_warning(FutureWarning, match=msg):
376
+ result = df.fillna(1)
377
+ expected = DataFrame(1, index=["A", "B", "C"], columns=[1, 2, 3, 4, 5])
378
+ tm.assert_frame_equal(result, expected)
379
+
380
+ # empty block
381
+ df = DataFrame(index=range(3), columns=["A", "B"], dtype="float64")
382
+ result = df.fillna("nan")
383
+ expected = DataFrame("nan", index=range(3), columns=["A", "B"], dtype=object)
384
+ tm.assert_frame_equal(result, expected)
385
+
386
+ @pytest.mark.parametrize("val", ["", 1, np.nan, 1.0])
387
+ def test_fillna_dtype_conversion_equiv_replace(self, val):
388
+ df = DataFrame({"A": [1, np.nan], "B": [1.0, 2.0]})
389
+ expected = df.replace(np.nan, val)
390
+ result = df.fillna(val)
391
+ tm.assert_frame_equal(result, expected)
392
+
393
+ def test_fillna_datetime_columns(self):
394
+ # GH#7095
395
+ df = DataFrame(
396
+ {
397
+ "A": [-1, -2, np.nan],
398
+ "B": date_range("20130101", periods=3),
399
+ "C": ["foo", "bar", None],
400
+ "D": ["foo2", "bar2", None],
401
+ },
402
+ index=date_range("20130110", periods=3),
403
+ )
404
+ result = df.fillna("?")
405
+ expected = DataFrame(
406
+ {
407
+ "A": [-1, -2, "?"],
408
+ "B": date_range("20130101", periods=3),
409
+ "C": ["foo", "bar", "?"],
410
+ "D": ["foo2", "bar2", "?"],
411
+ },
412
+ index=date_range("20130110", periods=3),
413
+ )
414
+ tm.assert_frame_equal(result, expected)
415
+
416
+ df = DataFrame(
417
+ {
418
+ "A": [-1, -2, np.nan],
419
+ "B": [Timestamp("2013-01-01"), Timestamp("2013-01-02"), NaT],
420
+ "C": ["foo", "bar", None],
421
+ "D": ["foo2", "bar2", None],
422
+ },
423
+ index=date_range("20130110", periods=3),
424
+ )
425
+ result = df.fillna("?")
426
+ expected = DataFrame(
427
+ {
428
+ "A": [-1, -2, "?"],
429
+ "B": [Timestamp("2013-01-01"), Timestamp("2013-01-02"), "?"],
430
+ "C": ["foo", "bar", "?"],
431
+ "D": ["foo2", "bar2", "?"],
432
+ },
433
+ index=date_range("20130110", periods=3),
434
+ )
435
+ tm.assert_frame_equal(result, expected)
436
+
437
+ def test_ffill(self, datetime_frame):
438
+ datetime_frame.loc[datetime_frame.index[:5], "A"] = np.nan
439
+ datetime_frame.loc[datetime_frame.index[-5:], "A"] = np.nan
440
+
441
+ msg = "DataFrame.fillna with 'method' is deprecated"
442
+ with tm.assert_produces_warning(FutureWarning, match=msg):
443
+ alt = datetime_frame.fillna(method="ffill")
444
+ tm.assert_frame_equal(datetime_frame.ffill(), alt)
445
+
446
+ def test_bfill(self, datetime_frame):
447
+ datetime_frame.loc[datetime_frame.index[:5], "A"] = np.nan
448
+ datetime_frame.loc[datetime_frame.index[-5:], "A"] = np.nan
449
+
450
+ msg = "DataFrame.fillna with 'method' is deprecated"
451
+ with tm.assert_produces_warning(FutureWarning, match=msg):
452
+ alt = datetime_frame.fillna(method="bfill")
453
+
454
+ tm.assert_frame_equal(datetime_frame.bfill(), alt)
455
+
456
+ def test_frame_pad_backfill_limit(self):
457
+ index = np.arange(10)
458
+ df = DataFrame(np.random.default_rng(2).standard_normal((10, 4)), index=index)
459
+
460
+ result = df[:2].reindex(index, method="pad", limit=5)
461
+
462
+ msg = "DataFrame.fillna with 'method' is deprecated"
463
+ with tm.assert_produces_warning(FutureWarning, match=msg):
464
+ expected = df[:2].reindex(index).fillna(method="pad")
465
+ expected.iloc[-3:] = np.nan
466
+ tm.assert_frame_equal(result, expected)
467
+
468
+ result = df[-2:].reindex(index, method="backfill", limit=5)
469
+
470
+ with tm.assert_produces_warning(FutureWarning, match=msg):
471
+ expected = df[-2:].reindex(index).fillna(method="backfill")
472
+ expected.iloc[:3] = np.nan
473
+ tm.assert_frame_equal(result, expected)
474
+
475
+ def test_frame_fillna_limit(self):
476
+ index = np.arange(10)
477
+ df = DataFrame(np.random.default_rng(2).standard_normal((10, 4)), index=index)
478
+
479
+ result = df[:2].reindex(index)
480
+ msg = "DataFrame.fillna with 'method' is deprecated"
481
+ with tm.assert_produces_warning(FutureWarning, match=msg):
482
+ result = result.fillna(method="pad", limit=5)
483
+
484
+ with tm.assert_produces_warning(FutureWarning, match=msg):
485
+ expected = df[:2].reindex(index).fillna(method="pad")
486
+ expected.iloc[-3:] = np.nan
487
+ tm.assert_frame_equal(result, expected)
488
+
489
+ result = df[-2:].reindex(index)
490
+ with tm.assert_produces_warning(FutureWarning, match=msg):
491
+ result = result.fillna(method="backfill", limit=5)
492
+
493
+ with tm.assert_produces_warning(FutureWarning, match=msg):
494
+ expected = df[-2:].reindex(index).fillna(method="backfill")
495
+ expected.iloc[:3] = np.nan
496
+ tm.assert_frame_equal(result, expected)
497
+
498
+ def test_fillna_skip_certain_blocks(self):
499
+ # don't try to fill boolean, int blocks
500
+
501
+ df = DataFrame(np.random.default_rng(2).standard_normal((10, 4)).astype(int))
502
+
503
+ # it works!
504
+ df.fillna(np.nan)
505
+
506
+ @pytest.mark.parametrize("type", [int, float])
507
+ def test_fillna_positive_limit(self, type):
508
+ df = DataFrame(np.random.default_rng(2).standard_normal((10, 4))).astype(type)
509
+
510
+ msg = "Limit must be greater than 0"
511
+ with pytest.raises(ValueError, match=msg):
512
+ df.fillna(0, limit=-5)
513
+
514
+ @pytest.mark.parametrize("type", [int, float])
515
+ def test_fillna_integer_limit(self, type):
516
+ df = DataFrame(np.random.default_rng(2).standard_normal((10, 4))).astype(type)
517
+
518
+ msg = "Limit must be an integer"
519
+ with pytest.raises(ValueError, match=msg):
520
+ df.fillna(0, limit=0.5)
521
+
522
+ def test_fillna_inplace(self):
523
+ df = DataFrame(np.random.default_rng(2).standard_normal((10, 4)))
524
+ df.loc[:4, 1] = np.nan
525
+ df.loc[-4:, 3] = np.nan
526
+
527
+ expected = df.fillna(value=0)
528
+ assert expected is not df
529
+
530
+ df.fillna(value=0, inplace=True)
531
+ tm.assert_frame_equal(df, expected)
532
+
533
+ expected = df.fillna(value={0: 0}, inplace=True)
534
+ assert expected is None
535
+
536
+ df.loc[:4, 1] = np.nan
537
+ df.loc[-4:, 3] = np.nan
538
+ msg = "DataFrame.fillna with 'method' is deprecated"
539
+ with tm.assert_produces_warning(FutureWarning, match=msg):
540
+ expected = df.fillna(method="ffill")
541
+ assert expected is not df
542
+
543
+ with tm.assert_produces_warning(FutureWarning, match=msg):
544
+ df.fillna(method="ffill", inplace=True)
545
+ tm.assert_frame_equal(df, expected)
546
+
547
+ def test_fillna_dict_series(self):
548
+ df = DataFrame(
549
+ {
550
+ "a": [np.nan, 1, 2, np.nan, np.nan],
551
+ "b": [1, 2, 3, np.nan, np.nan],
552
+ "c": [np.nan, 1, 2, 3, 4],
553
+ }
554
+ )
555
+
556
+ result = df.fillna({"a": 0, "b": 5})
557
+
558
+ expected = df.copy()
559
+ expected["a"] = expected["a"].fillna(0)
560
+ expected["b"] = expected["b"].fillna(5)
561
+ tm.assert_frame_equal(result, expected)
562
+
563
+ # it works
564
+ result = df.fillna({"a": 0, "b": 5, "d": 7})
565
+
566
+ # Series treated same as dict
567
+ result = df.fillna(df.max())
568
+ expected = df.fillna(df.max().to_dict())
569
+ tm.assert_frame_equal(result, expected)
570
+
571
+ # disable this for now
572
+ with pytest.raises(NotImplementedError, match="column by column"):
573
+ df.fillna(df.max(1), axis=1)
574
+
575
+ def test_fillna_dataframe(self):
576
+ # GH#8377
577
+ df = DataFrame(
578
+ {
579
+ "a": [np.nan, 1, 2, np.nan, np.nan],
580
+ "b": [1, 2, 3, np.nan, np.nan],
581
+ "c": [np.nan, 1, 2, 3, 4],
582
+ },
583
+ index=list("VWXYZ"),
584
+ )
585
+
586
+ # df2 may have different index and columns
587
+ df2 = DataFrame(
588
+ {
589
+ "a": [np.nan, 10, 20, 30, 40],
590
+ "b": [50, 60, 70, 80, 90],
591
+ "foo": ["bar"] * 5,
592
+ },
593
+ index=list("VWXuZ"),
594
+ )
595
+
596
+ result = df.fillna(df2)
597
+
598
+ # only those columns and indices which are shared get filled
599
+ expected = DataFrame(
600
+ {
601
+ "a": [np.nan, 1, 2, np.nan, 40],
602
+ "b": [1, 2, 3, np.nan, 90],
603
+ "c": [np.nan, 1, 2, 3, 4],
604
+ },
605
+ index=list("VWXYZ"),
606
+ )
607
+
608
+ tm.assert_frame_equal(result, expected)
609
+
610
+ def test_fillna_columns(self):
611
+ arr = np.random.default_rng(2).standard_normal((10, 10))
612
+ arr[:, ::2] = np.nan
613
+ df = DataFrame(arr)
614
+
615
+ msg = "DataFrame.fillna with 'method' is deprecated"
616
+ with tm.assert_produces_warning(FutureWarning, match=msg):
617
+ result = df.fillna(method="ffill", axis=1)
618
+ with tm.assert_produces_warning(FutureWarning, match=msg):
619
+ expected = df.T.fillna(method="pad").T
620
+ tm.assert_frame_equal(result, expected)
621
+
622
+ df.insert(6, "foo", 5)
623
+ with tm.assert_produces_warning(FutureWarning, match=msg):
624
+ result = df.fillna(method="ffill", axis=1)
625
+ with tm.assert_produces_warning(FutureWarning, match=msg):
626
+ expected = df.astype(float).fillna(method="ffill", axis=1)
627
+ tm.assert_frame_equal(result, expected)
628
+
629
+ def test_fillna_invalid_method(self, float_frame):
630
+ with pytest.raises(ValueError, match="ffil"):
631
+ float_frame.fillna(method="ffil")
632
+
633
+ def test_fillna_invalid_value(self, float_frame):
634
+ # list
635
+ msg = '"value" parameter must be a scalar or dict, but you passed a "{}"'
636
+ with pytest.raises(TypeError, match=msg.format("list")):
637
+ float_frame.fillna([1, 2])
638
+ # tuple
639
+ with pytest.raises(TypeError, match=msg.format("tuple")):
640
+ float_frame.fillna((1, 2))
641
+ # frame with series
642
+ msg = (
643
+ '"value" parameter must be a scalar, dict or Series, but you '
644
+ 'passed a "DataFrame"'
645
+ )
646
+ with pytest.raises(TypeError, match=msg):
647
+ float_frame.iloc[:, 0].fillna(float_frame)
648
+
649
+ def test_fillna_col_reordering(self):
650
+ cols = ["COL." + str(i) for i in range(5, 0, -1)]
651
+ data = np.random.default_rng(2).random((20, 5))
652
+ df = DataFrame(index=range(20), columns=cols, data=data)
653
+ msg = "DataFrame.fillna with 'method' is deprecated"
654
+ with tm.assert_produces_warning(FutureWarning, match=msg):
655
+ filled = df.fillna(method="ffill")
656
+ assert df.columns.tolist() == filled.columns.tolist()
657
+
658
+ def test_fill_empty(self, float_frame):
659
+ df = float_frame.reindex(columns=[])
660
+ result = df.fillna(value=0)
661
+ tm.assert_frame_equal(result, df)
662
+
663
+ def test_fillna_downcast_dict(self):
664
+ # GH#40809
665
+ df = DataFrame({"col1": [1, np.nan]})
666
+
667
+ msg = "The 'downcast' keyword in fillna"
668
+ with tm.assert_produces_warning(FutureWarning, match=msg):
669
+ result = df.fillna({"col1": 2}, downcast={"col1": "int64"})
670
+ expected = DataFrame({"col1": [1, 2]})
671
+ tm.assert_frame_equal(result, expected)
672
+
673
+ def test_fillna_with_columns_and_limit(self):
674
+ # GH40989
675
+ df = DataFrame(
676
+ [
677
+ [np.nan, 2, np.nan, 0],
678
+ [3, 4, np.nan, 1],
679
+ [np.nan, np.nan, np.nan, 5],
680
+ [np.nan, 3, np.nan, 4],
681
+ ],
682
+ columns=list("ABCD"),
683
+ )
684
+ result = df.fillna(axis=1, value=100, limit=1)
685
+ result2 = df.fillna(axis=1, value=100, limit=2)
686
+
687
+ expected = DataFrame(
688
+ {
689
+ "A": Series([100, 3, 100, 100], dtype="float64"),
690
+ "B": [2, 4, np.nan, 3],
691
+ "C": [np.nan, 100, np.nan, np.nan],
692
+ "D": Series([0, 1, 5, 4], dtype="float64"),
693
+ },
694
+ index=[0, 1, 2, 3],
695
+ )
696
+ expected2 = DataFrame(
697
+ {
698
+ "A": Series([100, 3, 100, 100], dtype="float64"),
699
+ "B": Series([2, 4, 100, 3], dtype="float64"),
700
+ "C": [100, 100, np.nan, 100],
701
+ "D": Series([0, 1, 5, 4], dtype="float64"),
702
+ },
703
+ index=[0, 1, 2, 3],
704
+ )
705
+
706
+ tm.assert_frame_equal(result, expected)
707
+ tm.assert_frame_equal(result2, expected2)
708
+
709
+ def test_fillna_datetime_inplace(self):
710
+ # GH#48863
711
+ df = DataFrame(
712
+ {
713
+ "date1": to_datetime(["2018-05-30", None]),
714
+ "date2": to_datetime(["2018-09-30", None]),
715
+ }
716
+ )
717
+ expected = df.copy()
718
+ df.fillna(np.nan, inplace=True)
719
+ tm.assert_frame_equal(df, expected)
720
+
721
+ def test_fillna_inplace_with_columns_limit_and_value(self):
722
+ # GH40989
723
+ df = DataFrame(
724
+ [
725
+ [np.nan, 2, np.nan, 0],
726
+ [3, 4, np.nan, 1],
727
+ [np.nan, np.nan, np.nan, 5],
728
+ [np.nan, 3, np.nan, 4],
729
+ ],
730
+ columns=list("ABCD"),
731
+ )
732
+
733
+ expected = df.fillna(axis=1, value=100, limit=1)
734
+ assert expected is not df
735
+
736
+ df.fillna(axis=1, value=100, limit=1, inplace=True)
737
+ tm.assert_frame_equal(df, expected)
738
+
739
+ @td.skip_array_manager_invalid_test
740
+ @pytest.mark.parametrize("val", [-1, {"x": -1, "y": -1}])
741
+ def test_inplace_dict_update_view(
742
+ self, val, using_copy_on_write, warn_copy_on_write
743
+ ):
744
+ # GH#47188
745
+ df = DataFrame({"x": [np.nan, 2], "y": [np.nan, 2]})
746
+ df_orig = df.copy()
747
+ result_view = df[:]
748
+ with tm.assert_cow_warning(warn_copy_on_write):
749
+ df.fillna(val, inplace=True)
750
+ expected = DataFrame({"x": [-1, 2.0], "y": [-1.0, 2]})
751
+ tm.assert_frame_equal(df, expected)
752
+ if using_copy_on_write:
753
+ tm.assert_frame_equal(result_view, df_orig)
754
+ else:
755
+ tm.assert_frame_equal(result_view, expected)
756
+
757
+ def test_single_block_df_with_horizontal_axis(self):
758
+ # GH 47713
759
+ df = DataFrame(
760
+ {
761
+ "col1": [5, 0, np.nan, 10, np.nan],
762
+ "col2": [7, np.nan, np.nan, 5, 3],
763
+ "col3": [12, np.nan, 1, 2, 0],
764
+ "col4": [np.nan, 1, 1, np.nan, 18],
765
+ }
766
+ )
767
+ result = df.fillna(50, limit=1, axis=1)
768
+ expected = DataFrame(
769
+ [
770
+ [5.0, 7.0, 12.0, 50.0],
771
+ [0.0, 50.0, np.nan, 1.0],
772
+ [50.0, np.nan, 1.0, 1.0],
773
+ [10.0, 5.0, 2.0, 50.0],
774
+ [50.0, 3.0, 0.0, 18.0],
775
+ ],
776
+ columns=["col1", "col2", "col3", "col4"],
777
+ )
778
+ tm.assert_frame_equal(result, expected)
779
+
780
+ def test_fillna_with_multi_index_frame(self):
781
+ # GH 47649
782
+ pdf = DataFrame(
783
+ {
784
+ ("x", "a"): [np.nan, 2.0, 3.0],
785
+ ("x", "b"): [1.0, 2.0, np.nan],
786
+ ("y", "c"): [1.0, 2.0, np.nan],
787
+ }
788
+ )
789
+ expected = DataFrame(
790
+ {
791
+ ("x", "a"): [-1.0, 2.0, 3.0],
792
+ ("x", "b"): [1.0, 2.0, -1.0],
793
+ ("y", "c"): [1.0, 2.0, np.nan],
794
+ }
795
+ )
796
+ tm.assert_frame_equal(pdf.fillna({"x": -1}), expected)
797
+ tm.assert_frame_equal(pdf.fillna({"x": -1, ("x", "b"): -2}), expected)
798
+
799
+ expected = DataFrame(
800
+ {
801
+ ("x", "a"): [-1.0, 2.0, 3.0],
802
+ ("x", "b"): [1.0, 2.0, -2.0],
803
+ ("y", "c"): [1.0, 2.0, np.nan],
804
+ }
805
+ )
806
+ tm.assert_frame_equal(pdf.fillna({("x", "b"): -2, "x": -1}), expected)
807
+
808
+
809
+ def test_fillna_nonconsolidated_frame():
810
+ # https://github.com/pandas-dev/pandas/issues/36495
811
+ df = DataFrame(
812
+ [
813
+ [1, 1, 1, 1.0],
814
+ [2, 2, 2, 2.0],
815
+ [3, 3, 3, 3.0],
816
+ ],
817
+ columns=["i1", "i2", "i3", "f1"],
818
+ )
819
+ df_nonconsol = df.pivot(index="i1", columns="i2")
820
+ result = df_nonconsol.fillna(0)
821
+ assert result.isna().sum().sum() == 0
822
+
823
+
824
+ def test_fillna_nones_inplace():
825
+ # GH 48480
826
+ df = DataFrame(
827
+ [[None, None], [None, None]],
828
+ columns=["A", "B"],
829
+ )
830
+ msg = "Downcasting object dtype arrays"
831
+ with tm.assert_produces_warning(FutureWarning, match=msg):
832
+ df.fillna(value={"A": 1, "B": 2}, inplace=True)
833
+
834
+ expected = DataFrame([[1, 2], [1, 2]], columns=["A", "B"])
835
+ tm.assert_frame_equal(df, expected)
836
+
837
+
838
+ @pytest.mark.parametrize("func", ["pad", "backfill"])
839
+ def test_pad_backfill_deprecated(func):
840
+ # GH#33396
841
+ df = DataFrame({"a": [1, 2, 3]})
842
+ with tm.assert_produces_warning(FutureWarning):
843
+ getattr(df, func)()
844
+
845
+
846
+ @pytest.mark.parametrize(
847
+ "data, expected_data, method, kwargs",
848
+ (
849
+ (
850
+ [np.nan, np.nan, 3, np.nan, np.nan, np.nan, 7, np.nan, np.nan],
851
+ [np.nan, np.nan, 3.0, 3.0, 3.0, 3.0, 7.0, np.nan, np.nan],
852
+ "ffill",
853
+ {"limit_area": "inside"},
854
+ ),
855
+ (
856
+ [np.nan, np.nan, 3, np.nan, np.nan, np.nan, 7, np.nan, np.nan],
857
+ [np.nan, np.nan, 3.0, 3.0, np.nan, np.nan, 7.0, np.nan, np.nan],
858
+ "ffill",
859
+ {"limit_area": "inside", "limit": 1},
860
+ ),
861
+ (
862
+ [np.nan, np.nan, 3, np.nan, np.nan, np.nan, 7, np.nan, np.nan],
863
+ [np.nan, np.nan, 3.0, np.nan, np.nan, np.nan, 7.0, 7.0, 7.0],
864
+ "ffill",
865
+ {"limit_area": "outside"},
866
+ ),
867
+ (
868
+ [np.nan, np.nan, 3, np.nan, np.nan, np.nan, 7, np.nan, np.nan],
869
+ [np.nan, np.nan, 3.0, np.nan, np.nan, np.nan, 7.0, 7.0, np.nan],
870
+ "ffill",
871
+ {"limit_area": "outside", "limit": 1},
872
+ ),
873
+ (
874
+ [np.nan, np.nan, np.nan, np.nan, np.nan, np.nan, np.nan],
875
+ [np.nan, np.nan, np.nan, np.nan, np.nan, np.nan, np.nan],
876
+ "ffill",
877
+ {"limit_area": "outside", "limit": 1},
878
+ ),
879
+ (
880
+ range(5),
881
+ range(5),
882
+ "ffill",
883
+ {"limit_area": "outside", "limit": 1},
884
+ ),
885
+ (
886
+ [np.nan, np.nan, 3, np.nan, np.nan, np.nan, 7, np.nan, np.nan],
887
+ [np.nan, np.nan, 3.0, 7.0, 7.0, 7.0, 7.0, np.nan, np.nan],
888
+ "bfill",
889
+ {"limit_area": "inside"},
890
+ ),
891
+ (
892
+ [np.nan, np.nan, 3, np.nan, np.nan, np.nan, 7, np.nan, np.nan],
893
+ [np.nan, np.nan, 3.0, np.nan, np.nan, 7.0, 7.0, np.nan, np.nan],
894
+ "bfill",
895
+ {"limit_area": "inside", "limit": 1},
896
+ ),
897
+ (
898
+ [np.nan, np.nan, 3, np.nan, np.nan, np.nan, 7, np.nan, np.nan],
899
+ [3.0, 3.0, 3.0, np.nan, np.nan, np.nan, 7.0, np.nan, np.nan],
900
+ "bfill",
901
+ {"limit_area": "outside"},
902
+ ),
903
+ (
904
+ [np.nan, np.nan, 3, np.nan, np.nan, np.nan, 7, np.nan, np.nan],
905
+ [np.nan, 3.0, 3.0, np.nan, np.nan, np.nan, 7.0, np.nan, np.nan],
906
+ "bfill",
907
+ {"limit_area": "outside", "limit": 1},
908
+ ),
909
+ ),
910
+ )
911
+ def test_ffill_bfill_limit_area(data, expected_data, method, kwargs):
912
+ # GH#56492
913
+ df = DataFrame(data)
914
+ expected = DataFrame(expected_data)
915
+ result = getattr(df, method)(**kwargs)
916
+ tm.assert_frame_equal(result, expected)
py311/lib/python3.11/site-packages/pandas/tests/frame/methods/test_filter.py ADDED
@@ -0,0 +1,153 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import numpy as np
2
+ import pytest
3
+
4
+ import pandas as pd
5
+ from pandas import DataFrame
6
+ import pandas._testing as tm
7
+
8
+
9
+ class TestDataFrameFilter:
10
+ def test_filter(self, float_frame, float_string_frame):
11
+ # Items
12
+ filtered = float_frame.filter(["A", "B", "E"])
13
+ assert len(filtered.columns) == 2
14
+ assert "E" not in filtered
15
+
16
+ filtered = float_frame.filter(["A", "B", "E"], axis="columns")
17
+ assert len(filtered.columns) == 2
18
+ assert "E" not in filtered
19
+
20
+ # Other axis
21
+ idx = float_frame.index[0:4]
22
+ filtered = float_frame.filter(idx, axis="index")
23
+ expected = float_frame.reindex(index=idx)
24
+ tm.assert_frame_equal(filtered, expected)
25
+
26
+ # like
27
+ fcopy = float_frame.copy()
28
+ fcopy["AA"] = 1
29
+
30
+ filtered = fcopy.filter(like="A")
31
+ assert len(filtered.columns) == 2
32
+ assert "AA" in filtered
33
+
34
+ # like with ints in column names
35
+ df = DataFrame(0.0, index=[0, 1, 2], columns=[0, 1, "_A", "_B"])
36
+ filtered = df.filter(like="_")
37
+ assert len(filtered.columns) == 2
38
+
39
+ # regex with ints in column names
40
+ # from PR #10384
41
+ df = DataFrame(0.0, index=[0, 1, 2], columns=["A1", 1, "B", 2, "C"])
42
+ expected = DataFrame(
43
+ 0.0, index=[0, 1, 2], columns=pd.Index([1, 2], dtype=object)
44
+ )
45
+ filtered = df.filter(regex="^[0-9]+$")
46
+ tm.assert_frame_equal(filtered, expected)
47
+
48
+ expected = DataFrame(0.0, index=[0, 1, 2], columns=[0, "0", 1, "1"])
49
+ # shouldn't remove anything
50
+ filtered = expected.filter(regex="^[0-9]+$")
51
+ tm.assert_frame_equal(filtered, expected)
52
+
53
+ # pass in None
54
+ with pytest.raises(TypeError, match="Must pass"):
55
+ float_frame.filter()
56
+ with pytest.raises(TypeError, match="Must pass"):
57
+ float_frame.filter(items=None)
58
+ with pytest.raises(TypeError, match="Must pass"):
59
+ float_frame.filter(axis=1)
60
+
61
+ # test mutually exclusive arguments
62
+ with pytest.raises(TypeError, match="mutually exclusive"):
63
+ float_frame.filter(items=["one", "three"], regex="e$", like="bbi")
64
+ with pytest.raises(TypeError, match="mutually exclusive"):
65
+ float_frame.filter(items=["one", "three"], regex="e$", axis=1)
66
+ with pytest.raises(TypeError, match="mutually exclusive"):
67
+ float_frame.filter(items=["one", "three"], regex="e$")
68
+ with pytest.raises(TypeError, match="mutually exclusive"):
69
+ float_frame.filter(items=["one", "three"], like="bbi", axis=0)
70
+ with pytest.raises(TypeError, match="mutually exclusive"):
71
+ float_frame.filter(items=["one", "three"], like="bbi")
72
+
73
+ # objects
74
+ filtered = float_string_frame.filter(like="foo")
75
+ assert "foo" in filtered
76
+
77
+ # unicode columns, won't ascii-encode
78
+ df = float_frame.rename(columns={"B": "\u2202"})
79
+ filtered = df.filter(like="C")
80
+ assert "C" in filtered
81
+
82
+ def test_filter_regex_search(self, float_frame):
83
+ fcopy = float_frame.copy()
84
+ fcopy["AA"] = 1
85
+
86
+ # regex
87
+ filtered = fcopy.filter(regex="[A]+")
88
+ assert len(filtered.columns) == 2
89
+ assert "AA" in filtered
90
+
91
+ # doesn't have to be at beginning
92
+ df = DataFrame(
93
+ {"aBBa": [1, 2], "BBaBB": [1, 2], "aCCa": [1, 2], "aCCaBB": [1, 2]}
94
+ )
95
+
96
+ result = df.filter(regex="BB")
97
+ exp = df[[x for x in df.columns if "BB" in x]]
98
+ tm.assert_frame_equal(result, exp)
99
+
100
+ @pytest.mark.parametrize(
101
+ "name,expected",
102
+ [
103
+ ("a", DataFrame({"a": [1, 2]})),
104
+ ("a", DataFrame({"a": [1, 2]})),
105
+ ("あ", DataFrame({"あ": [3, 4]})),
106
+ ],
107
+ )
108
+ def test_filter_unicode(self, name, expected):
109
+ # GH13101
110
+ df = DataFrame({"a": [1, 2], "あ": [3, 4]})
111
+
112
+ tm.assert_frame_equal(df.filter(like=name), expected)
113
+ tm.assert_frame_equal(df.filter(regex=name), expected)
114
+
115
+ @pytest.mark.parametrize("name", ["a", "a"])
116
+ def test_filter_bytestring(self, name):
117
+ # GH13101
118
+ df = DataFrame({b"a": [1, 2], b"b": [3, 4]})
119
+ expected = DataFrame({b"a": [1, 2]})
120
+
121
+ tm.assert_frame_equal(df.filter(like=name), expected)
122
+ tm.assert_frame_equal(df.filter(regex=name), expected)
123
+
124
+ def test_filter_corner(self):
125
+ empty = DataFrame()
126
+
127
+ result = empty.filter([])
128
+ tm.assert_frame_equal(result, empty)
129
+
130
+ result = empty.filter(like="foo")
131
+ tm.assert_frame_equal(result, empty)
132
+
133
+ def test_filter_regex_non_string(self):
134
+ # GH#5798 trying to filter on non-string columns should drop,
135
+ # not raise
136
+ df = DataFrame(np.random.default_rng(2).random((3, 2)), columns=["STRING", 123])
137
+ result = df.filter(regex="STRING")
138
+ expected = df[["STRING"]]
139
+ tm.assert_frame_equal(result, expected)
140
+
141
+ def test_filter_keep_order(self):
142
+ # GH#54980
143
+ df = DataFrame({"A": [1, 2, 3], "B": [4, 5, 6]})
144
+ result = df.filter(items=["B", "A"])
145
+ expected = df[["B", "A"]]
146
+ tm.assert_frame_equal(result, expected)
147
+
148
+ def test_filter_different_dtype(self):
149
+ # GH#54980
150
+ df = DataFrame({1: [1, 2, 3], 2: [4, 5, 6]})
151
+ result = df.filter(items=["B", "A"])
152
+ expected = df[[]]
153
+ tm.assert_frame_equal(result, expected)
py311/lib/python3.11/site-packages/pandas/tests/frame/methods/test_iterrows.py ADDED
@@ -0,0 +1,16 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from pandas import (
2
+ DataFrame,
3
+ Timedelta,
4
+ )
5
+
6
+
7
+ def test_no_overflow_of_freq_and_time_in_dataframe():
8
+ # GH 35665
9
+ df = DataFrame(
10
+ {
11
+ "some_string": ["2222Y3"],
12
+ "time": [Timedelta("0 days 00:00:00.990000")],
13
+ }
14
+ )
15
+ for _, row in df.iterrows():
16
+ assert row.dtype == "object"
py311/lib/python3.11/site-packages/pandas/tests/frame/methods/test_join.py ADDED
@@ -0,0 +1,576 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from datetime import datetime
2
+
3
+ import numpy as np
4
+ import pytest
5
+
6
+ from pandas.errors import MergeError
7
+
8
+ import pandas as pd
9
+ from pandas import (
10
+ DataFrame,
11
+ Index,
12
+ MultiIndex,
13
+ date_range,
14
+ period_range,
15
+ )
16
+ import pandas._testing as tm
17
+ from pandas.core.reshape.concat import concat
18
+
19
+
20
+ @pytest.fixture
21
+ def frame_with_period_index():
22
+ return DataFrame(
23
+ data=np.arange(20).reshape(4, 5),
24
+ columns=list("abcde"),
25
+ index=period_range(start="2000", freq="Y", periods=4),
26
+ )
27
+
28
+
29
+ @pytest.fixture
30
+ def left():
31
+ return DataFrame({"a": [20, 10, 0]}, index=[2, 1, 0])
32
+
33
+
34
+ @pytest.fixture
35
+ def right():
36
+ return DataFrame({"b": [300, 100, 200]}, index=[3, 1, 2])
37
+
38
+
39
+ @pytest.fixture
40
+ def left_no_dup():
41
+ return DataFrame(
42
+ {"a": ["a", "b", "c", "d"], "b": ["cat", "dog", "weasel", "horse"]},
43
+ index=range(4),
44
+ )
45
+
46
+
47
+ @pytest.fixture
48
+ def right_no_dup():
49
+ return DataFrame(
50
+ {
51
+ "a": ["a", "b", "c", "d", "e"],
52
+ "c": ["meow", "bark", "um... weasel noise?", "nay", "chirp"],
53
+ },
54
+ index=range(5),
55
+ ).set_index("a")
56
+
57
+
58
+ @pytest.fixture
59
+ def left_w_dups(left_no_dup):
60
+ return concat(
61
+ [left_no_dup, DataFrame({"a": ["a"], "b": ["cow"]}, index=[3])], sort=True
62
+ )
63
+
64
+
65
+ @pytest.fixture
66
+ def right_w_dups(right_no_dup):
67
+ return concat(
68
+ [right_no_dup, DataFrame({"a": ["e"], "c": ["moo"]}, index=[3])]
69
+ ).set_index("a")
70
+
71
+
72
+ @pytest.mark.parametrize(
73
+ "how, sort, expected",
74
+ [
75
+ ("inner", False, DataFrame({"a": [20, 10], "b": [200, 100]}, index=[2, 1])),
76
+ ("inner", True, DataFrame({"a": [10, 20], "b": [100, 200]}, index=[1, 2])),
77
+ (
78
+ "left",
79
+ False,
80
+ DataFrame({"a": [20, 10, 0], "b": [200, 100, np.nan]}, index=[2, 1, 0]),
81
+ ),
82
+ (
83
+ "left",
84
+ True,
85
+ DataFrame({"a": [0, 10, 20], "b": [np.nan, 100, 200]}, index=[0, 1, 2]),
86
+ ),
87
+ (
88
+ "right",
89
+ False,
90
+ DataFrame({"a": [np.nan, 10, 20], "b": [300, 100, 200]}, index=[3, 1, 2]),
91
+ ),
92
+ (
93
+ "right",
94
+ True,
95
+ DataFrame({"a": [10, 20, np.nan], "b": [100, 200, 300]}, index=[1, 2, 3]),
96
+ ),
97
+ (
98
+ "outer",
99
+ False,
100
+ DataFrame(
101
+ {"a": [0, 10, 20, np.nan], "b": [np.nan, 100, 200, 300]},
102
+ index=[0, 1, 2, 3],
103
+ ),
104
+ ),
105
+ (
106
+ "outer",
107
+ True,
108
+ DataFrame(
109
+ {"a": [0, 10, 20, np.nan], "b": [np.nan, 100, 200, 300]},
110
+ index=[0, 1, 2, 3],
111
+ ),
112
+ ),
113
+ ],
114
+ )
115
+ def test_join(left, right, how, sort, expected):
116
+ result = left.join(right, how=how, sort=sort, validate="1:1")
117
+ tm.assert_frame_equal(result, expected)
118
+
119
+
120
+ def test_suffix_on_list_join():
121
+ first = DataFrame({"key": [1, 2, 3, 4, 5]})
122
+ second = DataFrame({"key": [1, 8, 3, 2, 5], "v1": [1, 2, 3, 4, 5]})
123
+ third = DataFrame({"keys": [5, 2, 3, 4, 1], "v2": [1, 2, 3, 4, 5]})
124
+
125
+ # check proper errors are raised
126
+ msg = "Suffixes not supported when joining multiple DataFrames"
127
+ with pytest.raises(ValueError, match=msg):
128
+ first.join([second], lsuffix="y")
129
+ with pytest.raises(ValueError, match=msg):
130
+ first.join([second, third], rsuffix="x")
131
+ with pytest.raises(ValueError, match=msg):
132
+ first.join([second, third], lsuffix="y", rsuffix="x")
133
+ with pytest.raises(ValueError, match="Indexes have overlapping values"):
134
+ first.join([second, third])
135
+
136
+ # no errors should be raised
137
+ arr_joined = first.join([third])
138
+ norm_joined = first.join(third)
139
+ tm.assert_frame_equal(arr_joined, norm_joined)
140
+
141
+
142
+ def test_join_invalid_validate(left_no_dup, right_no_dup):
143
+ # GH 46622
144
+ # Check invalid arguments
145
+ msg = (
146
+ '"invalid" is not a valid argument. '
147
+ "Valid arguments are:\n"
148
+ '- "1:1"\n'
149
+ '- "1:m"\n'
150
+ '- "m:1"\n'
151
+ '- "m:m"\n'
152
+ '- "one_to_one"\n'
153
+ '- "one_to_many"\n'
154
+ '- "many_to_one"\n'
155
+ '- "many_to_many"'
156
+ )
157
+ with pytest.raises(ValueError, match=msg):
158
+ left_no_dup.merge(right_no_dup, on="a", validate="invalid")
159
+
160
+
161
+ @pytest.mark.parametrize("dtype", ["object", "string[pyarrow]"])
162
+ def test_join_on_single_col_dup_on_right(left_no_dup, right_w_dups, dtype):
163
+ # GH 46622
164
+ # Dups on right allowed by one_to_many constraint
165
+ if dtype == "string[pyarrow]":
166
+ pytest.importorskip("pyarrow")
167
+ left_no_dup = left_no_dup.astype(dtype)
168
+ right_w_dups.index = right_w_dups.index.astype(dtype)
169
+ left_no_dup.join(
170
+ right_w_dups,
171
+ on="a",
172
+ validate="one_to_many",
173
+ )
174
+
175
+ # Dups on right not allowed by one_to_one constraint
176
+ msg = "Merge keys are not unique in right dataset; not a one-to-one merge"
177
+ with pytest.raises(MergeError, match=msg):
178
+ left_no_dup.join(
179
+ right_w_dups,
180
+ on="a",
181
+ validate="one_to_one",
182
+ )
183
+
184
+
185
+ def test_join_on_single_col_dup_on_left(left_w_dups, right_no_dup):
186
+ # GH 46622
187
+ # Dups on left allowed by many_to_one constraint
188
+ left_w_dups.join(
189
+ right_no_dup,
190
+ on="a",
191
+ validate="many_to_one",
192
+ )
193
+
194
+ # Dups on left not allowed by one_to_one constraint
195
+ msg = "Merge keys are not unique in left dataset; not a one-to-one merge"
196
+ with pytest.raises(MergeError, match=msg):
197
+ left_w_dups.join(
198
+ right_no_dup,
199
+ on="a",
200
+ validate="one_to_one",
201
+ )
202
+
203
+
204
+ def test_join_on_single_col_dup_on_both(left_w_dups, right_w_dups):
205
+ # GH 46622
206
+ # Dups on both allowed by many_to_many constraint
207
+ left_w_dups.join(right_w_dups, on="a", validate="many_to_many")
208
+
209
+ # Dups on both not allowed by many_to_one constraint
210
+ msg = "Merge keys are not unique in right dataset; not a many-to-one merge"
211
+ with pytest.raises(MergeError, match=msg):
212
+ left_w_dups.join(
213
+ right_w_dups,
214
+ on="a",
215
+ validate="many_to_one",
216
+ )
217
+
218
+ # Dups on both not allowed by one_to_many constraint
219
+ msg = "Merge keys are not unique in left dataset; not a one-to-many merge"
220
+ with pytest.raises(MergeError, match=msg):
221
+ left_w_dups.join(
222
+ right_w_dups,
223
+ on="a",
224
+ validate="one_to_many",
225
+ )
226
+
227
+
228
+ def test_join_on_multi_col_check_dup():
229
+ # GH 46622
230
+ # Two column join, dups in both, but jointly no dups
231
+ left = DataFrame(
232
+ {
233
+ "a": ["a", "a", "b", "b"],
234
+ "b": [0, 1, 0, 1],
235
+ "c": ["cat", "dog", "weasel", "horse"],
236
+ },
237
+ index=range(4),
238
+ ).set_index(["a", "b"])
239
+
240
+ right = DataFrame(
241
+ {
242
+ "a": ["a", "a", "b"],
243
+ "b": [0, 1, 0],
244
+ "d": ["meow", "bark", "um... weasel noise?"],
245
+ },
246
+ index=range(3),
247
+ ).set_index(["a", "b"])
248
+
249
+ expected_multi = DataFrame(
250
+ {
251
+ "a": ["a", "a", "b"],
252
+ "b": [0, 1, 0],
253
+ "c": ["cat", "dog", "weasel"],
254
+ "d": ["meow", "bark", "um... weasel noise?"],
255
+ },
256
+ index=range(3),
257
+ ).set_index(["a", "b"])
258
+
259
+ # Jointly no dups allowed by one_to_one constraint
260
+ result = left.join(right, how="inner", validate="1:1")
261
+ tm.assert_frame_equal(result, expected_multi)
262
+
263
+
264
+ def test_join_index(float_frame):
265
+ # left / right
266
+
267
+ f = float_frame.loc[float_frame.index[:10], ["A", "B"]]
268
+ f2 = float_frame.loc[float_frame.index[5:], ["C", "D"]].iloc[::-1]
269
+
270
+ joined = f.join(f2)
271
+ tm.assert_index_equal(f.index, joined.index)
272
+ expected_columns = Index(["A", "B", "C", "D"])
273
+ tm.assert_index_equal(joined.columns, expected_columns)
274
+
275
+ joined = f.join(f2, how="left")
276
+ tm.assert_index_equal(joined.index, f.index)
277
+ tm.assert_index_equal(joined.columns, expected_columns)
278
+
279
+ joined = f.join(f2, how="right")
280
+ tm.assert_index_equal(joined.index, f2.index)
281
+ tm.assert_index_equal(joined.columns, expected_columns)
282
+
283
+ # inner
284
+
285
+ joined = f.join(f2, how="inner")
286
+ tm.assert_index_equal(joined.index, f.index[5:10])
287
+ tm.assert_index_equal(joined.columns, expected_columns)
288
+
289
+ # outer
290
+
291
+ joined = f.join(f2, how="outer")
292
+ tm.assert_index_equal(joined.index, float_frame.index.sort_values())
293
+ tm.assert_index_equal(joined.columns, expected_columns)
294
+
295
+ with pytest.raises(ValueError, match="join method"):
296
+ f.join(f2, how="foo")
297
+
298
+ # corner case - overlapping columns
299
+ msg = "columns overlap but no suffix"
300
+ for how in ("outer", "left", "inner"):
301
+ with pytest.raises(ValueError, match=msg):
302
+ float_frame.join(float_frame, how=how)
303
+
304
+
305
+ def test_join_index_more(float_frame):
306
+ af = float_frame.loc[:, ["A", "B"]]
307
+ bf = float_frame.loc[::2, ["C", "D"]]
308
+
309
+ expected = af.copy()
310
+ expected["C"] = float_frame["C"][::2]
311
+ expected["D"] = float_frame["D"][::2]
312
+
313
+ result = af.join(bf)
314
+ tm.assert_frame_equal(result, expected)
315
+
316
+ result = af.join(bf, how="right")
317
+ tm.assert_frame_equal(result, expected[::2])
318
+
319
+ result = bf.join(af, how="right")
320
+ tm.assert_frame_equal(result, expected.loc[:, result.columns])
321
+
322
+
323
+ def test_join_index_series(float_frame):
324
+ df = float_frame.copy()
325
+ ser = df.pop(float_frame.columns[-1])
326
+ joined = df.join(ser)
327
+
328
+ tm.assert_frame_equal(joined, float_frame)
329
+
330
+ ser.name = None
331
+ with pytest.raises(ValueError, match="must have a name"):
332
+ df.join(ser)
333
+
334
+
335
+ def test_join_overlap(float_frame):
336
+ df1 = float_frame.loc[:, ["A", "B", "C"]]
337
+ df2 = float_frame.loc[:, ["B", "C", "D"]]
338
+
339
+ joined = df1.join(df2, lsuffix="_df1", rsuffix="_df2")
340
+ df1_suf = df1.loc[:, ["B", "C"]].add_suffix("_df1")
341
+ df2_suf = df2.loc[:, ["B", "C"]].add_suffix("_df2")
342
+
343
+ no_overlap = float_frame.loc[:, ["A", "D"]]
344
+ expected = df1_suf.join(df2_suf).join(no_overlap)
345
+
346
+ # column order not necessarily sorted
347
+ tm.assert_frame_equal(joined, expected.loc[:, joined.columns])
348
+
349
+
350
+ def test_join_period_index(frame_with_period_index):
351
+ other = frame_with_period_index.rename(columns=lambda key: f"{key}{key}")
352
+
353
+ joined_values = np.concatenate([frame_with_period_index.values] * 2, axis=1)
354
+
355
+ joined_cols = frame_with_period_index.columns.append(other.columns)
356
+
357
+ joined = frame_with_period_index.join(other)
358
+ expected = DataFrame(
359
+ data=joined_values, columns=joined_cols, index=frame_with_period_index.index
360
+ )
361
+
362
+ tm.assert_frame_equal(joined, expected)
363
+
364
+
365
+ def test_join_left_sequence_non_unique_index():
366
+ # https://github.com/pandas-dev/pandas/issues/19607
367
+ df1 = DataFrame({"a": [0, 10, 20]}, index=[1, 2, 3])
368
+ df2 = DataFrame({"b": [100, 200, 300]}, index=[4, 3, 2])
369
+ df3 = DataFrame({"c": [400, 500, 600]}, index=[2, 2, 4])
370
+
371
+ joined = df1.join([df2, df3], how="left")
372
+
373
+ expected = DataFrame(
374
+ {
375
+ "a": [0, 10, 10, 20],
376
+ "b": [np.nan, 300, 300, 200],
377
+ "c": [np.nan, 400, 500, np.nan],
378
+ },
379
+ index=[1, 2, 2, 3],
380
+ )
381
+
382
+ tm.assert_frame_equal(joined, expected)
383
+
384
+
385
+ def test_join_list_series(float_frame):
386
+ # GH#46850
387
+ # Join a DataFrame with a list containing both a Series and a DataFrame
388
+ left = float_frame.A.to_frame()
389
+ right = [float_frame.B, float_frame[["C", "D"]]]
390
+ result = left.join(right)
391
+ tm.assert_frame_equal(result, float_frame)
392
+
393
+
394
+ @pytest.mark.parametrize("sort_kw", [True, False])
395
+ def test_suppress_future_warning_with_sort_kw(sort_kw):
396
+ a = DataFrame({"col1": [1, 2]}, index=["c", "a"])
397
+
398
+ b = DataFrame({"col2": [4, 5]}, index=["b", "a"])
399
+
400
+ c = DataFrame({"col3": [7, 8]}, index=["a", "b"])
401
+
402
+ expected = DataFrame(
403
+ {
404
+ "col1": {"a": 2.0, "b": float("nan"), "c": 1.0},
405
+ "col2": {"a": 5.0, "b": 4.0, "c": float("nan")},
406
+ "col3": {"a": 7.0, "b": 8.0, "c": float("nan")},
407
+ }
408
+ )
409
+ if sort_kw is False:
410
+ expected = expected.reindex(index=["c", "a", "b"])
411
+
412
+ with tm.assert_produces_warning(None):
413
+ result = a.join([b, c], how="outer", sort=sort_kw)
414
+ tm.assert_frame_equal(result, expected)
415
+
416
+
417
+ class TestDataFrameJoin:
418
+ def test_join(self, multiindex_dataframe_random_data):
419
+ frame = multiindex_dataframe_random_data
420
+
421
+ a = frame.loc[frame.index[:5], ["A"]]
422
+ b = frame.loc[frame.index[2:], ["B", "C"]]
423
+
424
+ joined = a.join(b, how="outer").reindex(frame.index)
425
+ expected = frame.copy().values.copy()
426
+ expected[np.isnan(joined.values)] = np.nan
427
+ expected = DataFrame(expected, index=frame.index, columns=frame.columns)
428
+
429
+ assert not np.isnan(joined.values).all()
430
+
431
+ tm.assert_frame_equal(joined, expected)
432
+
433
+ def test_join_segfault(self):
434
+ # GH#1532
435
+ df1 = DataFrame({"a": [1, 1], "b": [1, 2], "x": [1, 2]})
436
+ df2 = DataFrame({"a": [2, 2], "b": [1, 2], "y": [1, 2]})
437
+ df1 = df1.set_index(["a", "b"])
438
+ df2 = df2.set_index(["a", "b"])
439
+ # it works!
440
+ for how in ["left", "right", "outer"]:
441
+ df1.join(df2, how=how)
442
+
443
+ def test_join_str_datetime(self):
444
+ str_dates = ["20120209", "20120222"]
445
+ dt_dates = [datetime(2012, 2, 9), datetime(2012, 2, 22)]
446
+
447
+ A = DataFrame(str_dates, index=range(2), columns=["aa"])
448
+ C = DataFrame([[1, 2], [3, 4]], index=str_dates, columns=dt_dates)
449
+
450
+ tst = A.join(C, on="aa")
451
+
452
+ assert len(tst.columns) == 3
453
+
454
+ def test_join_multiindex_leftright(self):
455
+ # GH 10741
456
+ df1 = DataFrame(
457
+ [
458
+ ["a", "x", 0.471780],
459
+ ["a", "y", 0.774908],
460
+ ["a", "z", 0.563634],
461
+ ["b", "x", -0.353756],
462
+ ["b", "y", 0.368062],
463
+ ["b", "z", -1.721840],
464
+ ["c", "x", 1],
465
+ ["c", "y", 2],
466
+ ["c", "z", 3],
467
+ ],
468
+ columns=["first", "second", "value1"],
469
+ ).set_index(["first", "second"])
470
+
471
+ df2 = DataFrame([["a", 10], ["b", 20]], columns=["first", "value2"]).set_index(
472
+ ["first"]
473
+ )
474
+
475
+ exp = DataFrame(
476
+ [
477
+ [0.471780, 10],
478
+ [0.774908, 10],
479
+ [0.563634, 10],
480
+ [-0.353756, 20],
481
+ [0.368062, 20],
482
+ [-1.721840, 20],
483
+ [1.000000, np.nan],
484
+ [2.000000, np.nan],
485
+ [3.000000, np.nan],
486
+ ],
487
+ index=df1.index,
488
+ columns=["value1", "value2"],
489
+ )
490
+
491
+ # these must be the same results (but columns are flipped)
492
+ tm.assert_frame_equal(df1.join(df2, how="left"), exp)
493
+ tm.assert_frame_equal(df2.join(df1, how="right"), exp[["value2", "value1"]])
494
+
495
+ exp_idx = MultiIndex.from_product(
496
+ [["a", "b"], ["x", "y", "z"]], names=["first", "second"]
497
+ )
498
+ exp = DataFrame(
499
+ [
500
+ [0.471780, 10],
501
+ [0.774908, 10],
502
+ [0.563634, 10],
503
+ [-0.353756, 20],
504
+ [0.368062, 20],
505
+ [-1.721840, 20],
506
+ ],
507
+ index=exp_idx,
508
+ columns=["value1", "value2"],
509
+ )
510
+
511
+ tm.assert_frame_equal(df1.join(df2, how="right"), exp)
512
+ tm.assert_frame_equal(df2.join(df1, how="left"), exp[["value2", "value1"]])
513
+
514
+ def test_join_multiindex_dates(self):
515
+ # GH 33692
516
+ date = pd.Timestamp(2000, 1, 1).date()
517
+
518
+ df1_index = MultiIndex.from_tuples([(0, date)], names=["index_0", "date"])
519
+ df1 = DataFrame({"col1": [0]}, index=df1_index)
520
+ df2_index = MultiIndex.from_tuples([(0, date)], names=["index_0", "date"])
521
+ df2 = DataFrame({"col2": [0]}, index=df2_index)
522
+ df3_index = MultiIndex.from_tuples([(0, date)], names=["index_0", "date"])
523
+ df3 = DataFrame({"col3": [0]}, index=df3_index)
524
+
525
+ result = df1.join([df2, df3])
526
+
527
+ expected_index = MultiIndex.from_tuples([(0, date)], names=["index_0", "date"])
528
+ expected = DataFrame(
529
+ {"col1": [0], "col2": [0], "col3": [0]}, index=expected_index
530
+ )
531
+
532
+ tm.assert_equal(result, expected)
533
+
534
+ def test_merge_join_different_levels_raises(self):
535
+ # GH#9455
536
+ # GH 40993: For raising, enforced in 2.0
537
+
538
+ # first dataframe
539
+ df1 = DataFrame(columns=["a", "b"], data=[[1, 11], [0, 22]])
540
+
541
+ # second dataframe
542
+ columns = MultiIndex.from_tuples([("a", ""), ("c", "c1")])
543
+ df2 = DataFrame(columns=columns, data=[[1, 33], [0, 44]])
544
+
545
+ # merge
546
+ with pytest.raises(
547
+ MergeError, match="Not allowed to merge between different levels"
548
+ ):
549
+ pd.merge(df1, df2, on="a")
550
+
551
+ # join, see discussion in GH#12219
552
+ with pytest.raises(
553
+ MergeError, match="Not allowed to merge between different levels"
554
+ ):
555
+ df1.join(df2, on="a")
556
+
557
+ def test_frame_join_tzaware(self):
558
+ test1 = DataFrame(
559
+ np.zeros((6, 3)),
560
+ index=date_range(
561
+ "2012-11-15 00:00:00", periods=6, freq="100ms", tz="US/Central"
562
+ ),
563
+ )
564
+ test2 = DataFrame(
565
+ np.zeros((3, 3)),
566
+ index=date_range(
567
+ "2012-11-15 00:00:00", periods=3, freq="250ms", tz="US/Central"
568
+ ),
569
+ columns=range(3, 6),
570
+ )
571
+
572
+ result = test1.join(test2, how="outer")
573
+ expected = test1.index.union(test2.index)
574
+
575
+ tm.assert_index_equal(result.index, expected)
576
+ assert result.index.tz.zone == "US/Central"
py311/lib/python3.11/site-packages/pandas/tests/frame/methods/test_reindex.py ADDED
@@ -0,0 +1,1327 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from datetime import (
2
+ datetime,
3
+ timedelta,
4
+ )
5
+ import inspect
6
+
7
+ import numpy as np
8
+ import pytest
9
+
10
+ from pandas._libs.tslibs.timezones import dateutil_gettz as gettz
11
+ from pandas.compat import (
12
+ IS64,
13
+ is_platform_windows,
14
+ )
15
+ from pandas.compat.numpy import np_version_gt2
16
+ import pandas.util._test_decorators as td
17
+
18
+ import pandas as pd
19
+ from pandas import (
20
+ Categorical,
21
+ CategoricalIndex,
22
+ DataFrame,
23
+ Index,
24
+ MultiIndex,
25
+ Series,
26
+ date_range,
27
+ isna,
28
+ )
29
+ import pandas._testing as tm
30
+ from pandas.api.types import CategoricalDtype
31
+
32
+
33
+ class TestReindexSetIndex:
34
+ # Tests that check both reindex and set_index
35
+
36
+ def test_dti_set_index_reindex_datetimeindex(self):
37
+ # GH#6631
38
+ df = DataFrame(np.random.default_rng(2).random(6))
39
+ idx1 = date_range("2011/01/01", periods=6, freq="ME", tz="US/Eastern")
40
+ idx2 = date_range("2013", periods=6, freq="YE", tz="Asia/Tokyo")
41
+
42
+ df = df.set_index(idx1)
43
+ tm.assert_index_equal(df.index, idx1)
44
+ df = df.reindex(idx2)
45
+ tm.assert_index_equal(df.index, idx2)
46
+
47
+ def test_dti_set_index_reindex_freq_with_tz(self):
48
+ # GH#11314 with tz
49
+ index = date_range(
50
+ datetime(2015, 10, 1), datetime(2015, 10, 1, 23), freq="h", tz="US/Eastern"
51
+ )
52
+ df = DataFrame(
53
+ np.random.default_rng(2).standard_normal((24, 1)),
54
+ columns=["a"],
55
+ index=index,
56
+ )
57
+ new_index = date_range(
58
+ datetime(2015, 10, 2), datetime(2015, 10, 2, 23), freq="h", tz="US/Eastern"
59
+ )
60
+
61
+ result = df.set_index(new_index)
62
+ assert result.index.freq == index.freq
63
+
64
+ def test_set_reset_index_intervalindex(self):
65
+ df = DataFrame({"A": range(10)})
66
+ ser = pd.cut(df.A, 5)
67
+ df["B"] = ser
68
+ df = df.set_index("B")
69
+
70
+ df = df.reset_index()
71
+
72
+ def test_setitem_reset_index_dtypes(self):
73
+ # GH 22060
74
+ df = DataFrame(columns=["a", "b", "c"]).astype(
75
+ {"a": "datetime64[ns]", "b": np.int64, "c": np.float64}
76
+ )
77
+ df1 = df.set_index(["a"])
78
+ df1["d"] = []
79
+ result = df1.reset_index()
80
+ expected = DataFrame(columns=["a", "b", "c", "d"], index=range(0)).astype(
81
+ {"a": "datetime64[ns]", "b": np.int64, "c": np.float64, "d": np.float64}
82
+ )
83
+ tm.assert_frame_equal(result, expected)
84
+
85
+ df2 = df.set_index(["a", "b"])
86
+ df2["d"] = []
87
+ result = df2.reset_index()
88
+ tm.assert_frame_equal(result, expected)
89
+
90
+ @pytest.mark.parametrize(
91
+ "timezone, year, month, day, hour",
92
+ [["America/Chicago", 2013, 11, 3, 1], ["America/Santiago", 2021, 4, 3, 23]],
93
+ )
94
+ def test_reindex_timestamp_with_fold(self, timezone, year, month, day, hour):
95
+ # see gh-40817
96
+ test_timezone = gettz(timezone)
97
+ transition_1 = pd.Timestamp(
98
+ year=year,
99
+ month=month,
100
+ day=day,
101
+ hour=hour,
102
+ minute=0,
103
+ fold=0,
104
+ tzinfo=test_timezone,
105
+ )
106
+ transition_2 = pd.Timestamp(
107
+ year=year,
108
+ month=month,
109
+ day=day,
110
+ hour=hour,
111
+ minute=0,
112
+ fold=1,
113
+ tzinfo=test_timezone,
114
+ )
115
+ df = (
116
+ DataFrame({"index": [transition_1, transition_2], "vals": ["a", "b"]})
117
+ .set_index("index")
118
+ .reindex(["1", "2"])
119
+ )
120
+ exp = DataFrame({"index": ["1", "2"], "vals": [np.nan, np.nan]}).set_index(
121
+ "index"
122
+ )
123
+ exp = exp.astype(df.vals.dtype)
124
+ tm.assert_frame_equal(
125
+ df,
126
+ exp,
127
+ )
128
+
129
+
130
+ class TestDataFrameSelectReindex:
131
+ # These are specific reindex-based tests; other indexing tests should go in
132
+ # test_indexing
133
+
134
+ @pytest.mark.xfail(
135
+ not IS64 or (is_platform_windows() and not np_version_gt2),
136
+ reason="Passes int32 values to DatetimeArray in make_na_array on "
137
+ "windows, 32bit linux builds",
138
+ )
139
+ @td.skip_array_manager_not_yet_implemented
140
+ def test_reindex_tzaware_fill_value(self):
141
+ # GH#52586
142
+ df = DataFrame([[1]])
143
+
144
+ ts = pd.Timestamp("2023-04-10 17:32", tz="US/Pacific")
145
+ res = df.reindex([0, 1], axis=1, fill_value=ts)
146
+ assert res.dtypes[1] == pd.DatetimeTZDtype(unit="s", tz="US/Pacific")
147
+ expected = DataFrame({0: [1], 1: [ts]})
148
+ expected[1] = expected[1].astype(res.dtypes[1])
149
+ tm.assert_frame_equal(res, expected)
150
+
151
+ per = ts.tz_localize(None).to_period("s")
152
+ res = df.reindex([0, 1], axis=1, fill_value=per)
153
+ assert res.dtypes[1] == pd.PeriodDtype("s")
154
+ expected = DataFrame({0: [1], 1: [per]})
155
+ tm.assert_frame_equal(res, expected)
156
+
157
+ interval = pd.Interval(ts, ts + pd.Timedelta(seconds=1))
158
+ res = df.reindex([0, 1], axis=1, fill_value=interval)
159
+ assert res.dtypes[1] == pd.IntervalDtype("datetime64[s, US/Pacific]", "right")
160
+ expected = DataFrame({0: [1], 1: [interval]})
161
+ expected[1] = expected[1].astype(res.dtypes[1])
162
+ tm.assert_frame_equal(res, expected)
163
+
164
+ def test_reindex_copies(self):
165
+ # based on asv time_reindex_axis1
166
+ N = 10
167
+ df = DataFrame(np.random.default_rng(2).standard_normal((N * 10, N)))
168
+ cols = np.arange(N)
169
+ np.random.default_rng(2).shuffle(cols)
170
+
171
+ result = df.reindex(columns=cols, copy=True)
172
+ assert not np.shares_memory(result[0]._values, df[0]._values)
173
+
174
+ # pass both columns and index
175
+ result2 = df.reindex(columns=cols, index=df.index, copy=True)
176
+ assert not np.shares_memory(result2[0]._values, df[0]._values)
177
+
178
+ def test_reindex_copies_ea(self, using_copy_on_write):
179
+ # https://github.com/pandas-dev/pandas/pull/51197
180
+ # also ensure to honor copy keyword for ExtensionDtypes
181
+ N = 10
182
+ df = DataFrame(
183
+ np.random.default_rng(2).standard_normal((N * 10, N)), dtype="Float64"
184
+ )
185
+ cols = np.arange(N)
186
+ np.random.default_rng(2).shuffle(cols)
187
+
188
+ result = df.reindex(columns=cols, copy=True)
189
+ if using_copy_on_write:
190
+ assert np.shares_memory(result[0].array._data, df[0].array._data)
191
+ else:
192
+ assert not np.shares_memory(result[0].array._data, df[0].array._data)
193
+
194
+ # pass both columns and index
195
+ result2 = df.reindex(columns=cols, index=df.index, copy=True)
196
+ if using_copy_on_write:
197
+ assert np.shares_memory(result2[0].array._data, df[0].array._data)
198
+ else:
199
+ assert not np.shares_memory(result2[0].array._data, df[0].array._data)
200
+
201
+ @td.skip_array_manager_not_yet_implemented
202
+ def test_reindex_date_fill_value(self):
203
+ # passing date to dt64 is deprecated; enforced in 2.0 to cast to object
204
+ arr = date_range("2016-01-01", periods=6).values.reshape(3, 2)
205
+ df = DataFrame(arr, columns=["A", "B"], index=range(3))
206
+
207
+ ts = df.iloc[0, 0]
208
+ fv = ts.date()
209
+
210
+ res = df.reindex(index=range(4), columns=["A", "B", "C"], fill_value=fv)
211
+
212
+ expected = DataFrame(
213
+ {"A": df["A"].tolist() + [fv], "B": df["B"].tolist() + [fv], "C": [fv] * 4},
214
+ dtype=object,
215
+ )
216
+ tm.assert_frame_equal(res, expected)
217
+
218
+ # only reindexing rows
219
+ res = df.reindex(index=range(4), fill_value=fv)
220
+ tm.assert_frame_equal(res, expected[["A", "B"]])
221
+
222
+ # same with a datetime-castable str
223
+ res = df.reindex(
224
+ index=range(4), columns=["A", "B", "C"], fill_value="2016-01-01"
225
+ )
226
+ expected = DataFrame(
227
+ {"A": df["A"].tolist() + [ts], "B": df["B"].tolist() + [ts], "C": [ts] * 4},
228
+ )
229
+ tm.assert_frame_equal(res, expected)
230
+
231
+ def test_reindex_with_multi_index(self):
232
+ # https://github.com/pandas-dev/pandas/issues/29896
233
+ # tests for reindexing a multi-indexed DataFrame with a new MultiIndex
234
+ #
235
+ # confirms that we can reindex a multi-indexed DataFrame with a new
236
+ # MultiIndex object correctly when using no filling, backfilling, and
237
+ # padding
238
+ #
239
+ # The DataFrame, `df`, used in this test is:
240
+ # c
241
+ # a b
242
+ # -1 0 A
243
+ # 1 B
244
+ # 2 C
245
+ # 3 D
246
+ # 4 E
247
+ # 5 F
248
+ # 6 G
249
+ # 0 0 A
250
+ # 1 B
251
+ # 2 C
252
+ # 3 D
253
+ # 4 E
254
+ # 5 F
255
+ # 6 G
256
+ # 1 0 A
257
+ # 1 B
258
+ # 2 C
259
+ # 3 D
260
+ # 4 E
261
+ # 5 F
262
+ # 6 G
263
+ #
264
+ # and the other MultiIndex, `new_multi_index`, is:
265
+ # 0: 0 0.5
266
+ # 1: 2.0
267
+ # 2: 5.0
268
+ # 3: 5.8
269
+ df = DataFrame(
270
+ {
271
+ "a": [-1] * 7 + [0] * 7 + [1] * 7,
272
+ "b": list(range(7)) * 3,
273
+ "c": ["A", "B", "C", "D", "E", "F", "G"] * 3,
274
+ }
275
+ ).set_index(["a", "b"])
276
+ new_index = [0.5, 2.0, 5.0, 5.8]
277
+ new_multi_index = MultiIndex.from_product([[0], new_index], names=["a", "b"])
278
+
279
+ # reindexing w/o a `method` value
280
+ reindexed = df.reindex(new_multi_index)
281
+ expected = DataFrame(
282
+ {"a": [0] * 4, "b": new_index, "c": [np.nan, "C", "F", np.nan]}
283
+ ).set_index(["a", "b"])
284
+ tm.assert_frame_equal(expected, reindexed)
285
+
286
+ # reindexing with backfilling
287
+ expected = DataFrame(
288
+ {"a": [0] * 4, "b": new_index, "c": ["B", "C", "F", "G"]}
289
+ ).set_index(["a", "b"])
290
+ reindexed_with_backfilling = df.reindex(new_multi_index, method="bfill")
291
+ tm.assert_frame_equal(expected, reindexed_with_backfilling)
292
+
293
+ reindexed_with_backfilling = df.reindex(new_multi_index, method="backfill")
294
+ tm.assert_frame_equal(expected, reindexed_with_backfilling)
295
+
296
+ # reindexing with padding
297
+ expected = DataFrame(
298
+ {"a": [0] * 4, "b": new_index, "c": ["A", "C", "F", "F"]}
299
+ ).set_index(["a", "b"])
300
+ reindexed_with_padding = df.reindex(new_multi_index, method="pad")
301
+ tm.assert_frame_equal(expected, reindexed_with_padding)
302
+
303
+ reindexed_with_padding = df.reindex(new_multi_index, method="ffill")
304
+ tm.assert_frame_equal(expected, reindexed_with_padding)
305
+
306
+ @pytest.mark.parametrize(
307
+ "method,expected_values",
308
+ [
309
+ ("nearest", [0, 1, 1, 2]),
310
+ ("pad", [np.nan, 0, 1, 1]),
311
+ ("backfill", [0, 1, 2, 2]),
312
+ ],
313
+ )
314
+ def test_reindex_methods(self, method, expected_values):
315
+ df = DataFrame({"x": list(range(5))})
316
+ target = np.array([-0.1, 0.9, 1.1, 1.5])
317
+
318
+ expected = DataFrame({"x": expected_values}, index=target)
319
+ actual = df.reindex(target, method=method)
320
+ tm.assert_frame_equal(expected, actual)
321
+
322
+ actual = df.reindex(target, method=method, tolerance=1)
323
+ tm.assert_frame_equal(expected, actual)
324
+ actual = df.reindex(target, method=method, tolerance=[1, 1, 1, 1])
325
+ tm.assert_frame_equal(expected, actual)
326
+
327
+ e2 = expected[::-1]
328
+ actual = df.reindex(target[::-1], method=method)
329
+ tm.assert_frame_equal(e2, actual)
330
+
331
+ new_order = [3, 0, 2, 1]
332
+ e2 = expected.iloc[new_order]
333
+ actual = df.reindex(target[new_order], method=method)
334
+ tm.assert_frame_equal(e2, actual)
335
+
336
+ switched_method = (
337
+ "pad" if method == "backfill" else "backfill" if method == "pad" else method
338
+ )
339
+ actual = df[::-1].reindex(target, method=switched_method)
340
+ tm.assert_frame_equal(expected, actual)
341
+
342
+ def test_reindex_methods_nearest_special(self):
343
+ df = DataFrame({"x": list(range(5))})
344
+ target = np.array([-0.1, 0.9, 1.1, 1.5])
345
+
346
+ expected = DataFrame({"x": [0, 1, 1, np.nan]}, index=target)
347
+ actual = df.reindex(target, method="nearest", tolerance=0.2)
348
+ tm.assert_frame_equal(expected, actual)
349
+
350
+ expected = DataFrame({"x": [0, np.nan, 1, np.nan]}, index=target)
351
+ actual = df.reindex(target, method="nearest", tolerance=[0.5, 0.01, 0.4, 0.1])
352
+ tm.assert_frame_equal(expected, actual)
353
+
354
+ def test_reindex_nearest_tz(self, tz_aware_fixture):
355
+ # GH26683
356
+ tz = tz_aware_fixture
357
+ idx = date_range("2019-01-01", periods=5, tz=tz)
358
+ df = DataFrame({"x": list(range(5))}, index=idx)
359
+
360
+ expected = df.head(3)
361
+ actual = df.reindex(idx[:3], method="nearest")
362
+ tm.assert_frame_equal(expected, actual)
363
+
364
+ def test_reindex_nearest_tz_empty_frame(self):
365
+ # https://github.com/pandas-dev/pandas/issues/31964
366
+ dti = pd.DatetimeIndex(["2016-06-26 14:27:26+00:00"])
367
+ df = DataFrame(index=pd.DatetimeIndex(["2016-07-04 14:00:59+00:00"]))
368
+ expected = DataFrame(index=dti)
369
+ result = df.reindex(dti, method="nearest")
370
+ tm.assert_frame_equal(result, expected)
371
+
372
+ def test_reindex_frame_add_nat(self):
373
+ rng = date_range("1/1/2000 00:00:00", periods=10, freq="10s")
374
+ df = DataFrame(
375
+ {"A": np.random.default_rng(2).standard_normal(len(rng)), "B": rng}
376
+ )
377
+
378
+ result = df.reindex(range(15))
379
+ assert np.issubdtype(result["B"].dtype, np.dtype("M8[ns]"))
380
+
381
+ mask = isna(result)["B"]
382
+ assert mask[-5:].all()
383
+ assert not mask[:-5].any()
384
+
385
+ @pytest.mark.parametrize(
386
+ "method, exp_values",
387
+ [("ffill", [0, 1, 2, 3]), ("bfill", [1.0, 2.0, 3.0, np.nan])],
388
+ )
389
+ def test_reindex_frame_tz_ffill_bfill(self, frame_or_series, method, exp_values):
390
+ # GH#38566
391
+ obj = frame_or_series(
392
+ [0, 1, 2, 3],
393
+ index=date_range("2020-01-01 00:00:00", periods=4, freq="h", tz="UTC"),
394
+ )
395
+ new_index = date_range("2020-01-01 00:01:00", periods=4, freq="h", tz="UTC")
396
+ result = obj.reindex(new_index, method=method, tolerance=pd.Timedelta("1 hour"))
397
+ expected = frame_or_series(exp_values, index=new_index)
398
+ tm.assert_equal(result, expected)
399
+
400
+ def test_reindex_limit(self):
401
+ # GH 28631
402
+ data = [["A", "A", "A"], ["B", "B", "B"], ["C", "C", "C"], ["D", "D", "D"]]
403
+ exp_data = [
404
+ ["A", "A", "A"],
405
+ ["B", "B", "B"],
406
+ ["C", "C", "C"],
407
+ ["D", "D", "D"],
408
+ ["D", "D", "D"],
409
+ [np.nan, np.nan, np.nan],
410
+ ]
411
+ df = DataFrame(data)
412
+ result = df.reindex([0, 1, 2, 3, 4, 5], method="ffill", limit=1)
413
+ expected = DataFrame(exp_data)
414
+ tm.assert_frame_equal(result, expected)
415
+
416
+ @pytest.mark.parametrize(
417
+ "idx, check_index_type",
418
+ [
419
+ [["C", "B", "A"], True],
420
+ [["F", "C", "A", "D"], True],
421
+ [["A"], True],
422
+ [["A", "B", "C"], True],
423
+ [["C", "A", "B"], True],
424
+ [["C", "B"], True],
425
+ [["C", "A"], True],
426
+ [["A", "B"], True],
427
+ [["B", "A", "C"], True],
428
+ # reindex by these causes different MultiIndex levels
429
+ [["D", "F"], False],
430
+ [["A", "C", "B"], False],
431
+ ],
432
+ )
433
+ def test_reindex_level_verify_first_level(self, idx, check_index_type):
434
+ df = DataFrame(
435
+ {
436
+ "jim": list("B" * 4 + "A" * 2 + "C" * 3),
437
+ "joe": list("abcdeabcd")[::-1],
438
+ "jolie": [10, 20, 30] * 3,
439
+ "joline": np.random.default_rng(2).integers(0, 1000, 9),
440
+ }
441
+ )
442
+ icol = ["jim", "joe", "jolie"]
443
+
444
+ def f(val):
445
+ return np.nonzero((df["jim"] == val).to_numpy())[0]
446
+
447
+ i = np.concatenate(list(map(f, idx)))
448
+ left = df.set_index(icol).reindex(idx, level="jim")
449
+ right = df.iloc[i].set_index(icol)
450
+ tm.assert_frame_equal(left, right, check_index_type=check_index_type)
451
+
452
+ @pytest.mark.parametrize(
453
+ "idx",
454
+ [
455
+ ("mid",),
456
+ ("mid", "btm"),
457
+ ("mid", "btm", "top"),
458
+ ("mid",),
459
+ ("mid", "top"),
460
+ ("mid", "top", "btm"),
461
+ ("btm",),
462
+ ("btm", "mid"),
463
+ ("btm", "mid", "top"),
464
+ ("btm",),
465
+ ("btm", "top"),
466
+ ("btm", "top", "mid"),
467
+ ("top",),
468
+ ("top", "mid"),
469
+ ("top", "mid", "btm"),
470
+ ("top",),
471
+ ("top", "btm"),
472
+ ("top", "btm", "mid"),
473
+ ],
474
+ )
475
+ def test_reindex_level_verify_first_level_repeats(self, idx):
476
+ df = DataFrame(
477
+ {
478
+ "jim": ["mid"] * 5 + ["btm"] * 8 + ["top"] * 7,
479
+ "joe": ["3rd"] * 2
480
+ + ["1st"] * 3
481
+ + ["2nd"] * 3
482
+ + ["1st"] * 2
483
+ + ["3rd"] * 3
484
+ + ["1st"] * 2
485
+ + ["3rd"] * 3
486
+ + ["2nd"] * 2,
487
+ # this needs to be jointly unique with jim and joe or
488
+ # reindexing will fail ~1.5% of the time, this works
489
+ # out to needing unique groups of same size as joe
490
+ "jolie": np.concatenate(
491
+ [
492
+ np.random.default_rng(2).choice(1000, x, replace=False)
493
+ for x in [2, 3, 3, 2, 3, 2, 3, 2]
494
+ ]
495
+ ),
496
+ "joline": np.random.default_rng(2).standard_normal(20).round(3) * 10,
497
+ }
498
+ )
499
+ icol = ["jim", "joe", "jolie"]
500
+
501
+ def f(val):
502
+ return np.nonzero((df["jim"] == val).to_numpy())[0]
503
+
504
+ i = np.concatenate(list(map(f, idx)))
505
+ left = df.set_index(icol).reindex(idx, level="jim")
506
+ right = df.iloc[i].set_index(icol)
507
+ tm.assert_frame_equal(left, right)
508
+
509
+ @pytest.mark.parametrize(
510
+ "idx, indexer",
511
+ [
512
+ [
513
+ ["1st", "2nd", "3rd"],
514
+ [2, 3, 4, 0, 1, 8, 9, 5, 6, 7, 10, 11, 12, 13, 14, 18, 19, 15, 16, 17],
515
+ ],
516
+ [
517
+ ["3rd", "2nd", "1st"],
518
+ [0, 1, 2, 3, 4, 10, 11, 12, 5, 6, 7, 8, 9, 15, 16, 17, 18, 19, 13, 14],
519
+ ],
520
+ [["2nd", "3rd"], [0, 1, 5, 6, 7, 10, 11, 12, 18, 19, 15, 16, 17]],
521
+ [["3rd", "1st"], [0, 1, 2, 3, 4, 10, 11, 12, 8, 9, 15, 16, 17, 13, 14]],
522
+ ],
523
+ )
524
+ def test_reindex_level_verify_repeats(self, idx, indexer):
525
+ df = DataFrame(
526
+ {
527
+ "jim": ["mid"] * 5 + ["btm"] * 8 + ["top"] * 7,
528
+ "joe": ["3rd"] * 2
529
+ + ["1st"] * 3
530
+ + ["2nd"] * 3
531
+ + ["1st"] * 2
532
+ + ["3rd"] * 3
533
+ + ["1st"] * 2
534
+ + ["3rd"] * 3
535
+ + ["2nd"] * 2,
536
+ # this needs to be jointly unique with jim and joe or
537
+ # reindexing will fail ~1.5% of the time, this works
538
+ # out to needing unique groups of same size as joe
539
+ "jolie": np.concatenate(
540
+ [
541
+ np.random.default_rng(2).choice(1000, x, replace=False)
542
+ for x in [2, 3, 3, 2, 3, 2, 3, 2]
543
+ ]
544
+ ),
545
+ "joline": np.random.default_rng(2).standard_normal(20).round(3) * 10,
546
+ }
547
+ )
548
+ icol = ["jim", "joe", "jolie"]
549
+ left = df.set_index(icol).reindex(idx, level="joe")
550
+ right = df.iloc[indexer].set_index(icol)
551
+ tm.assert_frame_equal(left, right)
552
+
553
+ @pytest.mark.parametrize(
554
+ "idx, indexer, check_index_type",
555
+ [
556
+ [list("abcde"), [3, 2, 1, 0, 5, 4, 8, 7, 6], True],
557
+ [list("abcd"), [3, 2, 1, 0, 5, 8, 7, 6], True],
558
+ [list("abc"), [3, 2, 1, 8, 7, 6], True],
559
+ [list("eca"), [1, 3, 4, 6, 8], True],
560
+ [list("edc"), [0, 1, 4, 5, 6], True],
561
+ [list("eadbc"), [3, 0, 2, 1, 4, 5, 8, 7, 6], True],
562
+ [list("edwq"), [0, 4, 5], True],
563
+ [list("wq"), [], False],
564
+ ],
565
+ )
566
+ def test_reindex_level_verify(self, idx, indexer, check_index_type):
567
+ df = DataFrame(
568
+ {
569
+ "jim": list("B" * 4 + "A" * 2 + "C" * 3),
570
+ "joe": list("abcdeabcd")[::-1],
571
+ "jolie": [10, 20, 30] * 3,
572
+ "joline": np.random.default_rng(2).integers(0, 1000, 9),
573
+ }
574
+ )
575
+ icol = ["jim", "joe", "jolie"]
576
+ left = df.set_index(icol).reindex(idx, level="joe")
577
+ right = df.iloc[indexer].set_index(icol)
578
+ tm.assert_frame_equal(left, right, check_index_type=check_index_type)
579
+
580
+ def test_non_monotonic_reindex_methods(self):
581
+ dr = date_range("2013-08-01", periods=6, freq="B")
582
+ data = np.random.default_rng(2).standard_normal((6, 1))
583
+ df = DataFrame(data, index=dr, columns=list("A"))
584
+ df_rev = DataFrame(data, index=dr[[3, 4, 5] + [0, 1, 2]], columns=list("A"))
585
+ # index is not monotonic increasing or decreasing
586
+ msg = "index must be monotonic increasing or decreasing"
587
+ with pytest.raises(ValueError, match=msg):
588
+ df_rev.reindex(df.index, method="pad")
589
+ with pytest.raises(ValueError, match=msg):
590
+ df_rev.reindex(df.index, method="ffill")
591
+ with pytest.raises(ValueError, match=msg):
592
+ df_rev.reindex(df.index, method="bfill")
593
+ with pytest.raises(ValueError, match=msg):
594
+ df_rev.reindex(df.index, method="nearest")
595
+
596
+ def test_reindex_sparse(self):
597
+ # https://github.com/pandas-dev/pandas/issues/35286
598
+ df = DataFrame(
599
+ {"A": [0, 1], "B": pd.array([0, 1], dtype=pd.SparseDtype("int64", 0))}
600
+ )
601
+ result = df.reindex([0, 2])
602
+ expected = DataFrame(
603
+ {
604
+ "A": [0.0, np.nan],
605
+ "B": pd.array([0.0, np.nan], dtype=pd.SparseDtype("float64", 0.0)),
606
+ },
607
+ index=[0, 2],
608
+ )
609
+ tm.assert_frame_equal(result, expected)
610
+
611
+ def test_reindex(self, float_frame, using_copy_on_write):
612
+ datetime_series = Series(
613
+ np.arange(30, dtype=np.float64), index=date_range("2020-01-01", periods=30)
614
+ )
615
+
616
+ newFrame = float_frame.reindex(datetime_series.index)
617
+
618
+ for col in newFrame.columns:
619
+ for idx, val in newFrame[col].items():
620
+ if idx in float_frame.index:
621
+ if np.isnan(val):
622
+ assert np.isnan(float_frame[col][idx])
623
+ else:
624
+ assert val == float_frame[col][idx]
625
+ else:
626
+ assert np.isnan(val)
627
+
628
+ for col, series in newFrame.items():
629
+ tm.assert_index_equal(series.index, newFrame.index)
630
+ emptyFrame = float_frame.reindex(Index([]))
631
+ assert len(emptyFrame.index) == 0
632
+
633
+ # Cython code should be unit-tested directly
634
+ nonContigFrame = float_frame.reindex(datetime_series.index[::2])
635
+
636
+ for col in nonContigFrame.columns:
637
+ for idx, val in nonContigFrame[col].items():
638
+ if idx in float_frame.index:
639
+ if np.isnan(val):
640
+ assert np.isnan(float_frame[col][idx])
641
+ else:
642
+ assert val == float_frame[col][idx]
643
+ else:
644
+ assert np.isnan(val)
645
+
646
+ for col, series in nonContigFrame.items():
647
+ tm.assert_index_equal(series.index, nonContigFrame.index)
648
+
649
+ # corner cases
650
+
651
+ # Same index, copies values but not index if copy=False
652
+ newFrame = float_frame.reindex(float_frame.index, copy=False)
653
+ if using_copy_on_write:
654
+ assert newFrame.index.is_(float_frame.index)
655
+ else:
656
+ assert newFrame.index is float_frame.index
657
+
658
+ # length zero
659
+ newFrame = float_frame.reindex([])
660
+ assert newFrame.empty
661
+ assert len(newFrame.columns) == len(float_frame.columns)
662
+
663
+ # length zero with columns reindexed with non-empty index
664
+ newFrame = float_frame.reindex([])
665
+ newFrame = newFrame.reindex(float_frame.index)
666
+ assert len(newFrame.index) == len(float_frame.index)
667
+ assert len(newFrame.columns) == len(float_frame.columns)
668
+
669
+ # pass non-Index
670
+ newFrame = float_frame.reindex(list(datetime_series.index))
671
+ expected = datetime_series.index._with_freq(None)
672
+ tm.assert_index_equal(newFrame.index, expected)
673
+
674
+ # copy with no axes
675
+ result = float_frame.reindex()
676
+ tm.assert_frame_equal(result, float_frame)
677
+ assert result is not float_frame
678
+
679
+ def test_reindex_nan(self):
680
+ df = DataFrame(
681
+ [[1, 2], [3, 5], [7, 11], [9, 23]],
682
+ index=[2, np.nan, 1, 5],
683
+ columns=["joe", "jim"],
684
+ )
685
+
686
+ i, j = [np.nan, 5, 5, np.nan, 1, 2, np.nan], [1, 3, 3, 1, 2, 0, 1]
687
+ tm.assert_frame_equal(df.reindex(i), df.iloc[j])
688
+
689
+ df.index = df.index.astype("object")
690
+ tm.assert_frame_equal(df.reindex(i), df.iloc[j], check_index_type=False)
691
+
692
+ # GH10388
693
+ df = DataFrame(
694
+ {
695
+ "other": ["a", "b", np.nan, "c"],
696
+ "date": ["2015-03-22", np.nan, "2012-01-08", np.nan],
697
+ "amount": [2, 3, 4, 5],
698
+ }
699
+ )
700
+
701
+ df["date"] = pd.to_datetime(df.date)
702
+ df["delta"] = (pd.to_datetime("2015-06-18") - df["date"]).shift(1)
703
+
704
+ left = df.set_index(["delta", "other", "date"]).reset_index()
705
+ right = df.reindex(columns=["delta", "other", "date", "amount"])
706
+ tm.assert_frame_equal(left, right)
707
+
708
+ def test_reindex_name_remains(self):
709
+ s = Series(np.random.default_rng(2).random(10))
710
+ df = DataFrame(s, index=np.arange(len(s)))
711
+ i = Series(np.arange(10), name="iname")
712
+
713
+ df = df.reindex(i)
714
+ assert df.index.name == "iname"
715
+
716
+ df = df.reindex(Index(np.arange(10), name="tmpname"))
717
+ assert df.index.name == "tmpname"
718
+
719
+ s = Series(np.random.default_rng(2).random(10))
720
+ df = DataFrame(s.T, index=np.arange(len(s)))
721
+ i = Series(np.arange(10), name="iname")
722
+ df = df.reindex(columns=i)
723
+ assert df.columns.name == "iname"
724
+
725
+ def test_reindex_int(self, int_frame):
726
+ smaller = int_frame.reindex(int_frame.index[::2])
727
+
728
+ assert smaller["A"].dtype == np.int64
729
+
730
+ bigger = smaller.reindex(int_frame.index)
731
+ assert bigger["A"].dtype == np.float64
732
+
733
+ smaller = int_frame.reindex(columns=["A", "B"])
734
+ assert smaller["A"].dtype == np.int64
735
+
736
+ def test_reindex_columns(self, float_frame):
737
+ new_frame = float_frame.reindex(columns=["A", "B", "E"])
738
+
739
+ tm.assert_series_equal(new_frame["B"], float_frame["B"])
740
+ assert np.isnan(new_frame["E"]).all()
741
+ assert "C" not in new_frame
742
+
743
+ # Length zero
744
+ new_frame = float_frame.reindex(columns=[])
745
+ assert new_frame.empty
746
+
747
+ def test_reindex_columns_method(self):
748
+ # GH 14992, reindexing over columns ignored method
749
+ df = DataFrame(
750
+ data=[[11, 12, 13], [21, 22, 23], [31, 32, 33]],
751
+ index=[1, 2, 4],
752
+ columns=[1, 2, 4],
753
+ dtype=float,
754
+ )
755
+
756
+ # default method
757
+ result = df.reindex(columns=range(6))
758
+ expected = DataFrame(
759
+ data=[
760
+ [np.nan, 11, 12, np.nan, 13, np.nan],
761
+ [np.nan, 21, 22, np.nan, 23, np.nan],
762
+ [np.nan, 31, 32, np.nan, 33, np.nan],
763
+ ],
764
+ index=[1, 2, 4],
765
+ columns=range(6),
766
+ dtype=float,
767
+ )
768
+ tm.assert_frame_equal(result, expected)
769
+
770
+ # method='ffill'
771
+ result = df.reindex(columns=range(6), method="ffill")
772
+ expected = DataFrame(
773
+ data=[
774
+ [np.nan, 11, 12, 12, 13, 13],
775
+ [np.nan, 21, 22, 22, 23, 23],
776
+ [np.nan, 31, 32, 32, 33, 33],
777
+ ],
778
+ index=[1, 2, 4],
779
+ columns=range(6),
780
+ dtype=float,
781
+ )
782
+ tm.assert_frame_equal(result, expected)
783
+
784
+ # method='bfill'
785
+ result = df.reindex(columns=range(6), method="bfill")
786
+ expected = DataFrame(
787
+ data=[
788
+ [11, 11, 12, 13, 13, np.nan],
789
+ [21, 21, 22, 23, 23, np.nan],
790
+ [31, 31, 32, 33, 33, np.nan],
791
+ ],
792
+ index=[1, 2, 4],
793
+ columns=range(6),
794
+ dtype=float,
795
+ )
796
+ tm.assert_frame_equal(result, expected)
797
+
798
+ def test_reindex_axes(self):
799
+ # GH 3317, reindexing by both axes loses freq of the index
800
+ df = DataFrame(
801
+ np.ones((3, 3)),
802
+ index=[datetime(2012, 1, 1), datetime(2012, 1, 2), datetime(2012, 1, 3)],
803
+ columns=["a", "b", "c"],
804
+ )
805
+ time_freq = date_range("2012-01-01", "2012-01-03", freq="d")
806
+ some_cols = ["a", "b"]
807
+
808
+ index_freq = df.reindex(index=time_freq).index.freq
809
+ both_freq = df.reindex(index=time_freq, columns=some_cols).index.freq
810
+ seq_freq = df.reindex(index=time_freq).reindex(columns=some_cols).index.freq
811
+ assert index_freq == both_freq
812
+ assert index_freq == seq_freq
813
+
814
+ def test_reindex_fill_value(self):
815
+ df = DataFrame(np.random.default_rng(2).standard_normal((10, 4)))
816
+
817
+ # axis=0
818
+ result = df.reindex(list(range(15)))
819
+ assert np.isnan(result.values[-5:]).all()
820
+
821
+ result = df.reindex(range(15), fill_value=0)
822
+ expected = df.reindex(range(15)).fillna(0)
823
+ tm.assert_frame_equal(result, expected)
824
+
825
+ # axis=1
826
+ result = df.reindex(columns=range(5), fill_value=0.0)
827
+ expected = df.copy()
828
+ expected[4] = 0.0
829
+ tm.assert_frame_equal(result, expected)
830
+
831
+ result = df.reindex(columns=range(5), fill_value=0)
832
+ expected = df.copy()
833
+ expected[4] = 0
834
+ tm.assert_frame_equal(result, expected)
835
+
836
+ result = df.reindex(columns=range(5), fill_value="foo")
837
+ expected = df.copy()
838
+ expected[4] = "foo"
839
+ tm.assert_frame_equal(result, expected)
840
+
841
+ # other dtypes
842
+ df["foo"] = "foo"
843
+ result = df.reindex(range(15), fill_value="0")
844
+ expected = df.reindex(range(15)).fillna("0")
845
+ tm.assert_frame_equal(result, expected)
846
+
847
+ def test_reindex_uint_dtypes_fill_value(self, any_unsigned_int_numpy_dtype):
848
+ # GH#48184
849
+ df = DataFrame({"a": [1, 2], "b": [1, 2]}, dtype=any_unsigned_int_numpy_dtype)
850
+ result = df.reindex(columns=list("abcd"), index=[0, 1, 2, 3], fill_value=10)
851
+ expected = DataFrame(
852
+ {"a": [1, 2, 10, 10], "b": [1, 2, 10, 10], "c": 10, "d": 10},
853
+ dtype=any_unsigned_int_numpy_dtype,
854
+ )
855
+ tm.assert_frame_equal(result, expected)
856
+
857
+ def test_reindex_single_column_ea_index_and_columns(self, any_numeric_ea_dtype):
858
+ # GH#48190
859
+ df = DataFrame({"a": [1, 2]}, dtype=any_numeric_ea_dtype)
860
+ result = df.reindex(columns=list("ab"), index=[0, 1, 2], fill_value=10)
861
+ expected = DataFrame(
862
+ {"a": Series([1, 2, 10], dtype=any_numeric_ea_dtype), "b": 10}
863
+ )
864
+ tm.assert_frame_equal(result, expected)
865
+
866
+ def test_reindex_dups(self):
867
+ # GH4746, reindex on duplicate index error messages
868
+ arr = np.random.default_rng(2).standard_normal(10)
869
+ df = DataFrame(arr, index=[1, 2, 3, 4, 5, 1, 2, 3, 4, 5])
870
+
871
+ # set index is ok
872
+ result = df.copy()
873
+ result.index = list(range(len(df)))
874
+ expected = DataFrame(arr, index=list(range(len(df))))
875
+ tm.assert_frame_equal(result, expected)
876
+
877
+ # reindex fails
878
+ msg = "cannot reindex on an axis with duplicate labels"
879
+ with pytest.raises(ValueError, match=msg):
880
+ df.reindex(index=list(range(len(df))))
881
+
882
+ def test_reindex_with_duplicate_columns(self):
883
+ # reindex is invalid!
884
+ df = DataFrame(
885
+ [[1, 5, 7.0], [1, 5, 7.0], [1, 5, 7.0]], columns=["bar", "a", "a"]
886
+ )
887
+ msg = "cannot reindex on an axis with duplicate labels"
888
+ with pytest.raises(ValueError, match=msg):
889
+ df.reindex(columns=["bar"])
890
+ with pytest.raises(ValueError, match=msg):
891
+ df.reindex(columns=["bar", "foo"])
892
+
893
+ def test_reindex_axis_style(self):
894
+ # https://github.com/pandas-dev/pandas/issues/12392
895
+ df = DataFrame({"A": [1, 2, 3], "B": [4, 5, 6]})
896
+ expected = DataFrame(
897
+ {"A": [1, 2, np.nan], "B": [4, 5, np.nan]}, index=[0, 1, 3]
898
+ )
899
+ result = df.reindex([0, 1, 3])
900
+ tm.assert_frame_equal(result, expected)
901
+
902
+ result = df.reindex([0, 1, 3], axis=0)
903
+ tm.assert_frame_equal(result, expected)
904
+
905
+ result = df.reindex([0, 1, 3], axis="index")
906
+ tm.assert_frame_equal(result, expected)
907
+
908
+ def test_reindex_positional_raises(self):
909
+ # https://github.com/pandas-dev/pandas/issues/12392
910
+ # Enforced in 2.0
911
+ df = DataFrame({"A": [1, 2, 3], "B": [4, 5, 6]})
912
+ msg = r"reindex\(\) takes from 1 to 2 positional arguments but 3 were given"
913
+ with pytest.raises(TypeError, match=msg):
914
+ df.reindex([0, 1], ["A", "B", "C"])
915
+
916
+ def test_reindex_axis_style_raises(self):
917
+ # https://github.com/pandas-dev/pandas/issues/12392
918
+ df = DataFrame({"A": [1, 2, 3], "B": [4, 5, 6]})
919
+ with pytest.raises(TypeError, match="Cannot specify both 'axis'"):
920
+ df.reindex([0, 1], columns=["A"], axis=1)
921
+
922
+ with pytest.raises(TypeError, match="Cannot specify both 'axis'"):
923
+ df.reindex([0, 1], columns=["A"], axis="index")
924
+
925
+ with pytest.raises(TypeError, match="Cannot specify both 'axis'"):
926
+ df.reindex(index=[0, 1], axis="index")
927
+
928
+ with pytest.raises(TypeError, match="Cannot specify both 'axis'"):
929
+ df.reindex(index=[0, 1], axis="columns")
930
+
931
+ with pytest.raises(TypeError, match="Cannot specify both 'axis'"):
932
+ df.reindex(columns=[0, 1], axis="columns")
933
+
934
+ with pytest.raises(TypeError, match="Cannot specify both 'axis'"):
935
+ df.reindex(index=[0, 1], columns=[0, 1], axis="columns")
936
+
937
+ with pytest.raises(TypeError, match="Cannot specify all"):
938
+ df.reindex(labels=[0, 1], index=[0], columns=["A"])
939
+
940
+ # Mixing styles
941
+ with pytest.raises(TypeError, match="Cannot specify both 'axis'"):
942
+ df.reindex(index=[0, 1], axis="index")
943
+
944
+ with pytest.raises(TypeError, match="Cannot specify both 'axis'"):
945
+ df.reindex(index=[0, 1], axis="columns")
946
+
947
+ # Duplicates
948
+ with pytest.raises(TypeError, match="multiple values"):
949
+ df.reindex([0, 1], labels=[0, 1])
950
+
951
+ def test_reindex_single_named_indexer(self):
952
+ # https://github.com/pandas-dev/pandas/issues/12392
953
+ df = DataFrame({"A": [1, 2, 3], "B": [1, 2, 3]})
954
+ result = df.reindex([0, 1], columns=["A"])
955
+ expected = DataFrame({"A": [1, 2]})
956
+ tm.assert_frame_equal(result, expected)
957
+
958
+ def test_reindex_api_equivalence(self):
959
+ # https://github.com/pandas-dev/pandas/issues/12392
960
+ # equivalence of the labels/axis and index/columns API's
961
+ df = DataFrame(
962
+ [[1, 2, 3], [3, 4, 5], [5, 6, 7]],
963
+ index=["a", "b", "c"],
964
+ columns=["d", "e", "f"],
965
+ )
966
+
967
+ res1 = df.reindex(["b", "a"])
968
+ res2 = df.reindex(index=["b", "a"])
969
+ res3 = df.reindex(labels=["b", "a"])
970
+ res4 = df.reindex(labels=["b", "a"], axis=0)
971
+ res5 = df.reindex(["b", "a"], axis=0)
972
+ for res in [res2, res3, res4, res5]:
973
+ tm.assert_frame_equal(res1, res)
974
+
975
+ res1 = df.reindex(columns=["e", "d"])
976
+ res2 = df.reindex(["e", "d"], axis=1)
977
+ res3 = df.reindex(labels=["e", "d"], axis=1)
978
+ for res in [res2, res3]:
979
+ tm.assert_frame_equal(res1, res)
980
+
981
+ res1 = df.reindex(index=["b", "a"], columns=["e", "d"])
982
+ res2 = df.reindex(columns=["e", "d"], index=["b", "a"])
983
+ res3 = df.reindex(labels=["b", "a"], axis=0).reindex(labels=["e", "d"], axis=1)
984
+ for res in [res2, res3]:
985
+ tm.assert_frame_equal(res1, res)
986
+
987
+ def test_reindex_boolean(self):
988
+ frame = DataFrame(
989
+ np.ones((10, 2), dtype=bool), index=np.arange(0, 20, 2), columns=[0, 2]
990
+ )
991
+
992
+ reindexed = frame.reindex(np.arange(10))
993
+ assert reindexed.values.dtype == np.object_
994
+ assert isna(reindexed[0][1])
995
+
996
+ reindexed = frame.reindex(columns=range(3))
997
+ assert reindexed.values.dtype == np.object_
998
+ assert isna(reindexed[1]).all()
999
+
1000
+ def test_reindex_objects(self, float_string_frame):
1001
+ reindexed = float_string_frame.reindex(columns=["foo", "A", "B"])
1002
+ assert "foo" in reindexed
1003
+
1004
+ reindexed = float_string_frame.reindex(columns=["A", "B"])
1005
+ assert "foo" not in reindexed
1006
+
1007
+ def test_reindex_corner(self, int_frame):
1008
+ index = Index(["a", "b", "c"])
1009
+ dm = DataFrame({}).reindex(index=[1, 2, 3])
1010
+ reindexed = dm.reindex(columns=index)
1011
+ tm.assert_index_equal(reindexed.columns, index)
1012
+
1013
+ # ints are weird
1014
+ smaller = int_frame.reindex(columns=["A", "B", "E"])
1015
+ assert smaller["E"].dtype == np.float64
1016
+
1017
+ def test_reindex_with_nans(self):
1018
+ df = DataFrame(
1019
+ [[1, 2], [3, 4], [np.nan, np.nan], [7, 8], [9, 10]],
1020
+ columns=["a", "b"],
1021
+ index=[100.0, 101.0, np.nan, 102.0, 103.0],
1022
+ )
1023
+
1024
+ result = df.reindex(index=[101.0, 102.0, 103.0])
1025
+ expected = df.iloc[[1, 3, 4]]
1026
+ tm.assert_frame_equal(result, expected)
1027
+
1028
+ result = df.reindex(index=[103.0])
1029
+ expected = df.iloc[[4]]
1030
+ tm.assert_frame_equal(result, expected)
1031
+
1032
+ result = df.reindex(index=[101.0])
1033
+ expected = df.iloc[[1]]
1034
+ tm.assert_frame_equal(result, expected)
1035
+
1036
+ def test_reindex_multi(self):
1037
+ df = DataFrame(np.random.default_rng(2).standard_normal((3, 3)))
1038
+
1039
+ result = df.reindex(index=range(4), columns=range(4))
1040
+ expected = df.reindex(list(range(4))).reindex(columns=range(4))
1041
+
1042
+ tm.assert_frame_equal(result, expected)
1043
+
1044
+ df = DataFrame(np.random.default_rng(2).integers(0, 10, (3, 3)))
1045
+
1046
+ result = df.reindex(index=range(4), columns=range(4))
1047
+ expected = df.reindex(list(range(4))).reindex(columns=range(4))
1048
+
1049
+ tm.assert_frame_equal(result, expected)
1050
+
1051
+ df = DataFrame(np.random.default_rng(2).integers(0, 10, (3, 3)))
1052
+
1053
+ result = df.reindex(index=range(2), columns=range(2))
1054
+ expected = df.reindex(range(2)).reindex(columns=range(2))
1055
+
1056
+ tm.assert_frame_equal(result, expected)
1057
+
1058
+ df = DataFrame(
1059
+ np.random.default_rng(2).standard_normal((5, 3)) + 1j,
1060
+ columns=["a", "b", "c"],
1061
+ )
1062
+
1063
+ result = df.reindex(index=[0, 1], columns=["a", "b"])
1064
+ expected = df.reindex([0, 1]).reindex(columns=["a", "b"])
1065
+
1066
+ tm.assert_frame_equal(result, expected)
1067
+
1068
+ def test_reindex_multi_categorical_time(self):
1069
+ # https://github.com/pandas-dev/pandas/issues/21390
1070
+ midx = MultiIndex.from_product(
1071
+ [
1072
+ Categorical(["a", "b", "c"]),
1073
+ Categorical(date_range("2012-01-01", periods=3, freq="h")),
1074
+ ]
1075
+ )
1076
+ df = DataFrame({"a": range(len(midx))}, index=midx)
1077
+ df2 = df.iloc[[0, 1, 2, 3, 4, 5, 6, 8]]
1078
+
1079
+ result = df2.reindex(midx)
1080
+ expected = DataFrame({"a": [0, 1, 2, 3, 4, 5, 6, np.nan, 8]}, index=midx)
1081
+ tm.assert_frame_equal(result, expected)
1082
+
1083
+ def test_reindex_with_categoricalindex(self):
1084
+ df = DataFrame(
1085
+ {
1086
+ "A": np.arange(3, dtype="int64"),
1087
+ },
1088
+ index=CategoricalIndex(
1089
+ list("abc"), dtype=CategoricalDtype(list("cabe")), name="B"
1090
+ ),
1091
+ )
1092
+
1093
+ # reindexing
1094
+ # convert to a regular index
1095
+ result = df.reindex(["a", "b", "e"])
1096
+ expected = DataFrame({"A": [0, 1, np.nan], "B": Series(list("abe"))}).set_index(
1097
+ "B"
1098
+ )
1099
+ tm.assert_frame_equal(result, expected, check_index_type=True)
1100
+
1101
+ result = df.reindex(["a", "b"])
1102
+ expected = DataFrame({"A": [0, 1], "B": Series(list("ab"))}).set_index("B")
1103
+ tm.assert_frame_equal(result, expected, check_index_type=True)
1104
+
1105
+ result = df.reindex(["e"])
1106
+ expected = DataFrame({"A": [np.nan], "B": Series(["e"])}).set_index("B")
1107
+ tm.assert_frame_equal(result, expected, check_index_type=True)
1108
+
1109
+ result = df.reindex(["d"])
1110
+ expected = DataFrame({"A": [np.nan], "B": Series(["d"])}).set_index("B")
1111
+ tm.assert_frame_equal(result, expected, check_index_type=True)
1112
+
1113
+ # since we are actually reindexing with a Categorical
1114
+ # then return a Categorical
1115
+ cats = list("cabe")
1116
+
1117
+ result = df.reindex(Categorical(["a", "e"], categories=cats))
1118
+ expected = DataFrame(
1119
+ {"A": [0, np.nan], "B": Series(list("ae")).astype(CategoricalDtype(cats))}
1120
+ ).set_index("B")
1121
+ tm.assert_frame_equal(result, expected, check_index_type=True)
1122
+
1123
+ result = df.reindex(Categorical(["a"], categories=cats))
1124
+ expected = DataFrame(
1125
+ {"A": [0], "B": Series(list("a")).astype(CategoricalDtype(cats))}
1126
+ ).set_index("B")
1127
+ tm.assert_frame_equal(result, expected, check_index_type=True)
1128
+
1129
+ result = df.reindex(["a", "b", "e"])
1130
+ expected = DataFrame({"A": [0, 1, np.nan], "B": Series(list("abe"))}).set_index(
1131
+ "B"
1132
+ )
1133
+ tm.assert_frame_equal(result, expected, check_index_type=True)
1134
+
1135
+ result = df.reindex(["a", "b"])
1136
+ expected = DataFrame({"A": [0, 1], "B": Series(list("ab"))}).set_index("B")
1137
+ tm.assert_frame_equal(result, expected, check_index_type=True)
1138
+
1139
+ result = df.reindex(["e"])
1140
+ expected = DataFrame({"A": [np.nan], "B": Series(["e"])}).set_index("B")
1141
+ tm.assert_frame_equal(result, expected, check_index_type=True)
1142
+
1143
+ # give back the type of categorical that we received
1144
+ result = df.reindex(Categorical(["a", "e"], categories=cats, ordered=True))
1145
+ expected = DataFrame(
1146
+ {
1147
+ "A": [0, np.nan],
1148
+ "B": Series(list("ae")).astype(CategoricalDtype(cats, ordered=True)),
1149
+ }
1150
+ ).set_index("B")
1151
+ tm.assert_frame_equal(result, expected, check_index_type=True)
1152
+
1153
+ result = df.reindex(Categorical(["a", "d"], categories=["a", "d"]))
1154
+ expected = DataFrame(
1155
+ {
1156
+ "A": [0, np.nan],
1157
+ "B": Series(list("ad")).astype(CategoricalDtype(["a", "d"])),
1158
+ }
1159
+ ).set_index("B")
1160
+ tm.assert_frame_equal(result, expected, check_index_type=True)
1161
+
1162
+ df2 = DataFrame(
1163
+ {
1164
+ "A": np.arange(6, dtype="int64"),
1165
+ },
1166
+ index=CategoricalIndex(
1167
+ list("aabbca"), dtype=CategoricalDtype(list("cabe")), name="B"
1168
+ ),
1169
+ )
1170
+ # passed duplicate indexers are not allowed
1171
+ msg = "cannot reindex on an axis with duplicate labels"
1172
+ with pytest.raises(ValueError, match=msg):
1173
+ df2.reindex(["a", "b"])
1174
+
1175
+ # args NotImplemented ATM
1176
+ msg = r"argument {} is not implemented for CategoricalIndex\.reindex"
1177
+ with pytest.raises(NotImplementedError, match=msg.format("method")):
1178
+ df.reindex(["a"], method="ffill")
1179
+ with pytest.raises(NotImplementedError, match=msg.format("level")):
1180
+ df.reindex(["a"], level=1)
1181
+ with pytest.raises(NotImplementedError, match=msg.format("limit")):
1182
+ df.reindex(["a"], limit=2)
1183
+
1184
+ def test_reindex_signature(self):
1185
+ sig = inspect.signature(DataFrame.reindex)
1186
+ parameters = set(sig.parameters)
1187
+ assert parameters == {
1188
+ "self",
1189
+ "labels",
1190
+ "index",
1191
+ "columns",
1192
+ "axis",
1193
+ "limit",
1194
+ "copy",
1195
+ "level",
1196
+ "method",
1197
+ "fill_value",
1198
+ "tolerance",
1199
+ }
1200
+
1201
+ def test_reindex_multiindex_ffill_added_rows(self):
1202
+ # GH#23693
1203
+ # reindex added rows with nan values even when fill method was specified
1204
+ mi = MultiIndex.from_tuples([("a", "b"), ("d", "e")])
1205
+ df = DataFrame([[0, 7], [3, 4]], index=mi, columns=["x", "y"])
1206
+ mi2 = MultiIndex.from_tuples([("a", "b"), ("d", "e"), ("h", "i")])
1207
+ result = df.reindex(mi2, axis=0, method="ffill")
1208
+ expected = DataFrame([[0, 7], [3, 4], [3, 4]], index=mi2, columns=["x", "y"])
1209
+ tm.assert_frame_equal(result, expected)
1210
+
1211
+ @pytest.mark.parametrize(
1212
+ "kwargs",
1213
+ [
1214
+ {"method": "pad", "tolerance": timedelta(seconds=9)},
1215
+ {"method": "backfill", "tolerance": timedelta(seconds=9)},
1216
+ {"method": "nearest"},
1217
+ {"method": None},
1218
+ ],
1219
+ )
1220
+ def test_reindex_empty_frame(self, kwargs):
1221
+ # GH#27315
1222
+ idx = date_range(start="2020", freq="30s", periods=3)
1223
+ df = DataFrame([], index=Index([], name="time"), columns=["a"])
1224
+ result = df.reindex(idx, **kwargs)
1225
+ expected = DataFrame({"a": [np.nan] * 3}, index=idx, dtype=object)
1226
+ tm.assert_frame_equal(result, expected)
1227
+
1228
+ @pytest.mark.parametrize(
1229
+ "src_idx",
1230
+ [
1231
+ Index([]),
1232
+ CategoricalIndex([]),
1233
+ ],
1234
+ )
1235
+ @pytest.mark.parametrize(
1236
+ "cat_idx",
1237
+ [
1238
+ # No duplicates
1239
+ Index([]),
1240
+ CategoricalIndex([]),
1241
+ Index(["A", "B"]),
1242
+ CategoricalIndex(["A", "B"]),
1243
+ # Duplicates: GH#38906
1244
+ Index(["A", "A"]),
1245
+ CategoricalIndex(["A", "A"]),
1246
+ ],
1247
+ )
1248
+ def test_reindex_empty(self, src_idx, cat_idx):
1249
+ df = DataFrame(columns=src_idx, index=["K"], dtype="f8")
1250
+
1251
+ result = df.reindex(columns=cat_idx)
1252
+ expected = DataFrame(index=["K"], columns=cat_idx, dtype="f8")
1253
+ tm.assert_frame_equal(result, expected)
1254
+
1255
+ @pytest.mark.parametrize("dtype", ["m8[ns]", "M8[ns]"])
1256
+ def test_reindex_datetimelike_to_object(self, dtype):
1257
+ # GH#39755 dont cast dt64/td64 to ints
1258
+ mi = MultiIndex.from_product([list("ABCDE"), range(2)])
1259
+
1260
+ dti = date_range("2016-01-01", periods=10)
1261
+ fv = np.timedelta64("NaT", "ns")
1262
+ if dtype == "m8[ns]":
1263
+ dti = dti - dti[0]
1264
+ fv = np.datetime64("NaT", "ns")
1265
+
1266
+ ser = Series(dti, index=mi)
1267
+ ser[::3] = pd.NaT
1268
+
1269
+ df = ser.unstack()
1270
+
1271
+ index = df.index.append(Index([1]))
1272
+ columns = df.columns.append(Index(["foo"]))
1273
+
1274
+ res = df.reindex(index=index, columns=columns, fill_value=fv)
1275
+
1276
+ expected = DataFrame(
1277
+ {
1278
+ 0: df[0].tolist() + [fv],
1279
+ 1: df[1].tolist() + [fv],
1280
+ "foo": np.array(["NaT"] * 6, dtype=fv.dtype),
1281
+ },
1282
+ index=index,
1283
+ )
1284
+ assert (res.dtypes[[0, 1]] == object).all()
1285
+ assert res.iloc[0, 0] is pd.NaT
1286
+ assert res.iloc[-1, 0] is fv
1287
+ assert res.iloc[-1, 1] is fv
1288
+ tm.assert_frame_equal(res, expected)
1289
+
1290
+ @pytest.mark.parametrize(
1291
+ "index_df,index_res,index_exp",
1292
+ [
1293
+ (
1294
+ CategoricalIndex([], categories=["A"]),
1295
+ Index(["A"]),
1296
+ Index(["A"]),
1297
+ ),
1298
+ (
1299
+ CategoricalIndex([], categories=["A"]),
1300
+ Index(["B"]),
1301
+ Index(["B"]),
1302
+ ),
1303
+ (
1304
+ CategoricalIndex([], categories=["A"]),
1305
+ CategoricalIndex(["A"]),
1306
+ CategoricalIndex(["A"]),
1307
+ ),
1308
+ (
1309
+ CategoricalIndex([], categories=["A"]),
1310
+ CategoricalIndex(["B"]),
1311
+ CategoricalIndex(["B"]),
1312
+ ),
1313
+ ],
1314
+ )
1315
+ def test_reindex_not_category(self, index_df, index_res, index_exp):
1316
+ # GH#28690
1317
+ df = DataFrame(index=index_df)
1318
+ result = df.reindex(index=index_res)
1319
+ expected = DataFrame(index=index_exp)
1320
+ tm.assert_frame_equal(result, expected)
1321
+
1322
+ def test_invalid_method(self):
1323
+ df = DataFrame({"A": [1, np.nan, 2]})
1324
+
1325
+ msg = "Invalid fill method"
1326
+ with pytest.raises(ValueError, match=msg):
1327
+ df.reindex([1, 0, 2], method="asfreq")
py311/lib/python3.11/site-packages/pandas/tests/frame/methods/test_rename.py ADDED
@@ -0,0 +1,415 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from collections import ChainMap
2
+ import inspect
3
+
4
+ import numpy as np
5
+ import pytest
6
+
7
+ from pandas import (
8
+ DataFrame,
9
+ Index,
10
+ MultiIndex,
11
+ merge,
12
+ )
13
+ import pandas._testing as tm
14
+
15
+
16
+ class TestRename:
17
+ def test_rename_signature(self):
18
+ sig = inspect.signature(DataFrame.rename)
19
+ parameters = set(sig.parameters)
20
+ assert parameters == {
21
+ "self",
22
+ "mapper",
23
+ "index",
24
+ "columns",
25
+ "axis",
26
+ "inplace",
27
+ "copy",
28
+ "level",
29
+ "errors",
30
+ }
31
+
32
+ def test_rename_mi(self, frame_or_series):
33
+ obj = frame_or_series(
34
+ [11, 21, 31],
35
+ index=MultiIndex.from_tuples([("A", x) for x in ["a", "B", "c"]]),
36
+ )
37
+ obj.rename(str.lower)
38
+
39
+ def test_rename(self, float_frame):
40
+ mapping = {"A": "a", "B": "b", "C": "c", "D": "d"}
41
+
42
+ renamed = float_frame.rename(columns=mapping)
43
+ renamed2 = float_frame.rename(columns=str.lower)
44
+
45
+ tm.assert_frame_equal(renamed, renamed2)
46
+ tm.assert_frame_equal(
47
+ renamed2.rename(columns=str.upper), float_frame, check_names=False
48
+ )
49
+
50
+ # index
51
+ data = {"A": {"foo": 0, "bar": 1}}
52
+
53
+ df = DataFrame(data)
54
+ renamed = df.rename(index={"foo": "bar", "bar": "foo"})
55
+ tm.assert_index_equal(renamed.index, Index(["bar", "foo"]))
56
+
57
+ renamed = df.rename(index=str.upper)
58
+ tm.assert_index_equal(renamed.index, Index(["FOO", "BAR"]))
59
+
60
+ # have to pass something
61
+ with pytest.raises(TypeError, match="must pass an index to rename"):
62
+ float_frame.rename()
63
+
64
+ # partial columns
65
+ renamed = float_frame.rename(columns={"C": "foo", "D": "bar"})
66
+ tm.assert_index_equal(renamed.columns, Index(["A", "B", "foo", "bar"]))
67
+
68
+ # other axis
69
+ renamed = float_frame.T.rename(index={"C": "foo", "D": "bar"})
70
+ tm.assert_index_equal(renamed.index, Index(["A", "B", "foo", "bar"]))
71
+
72
+ # index with name
73
+ index = Index(["foo", "bar"], name="name")
74
+ renamer = DataFrame(data, index=index)
75
+ renamed = renamer.rename(index={"foo": "bar", "bar": "foo"})
76
+ tm.assert_index_equal(renamed.index, Index(["bar", "foo"], name="name"))
77
+ assert renamed.index.name == renamer.index.name
78
+
79
+ @pytest.mark.parametrize(
80
+ "args,kwargs",
81
+ [
82
+ ((ChainMap({"A": "a"}, {"B": "b"}),), {"axis": "columns"}),
83
+ ((), {"columns": ChainMap({"A": "a"}, {"B": "b"})}),
84
+ ],
85
+ )
86
+ def test_rename_chainmap(self, args, kwargs):
87
+ # see gh-23859
88
+ colAData = range(1, 11)
89
+ colBdata = np.random.default_rng(2).standard_normal(10)
90
+
91
+ df = DataFrame({"A": colAData, "B": colBdata})
92
+ result = df.rename(*args, **kwargs)
93
+
94
+ expected = DataFrame({"a": colAData, "b": colBdata})
95
+ tm.assert_frame_equal(result, expected)
96
+
97
+ def test_rename_multiindex(self):
98
+ tuples_index = [("foo1", "bar1"), ("foo2", "bar2")]
99
+ tuples_columns = [("fizz1", "buzz1"), ("fizz2", "buzz2")]
100
+ index = MultiIndex.from_tuples(tuples_index, names=["foo", "bar"])
101
+ columns = MultiIndex.from_tuples(tuples_columns, names=["fizz", "buzz"])
102
+ df = DataFrame([(0, 0), (1, 1)], index=index, columns=columns)
103
+
104
+ #
105
+ # without specifying level -> across all levels
106
+
107
+ renamed = df.rename(
108
+ index={"foo1": "foo3", "bar2": "bar3"},
109
+ columns={"fizz1": "fizz3", "buzz2": "buzz3"},
110
+ )
111
+ new_index = MultiIndex.from_tuples(
112
+ [("foo3", "bar1"), ("foo2", "bar3")], names=["foo", "bar"]
113
+ )
114
+ new_columns = MultiIndex.from_tuples(
115
+ [("fizz3", "buzz1"), ("fizz2", "buzz3")], names=["fizz", "buzz"]
116
+ )
117
+ tm.assert_index_equal(renamed.index, new_index)
118
+ tm.assert_index_equal(renamed.columns, new_columns)
119
+ assert renamed.index.names == df.index.names
120
+ assert renamed.columns.names == df.columns.names
121
+
122
+ #
123
+ # with specifying a level (GH13766)
124
+
125
+ # dict
126
+ new_columns = MultiIndex.from_tuples(
127
+ [("fizz3", "buzz1"), ("fizz2", "buzz2")], names=["fizz", "buzz"]
128
+ )
129
+ renamed = df.rename(columns={"fizz1": "fizz3", "buzz2": "buzz3"}, level=0)
130
+ tm.assert_index_equal(renamed.columns, new_columns)
131
+ renamed = df.rename(columns={"fizz1": "fizz3", "buzz2": "buzz3"}, level="fizz")
132
+ tm.assert_index_equal(renamed.columns, new_columns)
133
+
134
+ new_columns = MultiIndex.from_tuples(
135
+ [("fizz1", "buzz1"), ("fizz2", "buzz3")], names=["fizz", "buzz"]
136
+ )
137
+ renamed = df.rename(columns={"fizz1": "fizz3", "buzz2": "buzz3"}, level=1)
138
+ tm.assert_index_equal(renamed.columns, new_columns)
139
+ renamed = df.rename(columns={"fizz1": "fizz3", "buzz2": "buzz3"}, level="buzz")
140
+ tm.assert_index_equal(renamed.columns, new_columns)
141
+
142
+ # function
143
+ func = str.upper
144
+ new_columns = MultiIndex.from_tuples(
145
+ [("FIZZ1", "buzz1"), ("FIZZ2", "buzz2")], names=["fizz", "buzz"]
146
+ )
147
+ renamed = df.rename(columns=func, level=0)
148
+ tm.assert_index_equal(renamed.columns, new_columns)
149
+ renamed = df.rename(columns=func, level="fizz")
150
+ tm.assert_index_equal(renamed.columns, new_columns)
151
+
152
+ new_columns = MultiIndex.from_tuples(
153
+ [("fizz1", "BUZZ1"), ("fizz2", "BUZZ2")], names=["fizz", "buzz"]
154
+ )
155
+ renamed = df.rename(columns=func, level=1)
156
+ tm.assert_index_equal(renamed.columns, new_columns)
157
+ renamed = df.rename(columns=func, level="buzz")
158
+ tm.assert_index_equal(renamed.columns, new_columns)
159
+
160
+ # index
161
+ new_index = MultiIndex.from_tuples(
162
+ [("foo3", "bar1"), ("foo2", "bar2")], names=["foo", "bar"]
163
+ )
164
+ renamed = df.rename(index={"foo1": "foo3", "bar2": "bar3"}, level=0)
165
+ tm.assert_index_equal(renamed.index, new_index)
166
+
167
+ def test_rename_nocopy(self, float_frame, using_copy_on_write, warn_copy_on_write):
168
+ renamed = float_frame.rename(columns={"C": "foo"}, copy=False)
169
+
170
+ assert np.shares_memory(renamed["foo"]._values, float_frame["C"]._values)
171
+
172
+ with tm.assert_cow_warning(warn_copy_on_write):
173
+ renamed.loc[:, "foo"] = 1.0
174
+ if using_copy_on_write:
175
+ assert not (float_frame["C"] == 1.0).all()
176
+ else:
177
+ assert (float_frame["C"] == 1.0).all()
178
+
179
+ def test_rename_inplace(self, float_frame):
180
+ float_frame.rename(columns={"C": "foo"})
181
+ assert "C" in float_frame
182
+ assert "foo" not in float_frame
183
+
184
+ c_values = float_frame["C"]
185
+ float_frame = float_frame.copy()
186
+ return_value = float_frame.rename(columns={"C": "foo"}, inplace=True)
187
+ assert return_value is None
188
+
189
+ assert "C" not in float_frame
190
+ assert "foo" in float_frame
191
+ # GH 44153
192
+ # Used to be id(float_frame["foo"]) != c_id, but flaky in the CI
193
+ assert float_frame["foo"] is not c_values
194
+
195
+ def test_rename_bug(self):
196
+ # GH 5344
197
+ # rename set ref_locs, and set_index was not resetting
198
+ df = DataFrame({0: ["foo", "bar"], 1: ["bah", "bas"], 2: [1, 2]})
199
+ df = df.rename(columns={0: "a"})
200
+ df = df.rename(columns={1: "b"})
201
+ df = df.set_index(["a", "b"])
202
+ df.columns = ["2001-01-01"]
203
+ expected = DataFrame(
204
+ [[1], [2]],
205
+ index=MultiIndex.from_tuples(
206
+ [("foo", "bah"), ("bar", "bas")], names=["a", "b"]
207
+ ),
208
+ columns=["2001-01-01"],
209
+ )
210
+ tm.assert_frame_equal(df, expected)
211
+
212
+ def test_rename_bug2(self):
213
+ # GH 19497
214
+ # rename was changing Index to MultiIndex if Index contained tuples
215
+
216
+ df = DataFrame(data=np.arange(3), index=[(0, 0), (1, 1), (2, 2)], columns=["a"])
217
+ df = df.rename({(1, 1): (5, 4)}, axis="index")
218
+ expected = DataFrame(
219
+ data=np.arange(3), index=[(0, 0), (5, 4), (2, 2)], columns=["a"]
220
+ )
221
+ tm.assert_frame_equal(df, expected)
222
+
223
+ def test_rename_errors_raises(self):
224
+ df = DataFrame(columns=["A", "B", "C", "D"])
225
+ with pytest.raises(KeyError, match="'E'] not found in axis"):
226
+ df.rename(columns={"A": "a", "E": "e"}, errors="raise")
227
+
228
+ @pytest.mark.parametrize(
229
+ "mapper, errors, expected_columns",
230
+ [
231
+ ({"A": "a", "E": "e"}, "ignore", ["a", "B", "C", "D"]),
232
+ ({"A": "a"}, "raise", ["a", "B", "C", "D"]),
233
+ (str.lower, "raise", ["a", "b", "c", "d"]),
234
+ ],
235
+ )
236
+ def test_rename_errors(self, mapper, errors, expected_columns):
237
+ # GH 13473
238
+ # rename now works with errors parameter
239
+ df = DataFrame(columns=["A", "B", "C", "D"])
240
+ result = df.rename(columns=mapper, errors=errors)
241
+ expected = DataFrame(columns=expected_columns)
242
+ tm.assert_frame_equal(result, expected)
243
+
244
+ def test_rename_objects(self, float_string_frame):
245
+ renamed = float_string_frame.rename(columns=str.upper)
246
+
247
+ assert "FOO" in renamed
248
+ assert "foo" not in renamed
249
+
250
+ def test_rename_axis_style(self):
251
+ # https://github.com/pandas-dev/pandas/issues/12392
252
+ df = DataFrame({"A": [1, 2], "B": [1, 2]}, index=["X", "Y"])
253
+ expected = DataFrame({"a": [1, 2], "b": [1, 2]}, index=["X", "Y"])
254
+
255
+ result = df.rename(str.lower, axis=1)
256
+ tm.assert_frame_equal(result, expected)
257
+
258
+ result = df.rename(str.lower, axis="columns")
259
+ tm.assert_frame_equal(result, expected)
260
+
261
+ result = df.rename({"A": "a", "B": "b"}, axis=1)
262
+ tm.assert_frame_equal(result, expected)
263
+
264
+ result = df.rename({"A": "a", "B": "b"}, axis="columns")
265
+ tm.assert_frame_equal(result, expected)
266
+
267
+ # Index
268
+ expected = DataFrame({"A": [1, 2], "B": [1, 2]}, index=["x", "y"])
269
+ result = df.rename(str.lower, axis=0)
270
+ tm.assert_frame_equal(result, expected)
271
+
272
+ result = df.rename(str.lower, axis="index")
273
+ tm.assert_frame_equal(result, expected)
274
+
275
+ result = df.rename({"X": "x", "Y": "y"}, axis=0)
276
+ tm.assert_frame_equal(result, expected)
277
+
278
+ result = df.rename({"X": "x", "Y": "y"}, axis="index")
279
+ tm.assert_frame_equal(result, expected)
280
+
281
+ result = df.rename(mapper=str.lower, axis="index")
282
+ tm.assert_frame_equal(result, expected)
283
+
284
+ def test_rename_mapper_multi(self):
285
+ df = DataFrame({"A": ["a", "b"], "B": ["c", "d"], "C": [1, 2]}).set_index(
286
+ ["A", "B"]
287
+ )
288
+ result = df.rename(str.upper)
289
+ expected = df.rename(index=str.upper)
290
+ tm.assert_frame_equal(result, expected)
291
+
292
+ def test_rename_positional_named(self):
293
+ # https://github.com/pandas-dev/pandas/issues/12392
294
+ df = DataFrame({"a": [1, 2], "b": [1, 2]}, index=["X", "Y"])
295
+ result = df.rename(index=str.lower, columns=str.upper)
296
+ expected = DataFrame({"A": [1, 2], "B": [1, 2]}, index=["x", "y"])
297
+ tm.assert_frame_equal(result, expected)
298
+
299
+ def test_rename_axis_style_raises(self):
300
+ # see gh-12392
301
+ df = DataFrame({"A": [1, 2], "B": [1, 2]}, index=["0", "1"])
302
+
303
+ # Named target and axis
304
+ over_spec_msg = "Cannot specify both 'axis' and any of 'index' or 'columns'"
305
+ with pytest.raises(TypeError, match=over_spec_msg):
306
+ df.rename(index=str.lower, axis=1)
307
+
308
+ with pytest.raises(TypeError, match=over_spec_msg):
309
+ df.rename(index=str.lower, axis="columns")
310
+
311
+ with pytest.raises(TypeError, match=over_spec_msg):
312
+ df.rename(columns=str.lower, axis="columns")
313
+
314
+ with pytest.raises(TypeError, match=over_spec_msg):
315
+ df.rename(index=str.lower, axis=0)
316
+
317
+ # Multiple targets and axis
318
+ with pytest.raises(TypeError, match=over_spec_msg):
319
+ df.rename(str.lower, index=str.lower, axis="columns")
320
+
321
+ # Too many targets
322
+ over_spec_msg = "Cannot specify both 'mapper' and any of 'index' or 'columns'"
323
+ with pytest.raises(TypeError, match=over_spec_msg):
324
+ df.rename(str.lower, index=str.lower, columns=str.lower)
325
+
326
+ # Duplicates
327
+ with pytest.raises(TypeError, match="multiple values"):
328
+ df.rename(id, mapper=id)
329
+
330
+ def test_rename_positional_raises(self):
331
+ # GH 29136
332
+ df = DataFrame(columns=["A", "B"])
333
+ msg = r"rename\(\) takes from 1 to 2 positional arguments"
334
+
335
+ with pytest.raises(TypeError, match=msg):
336
+ df.rename(None, str.lower)
337
+
338
+ def test_rename_no_mappings_raises(self):
339
+ # GH 29136
340
+ df = DataFrame([[1]])
341
+ msg = "must pass an index to rename"
342
+ with pytest.raises(TypeError, match=msg):
343
+ df.rename()
344
+
345
+ with pytest.raises(TypeError, match=msg):
346
+ df.rename(None, index=None)
347
+
348
+ with pytest.raises(TypeError, match=msg):
349
+ df.rename(None, columns=None)
350
+
351
+ with pytest.raises(TypeError, match=msg):
352
+ df.rename(None, columns=None, index=None)
353
+
354
+ def test_rename_mapper_and_positional_arguments_raises(self):
355
+ # GH 29136
356
+ df = DataFrame([[1]])
357
+ msg = "Cannot specify both 'mapper' and any of 'index' or 'columns'"
358
+ with pytest.raises(TypeError, match=msg):
359
+ df.rename({}, index={})
360
+
361
+ with pytest.raises(TypeError, match=msg):
362
+ df.rename({}, columns={})
363
+
364
+ with pytest.raises(TypeError, match=msg):
365
+ df.rename({}, columns={}, index={})
366
+
367
+ def test_rename_with_duplicate_columns(self):
368
+ # GH#4403
369
+ df4 = DataFrame(
370
+ {"RT": [0.0454], "TClose": [22.02], "TExg": [0.0422]},
371
+ index=MultiIndex.from_tuples(
372
+ [(600809, 20130331)], names=["STK_ID", "RPT_Date"]
373
+ ),
374
+ )
375
+
376
+ df5 = DataFrame(
377
+ {
378
+ "RPT_Date": [20120930, 20121231, 20130331],
379
+ "STK_ID": [600809] * 3,
380
+ "STK_Name": ["饡驦", "饡驦", "饡驦"],
381
+ "TClose": [38.05, 41.66, 30.01],
382
+ },
383
+ index=MultiIndex.from_tuples(
384
+ [(600809, 20120930), (600809, 20121231), (600809, 20130331)],
385
+ names=["STK_ID", "RPT_Date"],
386
+ ),
387
+ )
388
+ # TODO: can we construct this without merge?
389
+ k = merge(df4, df5, how="inner", left_index=True, right_index=True)
390
+ result = k.rename(columns={"TClose_x": "TClose", "TClose_y": "QT_Close"})
391
+
392
+ expected = DataFrame(
393
+ [[0.0454, 22.02, 0.0422, 20130331, 600809, "饡驦", 30.01]],
394
+ columns=[
395
+ "RT",
396
+ "TClose",
397
+ "TExg",
398
+ "RPT_Date",
399
+ "STK_ID",
400
+ "STK_Name",
401
+ "QT_Close",
402
+ ],
403
+ ).set_index(["STK_ID", "RPT_Date"], drop=False)
404
+ tm.assert_frame_equal(result, expected)
405
+
406
+ def test_rename_boolean_index(self):
407
+ df = DataFrame(np.arange(15).reshape(3, 5), columns=[False, True, 2, 3, 4])
408
+ mapper = {0: "foo", 1: "bar", 2: "bah"}
409
+ res = df.rename(index=mapper)
410
+ exp = DataFrame(
411
+ np.arange(15).reshape(3, 5),
412
+ columns=[False, True, 2, 3, 4],
413
+ index=["foo", "bar", "bah"],
414
+ )
415
+ tm.assert_frame_equal(res, exp)
py311/lib/python3.11/site-packages/pandas/tests/frame/methods/test_reorder_levels.py ADDED
@@ -0,0 +1,74 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import numpy as np
2
+ import pytest
3
+
4
+ from pandas import (
5
+ DataFrame,
6
+ MultiIndex,
7
+ )
8
+ import pandas._testing as tm
9
+
10
+
11
+ class TestReorderLevels:
12
+ def test_reorder_levels(self, frame_or_series):
13
+ index = MultiIndex(
14
+ levels=[["bar"], ["one", "two", "three"], [0, 1]],
15
+ codes=[[0, 0, 0, 0, 0, 0], [0, 1, 2, 0, 1, 2], [0, 1, 0, 1, 0, 1]],
16
+ names=["L0", "L1", "L2"],
17
+ )
18
+ df = DataFrame({"A": np.arange(6), "B": np.arange(6)}, index=index)
19
+ obj = tm.get_obj(df, frame_or_series)
20
+
21
+ # no change, position
22
+ result = obj.reorder_levels([0, 1, 2])
23
+ tm.assert_equal(obj, result)
24
+
25
+ # no change, labels
26
+ result = obj.reorder_levels(["L0", "L1", "L2"])
27
+ tm.assert_equal(obj, result)
28
+
29
+ # rotate, position
30
+ result = obj.reorder_levels([1, 2, 0])
31
+ e_idx = MultiIndex(
32
+ levels=[["one", "two", "three"], [0, 1], ["bar"]],
33
+ codes=[[0, 1, 2, 0, 1, 2], [0, 1, 0, 1, 0, 1], [0, 0, 0, 0, 0, 0]],
34
+ names=["L1", "L2", "L0"],
35
+ )
36
+ expected = DataFrame({"A": np.arange(6), "B": np.arange(6)}, index=e_idx)
37
+ expected = tm.get_obj(expected, frame_or_series)
38
+ tm.assert_equal(result, expected)
39
+
40
+ result = obj.reorder_levels([0, 0, 0])
41
+ e_idx = MultiIndex(
42
+ levels=[["bar"], ["bar"], ["bar"]],
43
+ codes=[[0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0]],
44
+ names=["L0", "L0", "L0"],
45
+ )
46
+ expected = DataFrame({"A": np.arange(6), "B": np.arange(6)}, index=e_idx)
47
+ expected = tm.get_obj(expected, frame_or_series)
48
+ tm.assert_equal(result, expected)
49
+
50
+ result = obj.reorder_levels(["L0", "L0", "L0"])
51
+ tm.assert_equal(result, expected)
52
+
53
+ def test_reorder_levels_swaplevel_equivalence(
54
+ self, multiindex_year_month_day_dataframe_random_data
55
+ ):
56
+ ymd = multiindex_year_month_day_dataframe_random_data
57
+
58
+ result = ymd.reorder_levels(["month", "day", "year"])
59
+ expected = ymd.swaplevel(0, 1).swaplevel(1, 2)
60
+ tm.assert_frame_equal(result, expected)
61
+
62
+ result = ymd["A"].reorder_levels(["month", "day", "year"])
63
+ expected = ymd["A"].swaplevel(0, 1).swaplevel(1, 2)
64
+ tm.assert_series_equal(result, expected)
65
+
66
+ result = ymd.T.reorder_levels(["month", "day", "year"], axis=1)
67
+ expected = ymd.T.swaplevel(0, 1, axis=1).swaplevel(1, 2, axis=1)
68
+ tm.assert_frame_equal(result, expected)
69
+
70
+ with pytest.raises(TypeError, match="hierarchical axis"):
71
+ ymd.reorder_levels([1, 2], axis=1)
72
+
73
+ with pytest.raises(IndexError, match="Too many levels"):
74
+ ymd.index.reorder_levels([1, 2, 3])
py311/lib/python3.11/site-packages/pandas/tests/frame/methods/test_shift.py ADDED
@@ -0,0 +1,764 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import numpy as np
2
+ import pytest
3
+
4
+ import pandas.util._test_decorators as td
5
+
6
+ import pandas as pd
7
+ from pandas import (
8
+ CategoricalIndex,
9
+ DataFrame,
10
+ Index,
11
+ NaT,
12
+ Series,
13
+ date_range,
14
+ offsets,
15
+ )
16
+ import pandas._testing as tm
17
+
18
+
19
+ class TestDataFrameShift:
20
+ def test_shift_axis1_with_valid_fill_value_one_array(self):
21
+ # Case with axis=1 that does not go through the "len(arrays)>1" path
22
+ # in DataFrame.shift
23
+ data = np.random.default_rng(2).standard_normal((5, 3))
24
+ df = DataFrame(data)
25
+ res = df.shift(axis=1, periods=1, fill_value=12345)
26
+ expected = df.T.shift(periods=1, fill_value=12345).T
27
+ tm.assert_frame_equal(res, expected)
28
+
29
+ # same but with an 1D ExtensionArray backing it
30
+ df2 = df[[0]].astype("Float64")
31
+ res2 = df2.shift(axis=1, periods=1, fill_value=12345)
32
+ expected2 = DataFrame([12345] * 5, dtype="Float64")
33
+ tm.assert_frame_equal(res2, expected2)
34
+
35
+ def test_shift_deprecate_freq_and_fill_value(self, frame_or_series):
36
+ # Can't pass both!
37
+ obj = frame_or_series(
38
+ np.random.default_rng(2).standard_normal(5),
39
+ index=date_range("1/1/2000", periods=5, freq="h"),
40
+ )
41
+
42
+ msg = (
43
+ "Passing a 'freq' together with a 'fill_value' silently ignores the "
44
+ "fill_value"
45
+ )
46
+ with tm.assert_produces_warning(FutureWarning, match=msg):
47
+ obj.shift(1, fill_value=1, freq="h")
48
+
49
+ if frame_or_series is DataFrame:
50
+ obj.columns = date_range("1/1/2000", periods=1, freq="h")
51
+ with tm.assert_produces_warning(FutureWarning, match=msg):
52
+ obj.shift(1, axis=1, fill_value=1, freq="h")
53
+
54
+ @pytest.mark.parametrize(
55
+ "input_data, output_data",
56
+ [(np.empty(shape=(0,)), []), (np.ones(shape=(2,)), [np.nan, 1.0])],
57
+ )
58
+ def test_shift_non_writable_array(self, input_data, output_data, frame_or_series):
59
+ # GH21049 Verify whether non writable numpy array is shiftable
60
+ input_data.setflags(write=False)
61
+
62
+ result = frame_or_series(input_data).shift(1)
63
+ if frame_or_series is not Series:
64
+ # need to explicitly specify columns in the empty case
65
+ expected = frame_or_series(
66
+ output_data,
67
+ index=range(len(output_data)),
68
+ columns=range(1),
69
+ dtype="float64",
70
+ )
71
+ else:
72
+ expected = frame_or_series(output_data, dtype="float64")
73
+
74
+ tm.assert_equal(result, expected)
75
+
76
+ def test_shift_mismatched_freq(self, frame_or_series):
77
+ ts = frame_or_series(
78
+ np.random.default_rng(2).standard_normal(5),
79
+ index=date_range("1/1/2000", periods=5, freq="h"),
80
+ )
81
+
82
+ result = ts.shift(1, freq="5min")
83
+ exp_index = ts.index.shift(1, freq="5min")
84
+ tm.assert_index_equal(result.index, exp_index)
85
+
86
+ # GH#1063, multiple of same base
87
+ result = ts.shift(1, freq="4h")
88
+ exp_index = ts.index + offsets.Hour(4)
89
+ tm.assert_index_equal(result.index, exp_index)
90
+
91
+ @pytest.mark.parametrize(
92
+ "obj",
93
+ [
94
+ Series([np.arange(5)]),
95
+ date_range("1/1/2011", periods=24, freq="h"),
96
+ Series(range(5), index=date_range("2017", periods=5)),
97
+ ],
98
+ )
99
+ @pytest.mark.parametrize("shift_size", [0, 1, 2])
100
+ def test_shift_always_copy(self, obj, shift_size, frame_or_series):
101
+ # GH#22397
102
+ if frame_or_series is not Series:
103
+ obj = obj.to_frame()
104
+ assert obj.shift(shift_size) is not obj
105
+
106
+ def test_shift_object_non_scalar_fill(self):
107
+ # shift requires scalar fill_value except for object dtype
108
+ ser = Series(range(3))
109
+ with pytest.raises(ValueError, match="fill_value must be a scalar"):
110
+ ser.shift(1, fill_value=[])
111
+
112
+ df = ser.to_frame()
113
+ with pytest.raises(ValueError, match="fill_value must be a scalar"):
114
+ df.shift(1, fill_value=np.arange(3))
115
+
116
+ obj_ser = ser.astype(object)
117
+ result = obj_ser.shift(1, fill_value={})
118
+ assert result[0] == {}
119
+
120
+ obj_df = obj_ser.to_frame()
121
+ result = obj_df.shift(1, fill_value={})
122
+ assert result.iloc[0, 0] == {}
123
+
124
+ def test_shift_int(self, datetime_frame, frame_or_series):
125
+ ts = tm.get_obj(datetime_frame, frame_or_series).astype(int)
126
+ shifted = ts.shift(1)
127
+ expected = ts.astype(float).shift(1)
128
+ tm.assert_equal(shifted, expected)
129
+
130
+ @pytest.mark.parametrize("dtype", ["int32", "int64"])
131
+ def test_shift_32bit_take(self, frame_or_series, dtype):
132
+ # 32-bit taking
133
+ # GH#8129
134
+ index = date_range("2000-01-01", periods=5)
135
+ arr = np.arange(5, dtype=dtype)
136
+ s1 = frame_or_series(arr, index=index)
137
+ p = arr[1]
138
+ result = s1.shift(periods=p)
139
+ expected = frame_or_series([np.nan, 0, 1, 2, 3], index=index)
140
+ tm.assert_equal(result, expected)
141
+
142
+ @pytest.mark.parametrize("periods", [1, 2, 3, 4])
143
+ def test_shift_preserve_freqstr(self, periods, frame_or_series):
144
+ # GH#21275
145
+ obj = frame_or_series(
146
+ range(periods),
147
+ index=date_range("2016-1-1 00:00:00", periods=periods, freq="h"),
148
+ )
149
+
150
+ result = obj.shift(1, "2h")
151
+
152
+ expected = frame_or_series(
153
+ range(periods),
154
+ index=date_range("2016-1-1 02:00:00", periods=periods, freq="h"),
155
+ )
156
+ tm.assert_equal(result, expected)
157
+
158
+ def test_shift_dst(self, frame_or_series):
159
+ # GH#13926
160
+ dates = date_range("2016-11-06", freq="h", periods=10, tz="US/Eastern")
161
+ obj = frame_or_series(dates)
162
+
163
+ res = obj.shift(0)
164
+ tm.assert_equal(res, obj)
165
+ assert tm.get_dtype(res) == "datetime64[ns, US/Eastern]"
166
+
167
+ res = obj.shift(1)
168
+ exp_vals = [NaT] + dates.astype(object).values.tolist()[:9]
169
+ exp = frame_or_series(exp_vals)
170
+ tm.assert_equal(res, exp)
171
+ assert tm.get_dtype(res) == "datetime64[ns, US/Eastern]"
172
+
173
+ res = obj.shift(-2)
174
+ exp_vals = dates.astype(object).values.tolist()[2:] + [NaT, NaT]
175
+ exp = frame_or_series(exp_vals)
176
+ tm.assert_equal(res, exp)
177
+ assert tm.get_dtype(res) == "datetime64[ns, US/Eastern]"
178
+
179
+ @pytest.mark.parametrize("ex", [10, -10, 20, -20])
180
+ def test_shift_dst_beyond(self, frame_or_series, ex):
181
+ # GH#13926
182
+ dates = date_range("2016-11-06", freq="h", periods=10, tz="US/Eastern")
183
+ obj = frame_or_series(dates)
184
+ res = obj.shift(ex)
185
+ exp = frame_or_series([NaT] * 10, dtype="datetime64[ns, US/Eastern]")
186
+ tm.assert_equal(res, exp)
187
+ assert tm.get_dtype(res) == "datetime64[ns, US/Eastern]"
188
+
189
+ def test_shift_by_zero(self, datetime_frame, frame_or_series):
190
+ # shift by 0
191
+ obj = tm.get_obj(datetime_frame, frame_or_series)
192
+ unshifted = obj.shift(0)
193
+ tm.assert_equal(unshifted, obj)
194
+
195
+ def test_shift(self, datetime_frame):
196
+ # naive shift
197
+ ser = datetime_frame["A"]
198
+
199
+ shifted = datetime_frame.shift(5)
200
+ tm.assert_index_equal(shifted.index, datetime_frame.index)
201
+
202
+ shifted_ser = ser.shift(5)
203
+ tm.assert_series_equal(shifted["A"], shifted_ser)
204
+
205
+ shifted = datetime_frame.shift(-5)
206
+ tm.assert_index_equal(shifted.index, datetime_frame.index)
207
+
208
+ shifted_ser = ser.shift(-5)
209
+ tm.assert_series_equal(shifted["A"], shifted_ser)
210
+
211
+ unshifted = datetime_frame.shift(5).shift(-5)
212
+ tm.assert_numpy_array_equal(
213
+ unshifted.dropna().values, datetime_frame.values[:-5]
214
+ )
215
+
216
+ unshifted_ser = ser.shift(5).shift(-5)
217
+ tm.assert_numpy_array_equal(unshifted_ser.dropna().values, ser.values[:-5])
218
+
219
+ def test_shift_by_offset(self, datetime_frame, frame_or_series):
220
+ # shift by DateOffset
221
+ obj = tm.get_obj(datetime_frame, frame_or_series)
222
+ offset = offsets.BDay()
223
+
224
+ shifted = obj.shift(5, freq=offset)
225
+ assert len(shifted) == len(obj)
226
+ unshifted = shifted.shift(-5, freq=offset)
227
+ tm.assert_equal(unshifted, obj)
228
+
229
+ shifted2 = obj.shift(5, freq="B")
230
+ tm.assert_equal(shifted, shifted2)
231
+
232
+ unshifted = obj.shift(0, freq=offset)
233
+ tm.assert_equal(unshifted, obj)
234
+
235
+ d = obj.index[0]
236
+ shifted_d = d + offset * 5
237
+ if frame_or_series is DataFrame:
238
+ tm.assert_series_equal(obj.xs(d), shifted.xs(shifted_d), check_names=False)
239
+ else:
240
+ tm.assert_almost_equal(obj.at[d], shifted.at[shifted_d])
241
+
242
+ def test_shift_with_periodindex(self, frame_or_series):
243
+ # Shifting with PeriodIndex
244
+ ps = DataFrame(
245
+ np.arange(4, dtype=float), index=pd.period_range("2020-01-01", periods=4)
246
+ )
247
+ ps = tm.get_obj(ps, frame_or_series)
248
+
249
+ shifted = ps.shift(1)
250
+ unshifted = shifted.shift(-1)
251
+ tm.assert_index_equal(shifted.index, ps.index)
252
+ tm.assert_index_equal(unshifted.index, ps.index)
253
+ if frame_or_series is DataFrame:
254
+ tm.assert_numpy_array_equal(
255
+ unshifted.iloc[:, 0].dropna().values, ps.iloc[:-1, 0].values
256
+ )
257
+ else:
258
+ tm.assert_numpy_array_equal(unshifted.dropna().values, ps.values[:-1])
259
+
260
+ shifted2 = ps.shift(1, "D")
261
+ shifted3 = ps.shift(1, offsets.Day())
262
+ tm.assert_equal(shifted2, shifted3)
263
+ tm.assert_equal(ps, shifted2.shift(-1, "D"))
264
+
265
+ msg = "does not match PeriodIndex freq"
266
+ with pytest.raises(ValueError, match=msg):
267
+ ps.shift(freq="W")
268
+
269
+ # legacy support
270
+ shifted4 = ps.shift(1, freq="D")
271
+ tm.assert_equal(shifted2, shifted4)
272
+
273
+ shifted5 = ps.shift(1, freq=offsets.Day())
274
+ tm.assert_equal(shifted5, shifted4)
275
+
276
+ def test_shift_other_axis(self):
277
+ # shift other axis
278
+ # GH#6371
279
+ df = DataFrame(np.random.default_rng(2).random((10, 5)))
280
+ expected = pd.concat(
281
+ [DataFrame(np.nan, index=df.index, columns=[0]), df.iloc[:, 0:-1]],
282
+ ignore_index=True,
283
+ axis=1,
284
+ )
285
+ result = df.shift(1, axis=1)
286
+ tm.assert_frame_equal(result, expected)
287
+
288
+ def test_shift_named_axis(self):
289
+ # shift named axis
290
+ df = DataFrame(np.random.default_rng(2).random((10, 5)))
291
+ expected = pd.concat(
292
+ [DataFrame(np.nan, index=df.index, columns=[0]), df.iloc[:, 0:-1]],
293
+ ignore_index=True,
294
+ axis=1,
295
+ )
296
+ result = df.shift(1, axis="columns")
297
+ tm.assert_frame_equal(result, expected)
298
+
299
+ def test_shift_other_axis_with_freq(self, datetime_frame):
300
+ obj = datetime_frame.T
301
+ offset = offsets.BDay()
302
+
303
+ # GH#47039
304
+ shifted = obj.shift(5, freq=offset, axis=1)
305
+ assert len(shifted) == len(obj)
306
+ unshifted = shifted.shift(-5, freq=offset, axis=1)
307
+ tm.assert_equal(unshifted, obj)
308
+
309
+ def test_shift_bool(self):
310
+ df = DataFrame({"high": [True, False], "low": [False, False]})
311
+ rs = df.shift(1)
312
+ xp = DataFrame(
313
+ np.array([[np.nan, np.nan], [True, False]], dtype=object),
314
+ columns=["high", "low"],
315
+ )
316
+ tm.assert_frame_equal(rs, xp)
317
+
318
+ def test_shift_categorical1(self, frame_or_series):
319
+ # GH#9416
320
+ obj = frame_or_series(["a", "b", "c", "d"], dtype="category")
321
+
322
+ rt = obj.shift(1).shift(-1)
323
+ tm.assert_equal(obj.iloc[:-1], rt.dropna())
324
+
325
+ def get_cat_values(ndframe):
326
+ # For Series we could just do ._values; for DataFrame
327
+ # we may be able to do this if we ever have 2D Categoricals
328
+ return ndframe._mgr.arrays[0]
329
+
330
+ cat = get_cat_values(obj)
331
+
332
+ sp1 = obj.shift(1)
333
+ tm.assert_index_equal(obj.index, sp1.index)
334
+ assert np.all(get_cat_values(sp1).codes[:1] == -1)
335
+ assert np.all(cat.codes[:-1] == get_cat_values(sp1).codes[1:])
336
+
337
+ sn2 = obj.shift(-2)
338
+ tm.assert_index_equal(obj.index, sn2.index)
339
+ assert np.all(get_cat_values(sn2).codes[-2:] == -1)
340
+ assert np.all(cat.codes[2:] == get_cat_values(sn2).codes[:-2])
341
+
342
+ tm.assert_index_equal(cat.categories, get_cat_values(sp1).categories)
343
+ tm.assert_index_equal(cat.categories, get_cat_values(sn2).categories)
344
+
345
+ def test_shift_categorical(self):
346
+ # GH#9416
347
+ s1 = Series(["a", "b", "c"], dtype="category")
348
+ s2 = Series(["A", "B", "C"], dtype="category")
349
+ df = DataFrame({"one": s1, "two": s2})
350
+ rs = df.shift(1)
351
+ xp = DataFrame({"one": s1.shift(1), "two": s2.shift(1)})
352
+ tm.assert_frame_equal(rs, xp)
353
+
354
+ def test_shift_categorical_fill_value(self, frame_or_series):
355
+ ts = frame_or_series(["a", "b", "c", "d"], dtype="category")
356
+ res = ts.shift(1, fill_value="a")
357
+ expected = frame_or_series(
358
+ pd.Categorical(
359
+ ["a", "a", "b", "c"], categories=["a", "b", "c", "d"], ordered=False
360
+ )
361
+ )
362
+ tm.assert_equal(res, expected)
363
+
364
+ # check for incorrect fill_value
365
+ msg = r"Cannot setitem on a Categorical with a new category \(f\)"
366
+ with pytest.raises(TypeError, match=msg):
367
+ ts.shift(1, fill_value="f")
368
+
369
+ def test_shift_fill_value(self, frame_or_series):
370
+ # GH#24128
371
+ dti = date_range("1/1/2000", periods=5, freq="h")
372
+
373
+ ts = frame_or_series([1.0, 2.0, 3.0, 4.0, 5.0], index=dti)
374
+ exp = frame_or_series([0.0, 1.0, 2.0, 3.0, 4.0], index=dti)
375
+ # check that fill value works
376
+ result = ts.shift(1, fill_value=0.0)
377
+ tm.assert_equal(result, exp)
378
+
379
+ exp = frame_or_series([0.0, 0.0, 1.0, 2.0, 3.0], index=dti)
380
+ result = ts.shift(2, fill_value=0.0)
381
+ tm.assert_equal(result, exp)
382
+
383
+ ts = frame_or_series([1, 2, 3])
384
+ res = ts.shift(2, fill_value=0)
385
+ assert tm.get_dtype(res) == tm.get_dtype(ts)
386
+
387
+ # retain integer dtype
388
+ obj = frame_or_series([1, 2, 3, 4, 5], index=dti)
389
+ exp = frame_or_series([0, 1, 2, 3, 4], index=dti)
390
+ result = obj.shift(1, fill_value=0)
391
+ tm.assert_equal(result, exp)
392
+
393
+ exp = frame_or_series([0, 0, 1, 2, 3], index=dti)
394
+ result = obj.shift(2, fill_value=0)
395
+ tm.assert_equal(result, exp)
396
+
397
+ def test_shift_empty(self):
398
+ # Regression test for GH#8019
399
+ df = DataFrame({"foo": []})
400
+ rs = df.shift(-1)
401
+
402
+ tm.assert_frame_equal(df, rs)
403
+
404
+ def test_shift_duplicate_columns(self):
405
+ # GH#9092; verify that position-based shifting works
406
+ # in the presence of duplicate columns
407
+ column_lists = [list(range(5)), [1] * 5, [1, 1, 2, 2, 1]]
408
+ data = np.random.default_rng(2).standard_normal((20, 5))
409
+
410
+ shifted = []
411
+ for columns in column_lists:
412
+ df = DataFrame(data.copy(), columns=columns)
413
+ for s in range(5):
414
+ df.iloc[:, s] = df.iloc[:, s].shift(s + 1)
415
+ df.columns = range(5)
416
+ shifted.append(df)
417
+
418
+ # sanity check the base case
419
+ nulls = shifted[0].isna().sum()
420
+ tm.assert_series_equal(nulls, Series(range(1, 6), dtype="int64"))
421
+
422
+ # check all answers are the same
423
+ tm.assert_frame_equal(shifted[0], shifted[1])
424
+ tm.assert_frame_equal(shifted[0], shifted[2])
425
+
426
+ def test_shift_axis1_multiple_blocks(self, using_array_manager):
427
+ # GH#35488
428
+ df1 = DataFrame(np.random.default_rng(2).integers(1000, size=(5, 3)))
429
+ df2 = DataFrame(np.random.default_rng(2).integers(1000, size=(5, 2)))
430
+ df3 = pd.concat([df1, df2], axis=1)
431
+ if not using_array_manager:
432
+ assert len(df3._mgr.blocks) == 2
433
+
434
+ result = df3.shift(2, axis=1)
435
+
436
+ expected = df3.take([-1, -1, 0, 1, 2], axis=1)
437
+ # Explicit cast to float to avoid implicit cast when setting nan.
438
+ # Column names aren't unique, so directly calling `expected.astype` won't work.
439
+ expected = expected.pipe(
440
+ lambda df: df.set_axis(range(df.shape[1]), axis=1)
441
+ .astype({0: "float", 1: "float"})
442
+ .set_axis(df.columns, axis=1)
443
+ )
444
+ expected.iloc[:, :2] = np.nan
445
+ expected.columns = df3.columns
446
+
447
+ tm.assert_frame_equal(result, expected)
448
+
449
+ # Case with periods < 0
450
+ # rebuild df3 because `take` call above consolidated
451
+ df3 = pd.concat([df1, df2], axis=1)
452
+ if not using_array_manager:
453
+ assert len(df3._mgr.blocks) == 2
454
+ result = df3.shift(-2, axis=1)
455
+
456
+ expected = df3.take([2, 3, 4, -1, -1], axis=1)
457
+ # Explicit cast to float to avoid implicit cast when setting nan.
458
+ # Column names aren't unique, so directly calling `expected.astype` won't work.
459
+ expected = expected.pipe(
460
+ lambda df: df.set_axis(range(df.shape[1]), axis=1)
461
+ .astype({3: "float", 4: "float"})
462
+ .set_axis(df.columns, axis=1)
463
+ )
464
+ expected.iloc[:, -2:] = np.nan
465
+ expected.columns = df3.columns
466
+
467
+ tm.assert_frame_equal(result, expected)
468
+
469
+ @td.skip_array_manager_not_yet_implemented # TODO(ArrayManager) axis=1 support
470
+ def test_shift_axis1_multiple_blocks_with_int_fill(self):
471
+ # GH#42719
472
+ rng = np.random.default_rng(2)
473
+ df1 = DataFrame(rng.integers(1000, size=(5, 3), dtype=int))
474
+ df2 = DataFrame(rng.integers(1000, size=(5, 2), dtype=int))
475
+ df3 = pd.concat([df1.iloc[:4, 1:3], df2.iloc[:4, :]], axis=1)
476
+ result = df3.shift(2, axis=1, fill_value=np.int_(0))
477
+ assert len(df3._mgr.blocks) == 2
478
+
479
+ expected = df3.take([-1, -1, 0, 1], axis=1)
480
+ expected.iloc[:, :2] = np.int_(0)
481
+ expected.columns = df3.columns
482
+
483
+ tm.assert_frame_equal(result, expected)
484
+
485
+ # Case with periods < 0
486
+ df3 = pd.concat([df1.iloc[:4, 1:3], df2.iloc[:4, :]], axis=1)
487
+ result = df3.shift(-2, axis=1, fill_value=np.int_(0))
488
+ assert len(df3._mgr.blocks) == 2
489
+
490
+ expected = df3.take([2, 3, -1, -1], axis=1)
491
+ expected.iloc[:, -2:] = np.int_(0)
492
+ expected.columns = df3.columns
493
+
494
+ tm.assert_frame_equal(result, expected)
495
+
496
+ def test_period_index_frame_shift_with_freq(self, frame_or_series):
497
+ ps = DataFrame(range(4), index=pd.period_range("2020-01-01", periods=4))
498
+ ps = tm.get_obj(ps, frame_or_series)
499
+
500
+ shifted = ps.shift(1, freq="infer")
501
+ unshifted = shifted.shift(-1, freq="infer")
502
+ tm.assert_equal(unshifted, ps)
503
+
504
+ shifted2 = ps.shift(freq="D")
505
+ tm.assert_equal(shifted, shifted2)
506
+
507
+ shifted3 = ps.shift(freq=offsets.Day())
508
+ tm.assert_equal(shifted, shifted3)
509
+
510
+ def test_datetime_frame_shift_with_freq(self, datetime_frame, frame_or_series):
511
+ dtobj = tm.get_obj(datetime_frame, frame_or_series)
512
+ shifted = dtobj.shift(1, freq="infer")
513
+ unshifted = shifted.shift(-1, freq="infer")
514
+ tm.assert_equal(dtobj, unshifted)
515
+
516
+ shifted2 = dtobj.shift(freq=dtobj.index.freq)
517
+ tm.assert_equal(shifted, shifted2)
518
+
519
+ inferred_ts = DataFrame(
520
+ datetime_frame.values,
521
+ Index(np.asarray(datetime_frame.index)),
522
+ columns=datetime_frame.columns,
523
+ )
524
+ inferred_ts = tm.get_obj(inferred_ts, frame_or_series)
525
+ shifted = inferred_ts.shift(1, freq="infer")
526
+ expected = dtobj.shift(1, freq="infer")
527
+ expected.index = expected.index._with_freq(None)
528
+ tm.assert_equal(shifted, expected)
529
+
530
+ unshifted = shifted.shift(-1, freq="infer")
531
+ tm.assert_equal(unshifted, inferred_ts)
532
+
533
+ def test_period_index_frame_shift_with_freq_error(self, frame_or_series):
534
+ ps = DataFrame(range(4), index=pd.period_range("2020-01-01", periods=4))
535
+ ps = tm.get_obj(ps, frame_or_series)
536
+ msg = "Given freq M does not match PeriodIndex freq D"
537
+ with pytest.raises(ValueError, match=msg):
538
+ ps.shift(freq="M")
539
+
540
+ def test_datetime_frame_shift_with_freq_error(
541
+ self, datetime_frame, frame_or_series
542
+ ):
543
+ dtobj = tm.get_obj(datetime_frame, frame_or_series)
544
+ no_freq = dtobj.iloc[[0, 5, 7]]
545
+ msg = "Freq was not set in the index hence cannot be inferred"
546
+ with pytest.raises(ValueError, match=msg):
547
+ no_freq.shift(freq="infer")
548
+
549
+ def test_shift_dt64values_int_fill_deprecated(self):
550
+ # GH#31971
551
+ ser = Series([pd.Timestamp("2020-01-01"), pd.Timestamp("2020-01-02")])
552
+
553
+ with pytest.raises(TypeError, match="value should be a"):
554
+ ser.shift(1, fill_value=0)
555
+
556
+ df = ser.to_frame()
557
+ with pytest.raises(TypeError, match="value should be a"):
558
+ df.shift(1, fill_value=0)
559
+
560
+ # axis = 1
561
+ df2 = DataFrame({"A": ser, "B": ser})
562
+ df2._consolidate_inplace()
563
+
564
+ result = df2.shift(1, axis=1, fill_value=0)
565
+ expected = DataFrame({"A": [0, 0], "B": df2["A"]})
566
+ tm.assert_frame_equal(result, expected)
567
+
568
+ # same thing but not consolidated; pre-2.0 we got different behavior
569
+ df3 = DataFrame({"A": ser})
570
+ df3["B"] = ser
571
+ assert len(df3._mgr.arrays) == 2
572
+ result = df3.shift(1, axis=1, fill_value=0)
573
+ tm.assert_frame_equal(result, expected)
574
+
575
+ @pytest.mark.parametrize(
576
+ "as_cat",
577
+ [
578
+ pytest.param(
579
+ True,
580
+ marks=pytest.mark.xfail(
581
+ reason="_can_hold_element incorrectly always returns True"
582
+ ),
583
+ ),
584
+ False,
585
+ ],
586
+ )
587
+ @pytest.mark.parametrize(
588
+ "vals",
589
+ [
590
+ date_range("2020-01-01", periods=2),
591
+ date_range("2020-01-01", periods=2, tz="US/Pacific"),
592
+ pd.period_range("2020-01-01", periods=2, freq="D"),
593
+ pd.timedelta_range("2020 Days", periods=2, freq="D"),
594
+ pd.interval_range(0, 3, periods=2),
595
+ pytest.param(
596
+ pd.array([1, 2], dtype="Int64"),
597
+ marks=pytest.mark.xfail(
598
+ reason="_can_hold_element incorrectly always returns True"
599
+ ),
600
+ ),
601
+ pytest.param(
602
+ pd.array([1, 2], dtype="Float32"),
603
+ marks=pytest.mark.xfail(
604
+ reason="_can_hold_element incorrectly always returns True"
605
+ ),
606
+ ),
607
+ ],
608
+ ids=lambda x: str(x.dtype),
609
+ )
610
+ def test_shift_dt64values_axis1_invalid_fill(self, vals, as_cat):
611
+ # GH#44564
612
+ ser = Series(vals)
613
+ if as_cat:
614
+ ser = ser.astype("category")
615
+
616
+ df = DataFrame({"A": ser})
617
+ result = df.shift(-1, axis=1, fill_value="foo")
618
+ expected = DataFrame({"A": ["foo", "foo"]})
619
+ tm.assert_frame_equal(result, expected)
620
+
621
+ # same thing but multiple blocks
622
+ df2 = DataFrame({"A": ser, "B": ser})
623
+ df2._consolidate_inplace()
624
+
625
+ result = df2.shift(-1, axis=1, fill_value="foo")
626
+ expected = DataFrame({"A": df2["B"], "B": ["foo", "foo"]})
627
+ tm.assert_frame_equal(result, expected)
628
+
629
+ # same thing but not consolidated
630
+ df3 = DataFrame({"A": ser})
631
+ df3["B"] = ser
632
+ assert len(df3._mgr.arrays) == 2
633
+ result = df3.shift(-1, axis=1, fill_value="foo")
634
+ tm.assert_frame_equal(result, expected)
635
+
636
+ def test_shift_axis1_categorical_columns(self):
637
+ # GH#38434
638
+ ci = CategoricalIndex(["a", "b", "c"])
639
+ df = DataFrame(
640
+ {"a": [1, 3], "b": [2, 4], "c": [5, 6]}, index=ci[:-1], columns=ci
641
+ )
642
+ result = df.shift(axis=1)
643
+
644
+ expected = DataFrame(
645
+ {"a": [np.nan, np.nan], "b": [1, 3], "c": [2, 4]}, index=ci[:-1], columns=ci
646
+ )
647
+ tm.assert_frame_equal(result, expected)
648
+
649
+ # periods != 1
650
+ result = df.shift(2, axis=1)
651
+ expected = DataFrame(
652
+ {"a": [np.nan, np.nan], "b": [np.nan, np.nan], "c": [1, 3]},
653
+ index=ci[:-1],
654
+ columns=ci,
655
+ )
656
+ tm.assert_frame_equal(result, expected)
657
+
658
+ def test_shift_axis1_many_periods(self):
659
+ # GH#44978 periods > len(columns)
660
+ df = DataFrame(np.random.default_rng(2).random((5, 3)))
661
+ shifted = df.shift(6, axis=1, fill_value=None)
662
+
663
+ expected = df * np.nan
664
+ tm.assert_frame_equal(shifted, expected)
665
+
666
+ shifted2 = df.shift(-6, axis=1, fill_value=None)
667
+ tm.assert_frame_equal(shifted2, expected)
668
+
669
+ def test_shift_with_offsets_freq(self):
670
+ df = DataFrame({"x": [1, 2, 3]}, index=date_range("2000", periods=3))
671
+ shifted = df.shift(freq="1MS")
672
+ expected = DataFrame(
673
+ {"x": [1, 2, 3]},
674
+ index=date_range(start="02/01/2000", end="02/01/2000", periods=3),
675
+ )
676
+ tm.assert_frame_equal(shifted, expected)
677
+
678
+ def test_shift_with_iterable_basic_functionality(self):
679
+ # GH#44424
680
+ data = {"a": [1, 2, 3], "b": [4, 5, 6]}
681
+ shifts = [0, 1, 2]
682
+
683
+ df = DataFrame(data)
684
+ shifted = df.shift(shifts)
685
+
686
+ expected = DataFrame(
687
+ {
688
+ "a_0": [1, 2, 3],
689
+ "b_0": [4, 5, 6],
690
+ "a_1": [np.nan, 1.0, 2.0],
691
+ "b_1": [np.nan, 4.0, 5.0],
692
+ "a_2": [np.nan, np.nan, 1.0],
693
+ "b_2": [np.nan, np.nan, 4.0],
694
+ }
695
+ )
696
+ tm.assert_frame_equal(expected, shifted)
697
+
698
+ def test_shift_with_iterable_series(self):
699
+ # GH#44424
700
+ data = {"a": [1, 2, 3]}
701
+ shifts = [0, 1, 2]
702
+
703
+ df = DataFrame(data)
704
+ s = df["a"]
705
+ tm.assert_frame_equal(s.shift(shifts), df.shift(shifts))
706
+
707
+ def test_shift_with_iterable_freq_and_fill_value(self):
708
+ # GH#44424
709
+ df = DataFrame(
710
+ np.random.default_rng(2).standard_normal(5),
711
+ index=date_range("1/1/2000", periods=5, freq="h"),
712
+ )
713
+
714
+ tm.assert_frame_equal(
715
+ # rename because shift with an iterable leads to str column names
716
+ df.shift([1], fill_value=1).rename(columns=lambda x: int(x[0])),
717
+ df.shift(1, fill_value=1),
718
+ )
719
+
720
+ tm.assert_frame_equal(
721
+ df.shift([1], freq="h").rename(columns=lambda x: int(x[0])),
722
+ df.shift(1, freq="h"),
723
+ )
724
+
725
+ msg = (
726
+ "Passing a 'freq' together with a 'fill_value' silently ignores the "
727
+ "fill_value"
728
+ )
729
+ with tm.assert_produces_warning(FutureWarning, match=msg):
730
+ df.shift([1, 2], fill_value=1, freq="h")
731
+
732
+ def test_shift_with_iterable_check_other_arguments(self):
733
+ # GH#44424
734
+ data = {"a": [1, 2], "b": [4, 5]}
735
+ shifts = [0, 1]
736
+ df = DataFrame(data)
737
+
738
+ # test suffix
739
+ shifted = df[["a"]].shift(shifts, suffix="_suffix")
740
+ expected = DataFrame({"a_suffix_0": [1, 2], "a_suffix_1": [np.nan, 1.0]})
741
+ tm.assert_frame_equal(shifted, expected)
742
+
743
+ # check bad inputs when doing multiple shifts
744
+ msg = "If `periods` contains multiple shifts, `axis` cannot be 1."
745
+ with pytest.raises(ValueError, match=msg):
746
+ df.shift(shifts, axis=1)
747
+
748
+ msg = "Periods must be integer, but s is <class 'str'>."
749
+ with pytest.raises(TypeError, match=msg):
750
+ df.shift(["s"])
751
+
752
+ msg = "If `periods` is an iterable, it cannot be empty."
753
+ with pytest.raises(ValueError, match=msg):
754
+ df.shift([])
755
+
756
+ msg = "Cannot specify `suffix` if `periods` is an int."
757
+ with pytest.raises(ValueError, match=msg):
758
+ df.shift(1, suffix="fails")
759
+
760
+ def test_shift_axis_one_empty(self):
761
+ # GH#57301
762
+ df = DataFrame()
763
+ result = df.shift(1, axis=1)
764
+ tm.assert_frame_equal(result, df)
py311/lib/python3.11/site-packages/pandas/tests/frame/methods/test_swaplevel.py ADDED
@@ -0,0 +1,36 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import pytest
2
+
3
+ from pandas import DataFrame
4
+ import pandas._testing as tm
5
+
6
+
7
+ class TestSwaplevel:
8
+ def test_swaplevel(self, multiindex_dataframe_random_data):
9
+ frame = multiindex_dataframe_random_data
10
+
11
+ swapped = frame["A"].swaplevel()
12
+ swapped2 = frame["A"].swaplevel(0)
13
+ swapped3 = frame["A"].swaplevel(0, 1)
14
+ swapped4 = frame["A"].swaplevel("first", "second")
15
+ assert not swapped.index.equals(frame.index)
16
+ tm.assert_series_equal(swapped, swapped2)
17
+ tm.assert_series_equal(swapped, swapped3)
18
+ tm.assert_series_equal(swapped, swapped4)
19
+
20
+ back = swapped.swaplevel()
21
+ back2 = swapped.swaplevel(0)
22
+ back3 = swapped.swaplevel(0, 1)
23
+ back4 = swapped.swaplevel("second", "first")
24
+ assert back.index.equals(frame.index)
25
+ tm.assert_series_equal(back, back2)
26
+ tm.assert_series_equal(back, back3)
27
+ tm.assert_series_equal(back, back4)
28
+
29
+ ft = frame.T
30
+ swapped = ft.swaplevel("first", "second", axis=1)
31
+ exp = frame.swaplevel("first", "second").T
32
+ tm.assert_frame_equal(swapped, exp)
33
+
34
+ msg = "Can only swap levels on a hierarchical axis."
35
+ with pytest.raises(TypeError, match=msg):
36
+ DataFrame(range(3)).swaplevel()
py311/lib/python3.11/site-packages/pandas/tests/frame/methods/test_to_dict_of_blocks.py ADDED
@@ -0,0 +1,79 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import numpy as np
2
+ import pytest
3
+
4
+ from pandas._config import using_string_dtype
5
+
6
+ import pandas.util._test_decorators as td
7
+
8
+ from pandas import (
9
+ DataFrame,
10
+ MultiIndex,
11
+ )
12
+ import pandas._testing as tm
13
+ from pandas.core.arrays import NumpyExtensionArray
14
+
15
+ pytestmark = td.skip_array_manager_invalid_test
16
+
17
+
18
+ class TestToDictOfBlocks:
19
+ @pytest.mark.filterwarnings("ignore:Setting a value on a view:FutureWarning")
20
+ def test_no_copy_blocks(self, float_frame, using_copy_on_write):
21
+ # GH#9607
22
+ df = DataFrame(float_frame, copy=True)
23
+ column = df.columns[0]
24
+
25
+ _last_df = None
26
+ # use the copy=False, change a column
27
+ blocks = df._to_dict_of_blocks()
28
+ for _df in blocks.values():
29
+ _last_df = _df
30
+ if column in _df:
31
+ _df.loc[:, column] = _df[column] + 1
32
+
33
+ if not using_copy_on_write:
34
+ # make sure we did change the original DataFrame
35
+ assert _last_df is not None and _last_df[column].equals(df[column])
36
+ else:
37
+ assert _last_df is not None and not _last_df[column].equals(df[column])
38
+
39
+
40
+ @pytest.mark.xfail(using_string_dtype(), reason="TODO(infer_string)")
41
+ def test_to_dict_of_blocks_item_cache(using_copy_on_write, warn_copy_on_write):
42
+ # Calling to_dict_of_blocks should not poison item_cache
43
+ df = DataFrame({"a": [1, 2, 3, 4], "b": ["a", "b", "c", "d"]})
44
+ df["c"] = NumpyExtensionArray(np.array([1, 2, None, 3], dtype=object))
45
+ mgr = df._mgr
46
+ assert len(mgr.blocks) == 3 # i.e. not consolidated
47
+
48
+ ser = df["b"] # populations item_cache["b"]
49
+
50
+ df._to_dict_of_blocks()
51
+
52
+ if using_copy_on_write:
53
+ with pytest.raises(ValueError, match="read-only"):
54
+ ser.values[0] = "foo"
55
+ elif warn_copy_on_write:
56
+ ser.values[0] = "foo"
57
+ assert df.loc[0, "b"] == "foo"
58
+ # with warning mode, the item cache is disabled
59
+ assert df["b"] is not ser
60
+ else:
61
+ # Check that the to_dict_of_blocks didn't break link between ser and df
62
+ ser.values[0] = "foo"
63
+ assert df.loc[0, "b"] == "foo"
64
+
65
+ assert df["b"] is ser
66
+
67
+
68
+ def test_set_change_dtype_slice():
69
+ # GH#8850
70
+ cols = MultiIndex.from_tuples([("1st", "a"), ("2nd", "b"), ("3rd", "c")])
71
+ df = DataFrame([[1.0, 2, 3], [4.0, 5, 6]], columns=cols)
72
+ df["2nd"] = df["2nd"] * 2.0
73
+
74
+ blocks = df._to_dict_of_blocks()
75
+ assert sorted(blocks.keys()) == ["float64", "int64"]
76
+ tm.assert_frame_equal(
77
+ blocks["float64"], DataFrame([[1.0, 4.0], [4.0, 10.0]], columns=cols[:2])
78
+ )
79
+ tm.assert_frame_equal(blocks["int64"], DataFrame([[3], [6]], columns=cols[2:]))
py311/lib/python3.11/site-packages/pandas/tests/frame/methods/test_tz_convert.py ADDED
@@ -0,0 +1,131 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import numpy as np
2
+ import pytest
3
+
4
+ from pandas import (
5
+ DataFrame,
6
+ Index,
7
+ MultiIndex,
8
+ Series,
9
+ date_range,
10
+ )
11
+ import pandas._testing as tm
12
+
13
+
14
+ class TestTZConvert:
15
+ def test_tz_convert(self, frame_or_series):
16
+ rng = date_range("1/1/2011", periods=200, freq="D", tz="US/Eastern")
17
+
18
+ obj = DataFrame({"a": 1}, index=rng)
19
+ obj = tm.get_obj(obj, frame_or_series)
20
+
21
+ result = obj.tz_convert("Europe/Berlin")
22
+ expected = DataFrame({"a": 1}, rng.tz_convert("Europe/Berlin"))
23
+ expected = tm.get_obj(expected, frame_or_series)
24
+
25
+ assert result.index.tz.zone == "Europe/Berlin"
26
+ tm.assert_equal(result, expected)
27
+
28
+ def test_tz_convert_axis1(self):
29
+ rng = date_range("1/1/2011", periods=200, freq="D", tz="US/Eastern")
30
+
31
+ obj = DataFrame({"a": 1}, index=rng)
32
+
33
+ obj = obj.T
34
+ result = obj.tz_convert("Europe/Berlin", axis=1)
35
+ assert result.columns.tz.zone == "Europe/Berlin"
36
+
37
+ expected = DataFrame({"a": 1}, rng.tz_convert("Europe/Berlin"))
38
+
39
+ tm.assert_equal(result, expected.T)
40
+
41
+ def test_tz_convert_naive(self, frame_or_series):
42
+ # can't convert tz-naive
43
+ rng = date_range("1/1/2011", periods=200, freq="D")
44
+ ts = Series(1, index=rng)
45
+ ts = frame_or_series(ts)
46
+
47
+ with pytest.raises(TypeError, match="Cannot convert tz-naive"):
48
+ ts.tz_convert("US/Eastern")
49
+
50
+ @pytest.mark.parametrize("fn", ["tz_localize", "tz_convert"])
51
+ def test_tz_convert_and_localize(self, fn):
52
+ l0 = date_range("20140701", periods=5, freq="D")
53
+ l1 = date_range("20140701", periods=5, freq="D")
54
+
55
+ int_idx = Index(range(5))
56
+
57
+ if fn == "tz_convert":
58
+ l0 = l0.tz_localize("UTC")
59
+ l1 = l1.tz_localize("UTC")
60
+
61
+ for idx in [l0, l1]:
62
+ l0_expected = getattr(idx, fn)("US/Pacific")
63
+ l1_expected = getattr(idx, fn)("US/Pacific")
64
+
65
+ df1 = DataFrame(np.ones(5), index=l0)
66
+ df1 = getattr(df1, fn)("US/Pacific")
67
+ tm.assert_index_equal(df1.index, l0_expected)
68
+
69
+ # MultiIndex
70
+ # GH7846
71
+ df2 = DataFrame(np.ones(5), MultiIndex.from_arrays([l0, l1]))
72
+
73
+ # freq is not preserved in MultiIndex construction
74
+ l1_expected = l1_expected._with_freq(None)
75
+ l0_expected = l0_expected._with_freq(None)
76
+ l1 = l1._with_freq(None)
77
+ l0 = l0._with_freq(None)
78
+
79
+ df3 = getattr(df2, fn)("US/Pacific", level=0)
80
+ assert not df3.index.levels[0].equals(l0)
81
+ tm.assert_index_equal(df3.index.levels[0], l0_expected)
82
+ tm.assert_index_equal(df3.index.levels[1], l1)
83
+ assert not df3.index.levels[1].equals(l1_expected)
84
+
85
+ df3 = getattr(df2, fn)("US/Pacific", level=1)
86
+ tm.assert_index_equal(df3.index.levels[0], l0)
87
+ assert not df3.index.levels[0].equals(l0_expected)
88
+ tm.assert_index_equal(df3.index.levels[1], l1_expected)
89
+ assert not df3.index.levels[1].equals(l1)
90
+
91
+ df4 = DataFrame(np.ones(5), MultiIndex.from_arrays([int_idx, l0]))
92
+
93
+ # TODO: untested
94
+ getattr(df4, fn)("US/Pacific", level=1)
95
+
96
+ tm.assert_index_equal(df3.index.levels[0], l0)
97
+ assert not df3.index.levels[0].equals(l0_expected)
98
+ tm.assert_index_equal(df3.index.levels[1], l1_expected)
99
+ assert not df3.index.levels[1].equals(l1)
100
+
101
+ # Bad Inputs
102
+
103
+ # Not DatetimeIndex / PeriodIndex
104
+ with pytest.raises(TypeError, match="DatetimeIndex"):
105
+ df = DataFrame(index=int_idx)
106
+ getattr(df, fn)("US/Pacific")
107
+
108
+ # Not DatetimeIndex / PeriodIndex
109
+ with pytest.raises(TypeError, match="DatetimeIndex"):
110
+ df = DataFrame(np.ones(5), MultiIndex.from_arrays([int_idx, l0]))
111
+ getattr(df, fn)("US/Pacific", level=0)
112
+
113
+ # Invalid level
114
+ with pytest.raises(ValueError, match="not valid"):
115
+ df = DataFrame(index=l0)
116
+ getattr(df, fn)("US/Pacific", level=1)
117
+
118
+ @pytest.mark.parametrize("copy", [True, False])
119
+ def test_tz_convert_copy_inplace_mutate(self, copy, frame_or_series):
120
+ # GH#6326
121
+ obj = frame_or_series(
122
+ np.arange(0, 5),
123
+ index=date_range("20131027", periods=5, freq="h", tz="Europe/Berlin"),
124
+ )
125
+ orig = obj.copy()
126
+ result = obj.tz_convert("UTC", copy=copy)
127
+ expected = frame_or_series(np.arange(0, 5), index=obj.index.tz_convert("UTC"))
128
+ tm.assert_equal(result, expected)
129
+ tm.assert_equal(obj, orig)
130
+ assert result.index is not obj.index
131
+ assert result is not obj
py311/lib/python3.11/site-packages/pandas/tests/frame/methods/test_values.py ADDED
@@ -0,0 +1,280 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import numpy as np
2
+ import pytest
3
+
4
+ import pandas.util._test_decorators as td
5
+
6
+ from pandas import (
7
+ DataFrame,
8
+ NaT,
9
+ Series,
10
+ Timestamp,
11
+ date_range,
12
+ period_range,
13
+ )
14
+ import pandas._testing as tm
15
+
16
+
17
+ class TestDataFrameValues:
18
+ @td.skip_array_manager_invalid_test
19
+ def test_values(self, float_frame, using_copy_on_write):
20
+ if using_copy_on_write:
21
+ with pytest.raises(ValueError, match="read-only"):
22
+ float_frame.values[:, 0] = 5.0
23
+ assert (float_frame.values[:, 0] != 5).all()
24
+ else:
25
+ float_frame.values[:, 0] = 5.0
26
+ assert (float_frame.values[:, 0] == 5).all()
27
+
28
+ def test_more_values(self, float_string_frame):
29
+ values = float_string_frame.values
30
+ assert values.shape[1] == len(float_string_frame.columns)
31
+
32
+ def test_values_mixed_dtypes(self, float_frame, float_string_frame):
33
+ frame = float_frame
34
+ arr = frame.values
35
+
36
+ frame_cols = frame.columns
37
+ for i, row in enumerate(arr):
38
+ for j, value in enumerate(row):
39
+ col = frame_cols[j]
40
+ if np.isnan(value):
41
+ assert np.isnan(frame[col].iloc[i])
42
+ else:
43
+ assert value == frame[col].iloc[i]
44
+
45
+ # mixed type
46
+ arr = float_string_frame[["foo", "A"]].values
47
+ assert arr[0, 0] == "bar"
48
+
49
+ df = DataFrame({"complex": [1j, 2j, 3j], "real": [1, 2, 3]})
50
+ arr = df.values
51
+ assert arr[0, 0] == 1j
52
+
53
+ def test_values_duplicates(self):
54
+ df = DataFrame(
55
+ [[1, 2, "a", "b"], [1, 2, "a", "b"]], columns=["one", "one", "two", "two"]
56
+ )
57
+
58
+ result = df.values
59
+ expected = np.array([[1, 2, "a", "b"], [1, 2, "a", "b"]], dtype=object)
60
+
61
+ tm.assert_numpy_array_equal(result, expected)
62
+
63
+ def test_values_with_duplicate_columns(self):
64
+ df = DataFrame([[1, 2.5], [3, 4.5]], index=[1, 2], columns=["x", "x"])
65
+ result = df.values
66
+ expected = np.array([[1, 2.5], [3, 4.5]])
67
+ assert (result == expected).all().all()
68
+
69
+ @pytest.mark.parametrize("constructor", [date_range, period_range])
70
+ def test_values_casts_datetimelike_to_object(self, constructor):
71
+ series = Series(constructor("2000-01-01", periods=10, freq="D"))
72
+
73
+ expected = series.astype("object")
74
+
75
+ df = DataFrame(
76
+ {"a": series, "b": np.random.default_rng(2).standard_normal(len(series))}
77
+ )
78
+
79
+ result = df.values.squeeze()
80
+ assert (result[:, 0] == expected.values).all()
81
+
82
+ df = DataFrame({"a": series, "b": ["foo"] * len(series)})
83
+
84
+ result = df.values.squeeze()
85
+ assert (result[:, 0] == expected.values).all()
86
+
87
+ def test_frame_values_with_tz(self):
88
+ tz = "US/Central"
89
+ df = DataFrame({"A": date_range("2000", periods=4, tz=tz)})
90
+ result = df.values
91
+ expected = np.array(
92
+ [
93
+ [Timestamp("2000-01-01", tz=tz)],
94
+ [Timestamp("2000-01-02", tz=tz)],
95
+ [Timestamp("2000-01-03", tz=tz)],
96
+ [Timestamp("2000-01-04", tz=tz)],
97
+ ]
98
+ )
99
+ tm.assert_numpy_array_equal(result, expected)
100
+
101
+ # two columns, homogeneous
102
+
103
+ df["B"] = df["A"]
104
+ result = df.values
105
+ expected = np.concatenate([expected, expected], axis=1)
106
+ tm.assert_numpy_array_equal(result, expected)
107
+
108
+ # three columns, heterogeneous
109
+ est = "US/Eastern"
110
+ df["C"] = df["A"].dt.tz_convert(est)
111
+
112
+ new = np.array(
113
+ [
114
+ [Timestamp("2000-01-01T01:00:00", tz=est)],
115
+ [Timestamp("2000-01-02T01:00:00", tz=est)],
116
+ [Timestamp("2000-01-03T01:00:00", tz=est)],
117
+ [Timestamp("2000-01-04T01:00:00", tz=est)],
118
+ ]
119
+ )
120
+ expected = np.concatenate([expected, new], axis=1)
121
+ result = df.values
122
+ tm.assert_numpy_array_equal(result, expected)
123
+
124
+ def test_interleave_with_tzaware(self, timezone_frame):
125
+ # interleave with object
126
+ result = timezone_frame.assign(D="foo").values
127
+ expected = np.array(
128
+ [
129
+ [
130
+ Timestamp("2013-01-01 00:00:00"),
131
+ Timestamp("2013-01-02 00:00:00"),
132
+ Timestamp("2013-01-03 00:00:00"),
133
+ ],
134
+ [
135
+ Timestamp("2013-01-01 00:00:00-0500", tz="US/Eastern"),
136
+ NaT,
137
+ Timestamp("2013-01-03 00:00:00-0500", tz="US/Eastern"),
138
+ ],
139
+ [
140
+ Timestamp("2013-01-01 00:00:00+0100", tz="CET"),
141
+ NaT,
142
+ Timestamp("2013-01-03 00:00:00+0100", tz="CET"),
143
+ ],
144
+ ["foo", "foo", "foo"],
145
+ ],
146
+ dtype=object,
147
+ ).T
148
+ tm.assert_numpy_array_equal(result, expected)
149
+
150
+ # interleave with only datetime64[ns]
151
+ result = timezone_frame.values
152
+ expected = np.array(
153
+ [
154
+ [
155
+ Timestamp("2013-01-01 00:00:00"),
156
+ Timestamp("2013-01-02 00:00:00"),
157
+ Timestamp("2013-01-03 00:00:00"),
158
+ ],
159
+ [
160
+ Timestamp("2013-01-01 00:00:00-0500", tz="US/Eastern"),
161
+ NaT,
162
+ Timestamp("2013-01-03 00:00:00-0500", tz="US/Eastern"),
163
+ ],
164
+ [
165
+ Timestamp("2013-01-01 00:00:00+0100", tz="CET"),
166
+ NaT,
167
+ Timestamp("2013-01-03 00:00:00+0100", tz="CET"),
168
+ ],
169
+ ],
170
+ dtype=object,
171
+ ).T
172
+ tm.assert_numpy_array_equal(result, expected)
173
+
174
+ def test_values_interleave_non_unique_cols(self):
175
+ df = DataFrame(
176
+ [[Timestamp("20130101"), 3.5], [Timestamp("20130102"), 4.5]],
177
+ columns=["x", "x"],
178
+ index=[1, 2],
179
+ )
180
+
181
+ df_unique = df.copy()
182
+ df_unique.columns = ["x", "y"]
183
+ assert df_unique.values.shape == df.values.shape
184
+ tm.assert_numpy_array_equal(df_unique.values[0], df.values[0])
185
+ tm.assert_numpy_array_equal(df_unique.values[1], df.values[1])
186
+
187
+ def test_values_numeric_cols(self, float_frame):
188
+ float_frame["foo"] = "bar"
189
+
190
+ values = float_frame[["A", "B", "C", "D"]].values
191
+ assert values.dtype == np.float64
192
+
193
+ def test_values_lcd(self, mixed_float_frame, mixed_int_frame):
194
+ # mixed lcd
195
+ values = mixed_float_frame[["A", "B", "C", "D"]].values
196
+ assert values.dtype == np.float64
197
+
198
+ values = mixed_float_frame[["A", "B", "C"]].values
199
+ assert values.dtype == np.float32
200
+
201
+ values = mixed_float_frame[["C"]].values
202
+ assert values.dtype == np.float16
203
+
204
+ # GH#10364
205
+ # B uint64 forces float because there are other signed int types
206
+ values = mixed_int_frame[["A", "B", "C", "D"]].values
207
+ assert values.dtype == np.float64
208
+
209
+ values = mixed_int_frame[["A", "D"]].values
210
+ assert values.dtype == np.int64
211
+
212
+ # B uint64 forces float because there are other signed int types
213
+ values = mixed_int_frame[["A", "B", "C"]].values
214
+ assert values.dtype == np.float64
215
+
216
+ # as B and C are both unsigned, no forcing to float is needed
217
+ values = mixed_int_frame[["B", "C"]].values
218
+ assert values.dtype == np.uint64
219
+
220
+ values = mixed_int_frame[["A", "C"]].values
221
+ assert values.dtype == np.int32
222
+
223
+ values = mixed_int_frame[["C", "D"]].values
224
+ assert values.dtype == np.int64
225
+
226
+ values = mixed_int_frame[["A"]].values
227
+ assert values.dtype == np.int32
228
+
229
+ values = mixed_int_frame[["C"]].values
230
+ assert values.dtype == np.uint8
231
+
232
+
233
+ class TestPrivateValues:
234
+ @td.skip_array_manager_invalid_test
235
+ def test_private_values_dt64tz(self, using_copy_on_write):
236
+ dta = date_range("2000", periods=4, tz="US/Central")._data.reshape(-1, 1)
237
+
238
+ df = DataFrame(dta, columns=["A"])
239
+ tm.assert_equal(df._values, dta)
240
+
241
+ if using_copy_on_write:
242
+ assert not np.shares_memory(df._values._ndarray, dta._ndarray)
243
+ else:
244
+ # we have a view
245
+ assert np.shares_memory(df._values._ndarray, dta._ndarray)
246
+
247
+ # TimedeltaArray
248
+ tda = dta - dta
249
+ df2 = df - df
250
+ tm.assert_equal(df2._values, tda)
251
+
252
+ @td.skip_array_manager_invalid_test
253
+ def test_private_values_dt64tz_multicol(self, using_copy_on_write):
254
+ dta = date_range("2000", periods=8, tz="US/Central")._data.reshape(-1, 2)
255
+
256
+ df = DataFrame(dta, columns=["A", "B"])
257
+ tm.assert_equal(df._values, dta)
258
+
259
+ if using_copy_on_write:
260
+ assert not np.shares_memory(df._values._ndarray, dta._ndarray)
261
+ else:
262
+ # we have a view
263
+ assert np.shares_memory(df._values._ndarray, dta._ndarray)
264
+
265
+ # TimedeltaArray
266
+ tda = dta - dta
267
+ df2 = df - df
268
+ tm.assert_equal(df2._values, tda)
269
+
270
+ def test_private_values_dt64_multiblock(self):
271
+ dta = date_range("2000", periods=8)._data
272
+
273
+ df = DataFrame({"A": dta[:4]}, copy=False)
274
+ df["B"] = dta[4:]
275
+
276
+ assert len(df._mgr.arrays) == 2
277
+
278
+ result = df._values
279
+ expected = dta.reshape(2, 4).T
280
+ tm.assert_equal(result, expected)
py311/lib/python3.11/site-packages/pandas/tests/scalar/interval/test_arithmetic.py ADDED
@@ -0,0 +1,192 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from datetime import timedelta
2
+
3
+ import numpy as np
4
+ import pytest
5
+
6
+ from pandas import (
7
+ Interval,
8
+ Timedelta,
9
+ Timestamp,
10
+ )
11
+ import pandas._testing as tm
12
+
13
+
14
+ class TestIntervalArithmetic:
15
+ def test_interval_add(self, closed):
16
+ interval = Interval(0, 1, closed=closed)
17
+ expected = Interval(1, 2, closed=closed)
18
+
19
+ result = interval + 1
20
+ assert result == expected
21
+
22
+ result = 1 + interval
23
+ assert result == expected
24
+
25
+ result = interval
26
+ result += 1
27
+ assert result == expected
28
+
29
+ msg = r"unsupported operand type\(s\) for \+"
30
+ with pytest.raises(TypeError, match=msg):
31
+ interval + interval
32
+
33
+ with pytest.raises(TypeError, match=msg):
34
+ interval + "foo"
35
+
36
+ def test_interval_sub(self, closed):
37
+ interval = Interval(0, 1, closed=closed)
38
+ expected = Interval(-1, 0, closed=closed)
39
+
40
+ result = interval - 1
41
+ assert result == expected
42
+
43
+ result = interval
44
+ result -= 1
45
+ assert result == expected
46
+
47
+ msg = r"unsupported operand type\(s\) for -"
48
+ with pytest.raises(TypeError, match=msg):
49
+ interval - interval
50
+
51
+ with pytest.raises(TypeError, match=msg):
52
+ interval - "foo"
53
+
54
+ def test_interval_mult(self, closed):
55
+ interval = Interval(0, 1, closed=closed)
56
+ expected = Interval(0, 2, closed=closed)
57
+
58
+ result = interval * 2
59
+ assert result == expected
60
+
61
+ result = 2 * interval
62
+ assert result == expected
63
+
64
+ result = interval
65
+ result *= 2
66
+ assert result == expected
67
+
68
+ msg = r"unsupported operand type\(s\) for \*"
69
+ with pytest.raises(TypeError, match=msg):
70
+ interval * interval
71
+
72
+ msg = r"can\'t multiply sequence by non-int"
73
+ with pytest.raises(TypeError, match=msg):
74
+ interval * "foo"
75
+
76
+ def test_interval_div(self, closed):
77
+ interval = Interval(0, 1, closed=closed)
78
+ expected = Interval(0, 0.5, closed=closed)
79
+
80
+ result = interval / 2.0
81
+ assert result == expected
82
+
83
+ result = interval
84
+ result /= 2.0
85
+ assert result == expected
86
+
87
+ msg = r"unsupported operand type\(s\) for /"
88
+ with pytest.raises(TypeError, match=msg):
89
+ interval / interval
90
+
91
+ with pytest.raises(TypeError, match=msg):
92
+ interval / "foo"
93
+
94
+ def test_interval_floordiv(self, closed):
95
+ interval = Interval(1, 2, closed=closed)
96
+ expected = Interval(0, 1, closed=closed)
97
+
98
+ result = interval // 2
99
+ assert result == expected
100
+
101
+ result = interval
102
+ result //= 2
103
+ assert result == expected
104
+
105
+ msg = r"unsupported operand type\(s\) for //"
106
+ with pytest.raises(TypeError, match=msg):
107
+ interval // interval
108
+
109
+ with pytest.raises(TypeError, match=msg):
110
+ interval // "foo"
111
+
112
+ @pytest.mark.parametrize("method", ["__add__", "__sub__"])
113
+ @pytest.mark.parametrize(
114
+ "interval",
115
+ [
116
+ Interval(
117
+ Timestamp("2017-01-01 00:00:00"), Timestamp("2018-01-01 00:00:00")
118
+ ),
119
+ Interval(Timedelta(days=7), Timedelta(days=14)),
120
+ ],
121
+ )
122
+ @pytest.mark.parametrize(
123
+ "delta", [Timedelta(days=7), timedelta(7), np.timedelta64(7, "D")]
124
+ )
125
+ def test_time_interval_add_subtract_timedelta(self, interval, delta, method):
126
+ # https://github.com/pandas-dev/pandas/issues/32023
127
+ result = getattr(interval, method)(delta)
128
+ left = getattr(interval.left, method)(delta)
129
+ right = getattr(interval.right, method)(delta)
130
+ expected = Interval(left, right)
131
+
132
+ assert result == expected
133
+
134
+ @pytest.mark.parametrize("interval", [Interval(1, 2), Interval(1.0, 2.0)])
135
+ @pytest.mark.parametrize(
136
+ "delta", [Timedelta(days=7), timedelta(7), np.timedelta64(7, "D")]
137
+ )
138
+ def test_numeric_interval_add_timedelta_raises(self, interval, delta):
139
+ # https://github.com/pandas-dev/pandas/issues/32023
140
+ msg = "|".join(
141
+ [
142
+ "unsupported operand",
143
+ "cannot use operands",
144
+ "Only numeric, Timestamp and Timedelta endpoints are allowed",
145
+ ]
146
+ )
147
+ with pytest.raises((TypeError, ValueError), match=msg):
148
+ interval + delta
149
+
150
+ with pytest.raises((TypeError, ValueError), match=msg):
151
+ delta + interval
152
+
153
+ @pytest.mark.parametrize("klass", [timedelta, np.timedelta64, Timedelta])
154
+ def test_timedelta_add_timestamp_interval(self, klass):
155
+ delta = klass(0)
156
+ expected = Interval(Timestamp("2020-01-01"), Timestamp("2020-02-01"))
157
+
158
+ result = delta + expected
159
+ assert result == expected
160
+
161
+ result = expected + delta
162
+ assert result == expected
163
+
164
+
165
+ class TestIntervalComparisons:
166
+ def test_interval_equal(self):
167
+ assert Interval(0, 1) == Interval(0, 1, closed="right")
168
+ assert Interval(0, 1) != Interval(0, 1, closed="left")
169
+ assert Interval(0, 1) != 0
170
+
171
+ def test_interval_comparison(self):
172
+ msg = (
173
+ "'<' not supported between instances of "
174
+ "'pandas._libs.interval.Interval' and 'int'"
175
+ )
176
+ with pytest.raises(TypeError, match=msg):
177
+ Interval(0, 1) < 2
178
+
179
+ assert Interval(0, 1) < Interval(1, 2)
180
+ assert Interval(0, 1) < Interval(0, 2)
181
+ assert Interval(0, 1) < Interval(0.5, 1.5)
182
+ assert Interval(0, 1) <= Interval(0, 1)
183
+ assert Interval(0, 1) > Interval(-1, 2)
184
+ assert Interval(0, 1) >= Interval(0, 1)
185
+
186
+ def test_equality_comparison_broadcasts_over_array(self):
187
+ # https://github.com/pandas-dev/pandas/issues/35931
188
+ interval = Interval(0, 1)
189
+ arr = np.array([interval, interval])
190
+ result = interval == arr
191
+ expected = np.array([True, True])
192
+ tm.assert_numpy_array_equal(result, expected)
py311/lib/python3.11/site-packages/pandas/tests/scalar/period/__init__.py ADDED
File without changes
py311/lib/python3.11/site-packages/pandas/tests/scalar/period/test_arithmetic.py ADDED
@@ -0,0 +1,486 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from datetime import timedelta
2
+
3
+ import numpy as np
4
+ import pytest
5
+
6
+ from pandas._libs.tslibs.period import IncompatibleFrequency
7
+
8
+ from pandas import (
9
+ NaT,
10
+ Period,
11
+ Timedelta,
12
+ Timestamp,
13
+ offsets,
14
+ )
15
+
16
+
17
+ class TestPeriodArithmetic:
18
+ def test_add_overflow_raises(self):
19
+ # GH#55503
20
+ per = Timestamp.max.to_period("ns")
21
+
22
+ msg = "|".join(
23
+ [
24
+ "Python int too large to convert to C long",
25
+ # windows, 32bit linux builds
26
+ "int too big to convert",
27
+ ]
28
+ )
29
+ with pytest.raises(OverflowError, match=msg):
30
+ per + 1
31
+
32
+ msg = "value too large"
33
+ with pytest.raises(OverflowError, match=msg):
34
+ per + Timedelta(1)
35
+ with pytest.raises(OverflowError, match=msg):
36
+ per + offsets.Nano(1)
37
+
38
+ def test_period_add_integer(self):
39
+ per1 = Period(freq="D", year=2008, month=1, day=1)
40
+ per2 = Period(freq="D", year=2008, month=1, day=2)
41
+ assert per1 + 1 == per2
42
+ assert 1 + per1 == per2
43
+
44
+ def test_period_add_invalid(self):
45
+ # GH#4731
46
+ per1 = Period(freq="D", year=2008, month=1, day=1)
47
+ per2 = Period(freq="D", year=2008, month=1, day=2)
48
+
49
+ msg = "|".join(
50
+ [
51
+ r"unsupported operand type\(s\)",
52
+ "can only concatenate str",
53
+ "must be str, not Period",
54
+ ]
55
+ )
56
+ with pytest.raises(TypeError, match=msg):
57
+ per1 + "str"
58
+ with pytest.raises(TypeError, match=msg):
59
+ "str" + per1
60
+ with pytest.raises(TypeError, match=msg):
61
+ per1 + per2
62
+
63
+ def test_period_sub_period_annual(self):
64
+ left, right = Period("2011", freq="Y"), Period("2007", freq="Y")
65
+ result = left - right
66
+ assert result == 4 * right.freq
67
+
68
+ msg = r"Input has different freq=M from Period\(freq=Y-DEC\)"
69
+ with pytest.raises(IncompatibleFrequency, match=msg):
70
+ left - Period("2007-01", freq="M")
71
+
72
+ def test_period_sub_period(self):
73
+ per1 = Period("2011-01-01", freq="D")
74
+ per2 = Period("2011-01-15", freq="D")
75
+
76
+ off = per1.freq
77
+ assert per1 - per2 == -14 * off
78
+ assert per2 - per1 == 14 * off
79
+
80
+ msg = r"Input has different freq=M from Period\(freq=D\)"
81
+ with pytest.raises(IncompatibleFrequency, match=msg):
82
+ per1 - Period("2011-02", freq="M")
83
+
84
+ @pytest.mark.parametrize("n", [1, 2, 3, 4])
85
+ def test_sub_n_gt_1_ticks(self, tick_classes, n):
86
+ # GH#23878
87
+ p1 = Period("19910905", freq=tick_classes(n))
88
+ p2 = Period("19920406", freq=tick_classes(n))
89
+
90
+ expected = Period(str(p2), freq=p2.freq.base) - Period(
91
+ str(p1), freq=p1.freq.base
92
+ )
93
+
94
+ assert (p2 - p1) == expected
95
+
96
+ @pytest.mark.parametrize("normalize", [True, False])
97
+ @pytest.mark.parametrize("n", [1, 2, 3, 4])
98
+ @pytest.mark.parametrize(
99
+ "offset, kwd_name",
100
+ [
101
+ (offsets.YearEnd, "month"),
102
+ (offsets.QuarterEnd, "startingMonth"),
103
+ (offsets.MonthEnd, None),
104
+ (offsets.Week, "weekday"),
105
+ ],
106
+ )
107
+ def test_sub_n_gt_1_offsets(self, offset, kwd_name, n, normalize):
108
+ # GH#23878
109
+ kwds = {kwd_name: 3} if kwd_name is not None else {}
110
+ p1_d = "19910905"
111
+ p2_d = "19920406"
112
+ p1 = Period(p1_d, freq=offset(n, normalize, **kwds))
113
+ p2 = Period(p2_d, freq=offset(n, normalize, **kwds))
114
+
115
+ expected = Period(p2_d, freq=p2.freq.base) - Period(p1_d, freq=p1.freq.base)
116
+
117
+ assert (p2 - p1) == expected
118
+
119
+ def test_period_add_offset(self):
120
+ # freq is DateOffset
121
+ for freq in ["Y", "2Y", "3Y"]:
122
+ per = Period("2011", freq=freq)
123
+ exp = Period("2013", freq=freq)
124
+ assert per + offsets.YearEnd(2) == exp
125
+ assert offsets.YearEnd(2) + per == exp
126
+
127
+ for off in [
128
+ offsets.YearBegin(2),
129
+ offsets.MonthBegin(1),
130
+ offsets.Minute(),
131
+ np.timedelta64(365, "D"),
132
+ timedelta(365),
133
+ ]:
134
+ msg = "Input has different freq|Input cannot be converted to Period"
135
+ with pytest.raises(IncompatibleFrequency, match=msg):
136
+ per + off
137
+ with pytest.raises(IncompatibleFrequency, match=msg):
138
+ off + per
139
+
140
+ for freq in ["M", "2M", "3M"]:
141
+ per = Period("2011-03", freq=freq)
142
+ exp = Period("2011-05", freq=freq)
143
+ assert per + offsets.MonthEnd(2) == exp
144
+ assert offsets.MonthEnd(2) + per == exp
145
+
146
+ exp = Period("2012-03", freq=freq)
147
+ assert per + offsets.MonthEnd(12) == exp
148
+ assert offsets.MonthEnd(12) + per == exp
149
+
150
+ msg = "|".join(
151
+ [
152
+ "Input has different freq",
153
+ "Input cannot be converted to Period",
154
+ ]
155
+ )
156
+
157
+ for off in [
158
+ offsets.YearBegin(2),
159
+ offsets.MonthBegin(1),
160
+ offsets.Minute(),
161
+ np.timedelta64(365, "D"),
162
+ timedelta(365),
163
+ ]:
164
+ with pytest.raises(IncompatibleFrequency, match=msg):
165
+ per + off
166
+ with pytest.raises(IncompatibleFrequency, match=msg):
167
+ off + per
168
+
169
+ # freq is Tick
170
+ for freq in ["D", "2D", "3D"]:
171
+ per = Period("2011-04-01", freq=freq)
172
+
173
+ exp = Period("2011-04-06", freq=freq)
174
+ assert per + offsets.Day(5) == exp
175
+ assert offsets.Day(5) + per == exp
176
+
177
+ exp = Period("2011-04-02", freq=freq)
178
+ assert per + offsets.Hour(24) == exp
179
+ assert offsets.Hour(24) + per == exp
180
+
181
+ exp = Period("2011-04-03", freq=freq)
182
+ assert per + np.timedelta64(2, "D") == exp
183
+ assert np.timedelta64(2, "D") + per == exp
184
+
185
+ exp = Period("2011-04-02", freq=freq)
186
+ assert per + np.timedelta64(3600 * 24, "s") == exp
187
+ assert np.timedelta64(3600 * 24, "s") + per == exp
188
+
189
+ exp = Period("2011-03-30", freq=freq)
190
+ assert per + timedelta(-2) == exp
191
+ assert timedelta(-2) + per == exp
192
+
193
+ exp = Period("2011-04-03", freq=freq)
194
+ assert per + timedelta(hours=48) == exp
195
+ assert timedelta(hours=48) + per == exp
196
+
197
+ msg = "|".join(
198
+ [
199
+ "Input has different freq",
200
+ "Input cannot be converted to Period",
201
+ ]
202
+ )
203
+
204
+ for off in [
205
+ offsets.YearBegin(2),
206
+ offsets.MonthBegin(1),
207
+ offsets.Minute(),
208
+ np.timedelta64(4, "h"),
209
+ timedelta(hours=23),
210
+ ]:
211
+ with pytest.raises(IncompatibleFrequency, match=msg):
212
+ per + off
213
+ with pytest.raises(IncompatibleFrequency, match=msg):
214
+ off + per
215
+
216
+ for freq in ["h", "2h", "3h"]:
217
+ per = Period("2011-04-01 09:00", freq=freq)
218
+
219
+ exp = Period("2011-04-03 09:00", freq=freq)
220
+ assert per + offsets.Day(2) == exp
221
+ assert offsets.Day(2) + per == exp
222
+
223
+ exp = Period("2011-04-01 12:00", freq=freq)
224
+ assert per + offsets.Hour(3) == exp
225
+ assert offsets.Hour(3) + per == exp
226
+
227
+ msg = "cannot use operands with types"
228
+ exp = Period("2011-04-01 12:00", freq=freq)
229
+ assert per + np.timedelta64(3, "h") == exp
230
+ assert np.timedelta64(3, "h") + per == exp
231
+
232
+ exp = Period("2011-04-01 10:00", freq=freq)
233
+ assert per + np.timedelta64(3600, "s") == exp
234
+ assert np.timedelta64(3600, "s") + per == exp
235
+
236
+ exp = Period("2011-04-01 11:00", freq=freq)
237
+ assert per + timedelta(minutes=120) == exp
238
+ assert timedelta(minutes=120) + per == exp
239
+
240
+ exp = Period("2011-04-05 12:00", freq=freq)
241
+ assert per + timedelta(days=4, minutes=180) == exp
242
+ assert timedelta(days=4, minutes=180) + per == exp
243
+
244
+ msg = "|".join(
245
+ [
246
+ "Input has different freq",
247
+ "Input cannot be converted to Period",
248
+ ]
249
+ )
250
+
251
+ for off in [
252
+ offsets.YearBegin(2),
253
+ offsets.MonthBegin(1),
254
+ offsets.Minute(),
255
+ np.timedelta64(3200, "s"),
256
+ timedelta(hours=23, minutes=30),
257
+ ]:
258
+ with pytest.raises(IncompatibleFrequency, match=msg):
259
+ per + off
260
+ with pytest.raises(IncompatibleFrequency, match=msg):
261
+ off + per
262
+
263
+ def test_period_sub_offset(self):
264
+ # freq is DateOffset
265
+ msg = "|".join(
266
+ [
267
+ "Input has different freq",
268
+ "Input cannot be converted to Period",
269
+ ]
270
+ )
271
+
272
+ for freq in ["Y", "2Y", "3Y"]:
273
+ per = Period("2011", freq=freq)
274
+ assert per - offsets.YearEnd(2) == Period("2009", freq=freq)
275
+
276
+ for off in [
277
+ offsets.YearBegin(2),
278
+ offsets.MonthBegin(1),
279
+ offsets.Minute(),
280
+ np.timedelta64(365, "D"),
281
+ timedelta(365),
282
+ ]:
283
+ with pytest.raises(IncompatibleFrequency, match=msg):
284
+ per - off
285
+
286
+ for freq in ["M", "2M", "3M"]:
287
+ per = Period("2011-03", freq=freq)
288
+ assert per - offsets.MonthEnd(2) == Period("2011-01", freq=freq)
289
+ assert per - offsets.MonthEnd(12) == Period("2010-03", freq=freq)
290
+
291
+ for off in [
292
+ offsets.YearBegin(2),
293
+ offsets.MonthBegin(1),
294
+ offsets.Minute(),
295
+ np.timedelta64(365, "D"),
296
+ timedelta(365),
297
+ ]:
298
+ with pytest.raises(IncompatibleFrequency, match=msg):
299
+ per - off
300
+
301
+ # freq is Tick
302
+ for freq in ["D", "2D", "3D"]:
303
+ per = Period("2011-04-01", freq=freq)
304
+ assert per - offsets.Day(5) == Period("2011-03-27", freq=freq)
305
+ assert per - offsets.Hour(24) == Period("2011-03-31", freq=freq)
306
+ assert per - np.timedelta64(2, "D") == Period("2011-03-30", freq=freq)
307
+ assert per - np.timedelta64(3600 * 24, "s") == Period(
308
+ "2011-03-31", freq=freq
309
+ )
310
+ assert per - timedelta(-2) == Period("2011-04-03", freq=freq)
311
+ assert per - timedelta(hours=48) == Period("2011-03-30", freq=freq)
312
+
313
+ for off in [
314
+ offsets.YearBegin(2),
315
+ offsets.MonthBegin(1),
316
+ offsets.Minute(),
317
+ np.timedelta64(4, "h"),
318
+ timedelta(hours=23),
319
+ ]:
320
+ with pytest.raises(IncompatibleFrequency, match=msg):
321
+ per - off
322
+
323
+ for freq in ["h", "2h", "3h"]:
324
+ per = Period("2011-04-01 09:00", freq=freq)
325
+ assert per - offsets.Day(2) == Period("2011-03-30 09:00", freq=freq)
326
+ assert per - offsets.Hour(3) == Period("2011-04-01 06:00", freq=freq)
327
+ assert per - np.timedelta64(3, "h") == Period("2011-04-01 06:00", freq=freq)
328
+ assert per - np.timedelta64(3600, "s") == Period(
329
+ "2011-04-01 08:00", freq=freq
330
+ )
331
+ assert per - timedelta(minutes=120) == Period("2011-04-01 07:00", freq=freq)
332
+ assert per - timedelta(days=4, minutes=180) == Period(
333
+ "2011-03-28 06:00", freq=freq
334
+ )
335
+
336
+ for off in [
337
+ offsets.YearBegin(2),
338
+ offsets.MonthBegin(1),
339
+ offsets.Minute(),
340
+ np.timedelta64(3200, "s"),
341
+ timedelta(hours=23, minutes=30),
342
+ ]:
343
+ with pytest.raises(IncompatibleFrequency, match=msg):
344
+ per - off
345
+
346
+ @pytest.mark.parametrize("freq", ["M", "2M", "3M"])
347
+ def test_period_addsub_nat(self, freq):
348
+ # GH#13071
349
+ per = Period("2011-01", freq=freq)
350
+
351
+ # For subtraction, NaT is treated as another Period object
352
+ assert NaT - per is NaT
353
+ assert per - NaT is NaT
354
+
355
+ # For addition, NaT is treated as offset-like
356
+ assert NaT + per is NaT
357
+ assert per + NaT is NaT
358
+
359
+ @pytest.mark.parametrize("unit", ["ns", "us", "ms", "s", "m"])
360
+ def test_period_add_sub_td64_nat(self, unit):
361
+ # GH#47196
362
+ per = Period("2022-06-01", "D")
363
+ nat = np.timedelta64("NaT", unit)
364
+
365
+ assert per + nat is NaT
366
+ assert nat + per is NaT
367
+ assert per - nat is NaT
368
+
369
+ with pytest.raises(TypeError, match="unsupported operand"):
370
+ nat - per
371
+
372
+ def test_period_ops_offset(self):
373
+ per = Period("2011-04-01", freq="D")
374
+ result = per + offsets.Day()
375
+ exp = Period("2011-04-02", freq="D")
376
+ assert result == exp
377
+
378
+ result = per - offsets.Day(2)
379
+ exp = Period("2011-03-30", freq="D")
380
+ assert result == exp
381
+
382
+ msg = r"Input cannot be converted to Period\(freq=D\)"
383
+ with pytest.raises(IncompatibleFrequency, match=msg):
384
+ per + offsets.Hour(2)
385
+
386
+ with pytest.raises(IncompatibleFrequency, match=msg):
387
+ per - offsets.Hour(2)
388
+
389
+ def test_period_add_timestamp_raises(self):
390
+ # GH#17983
391
+ ts = Timestamp("2017")
392
+ per = Period("2017", freq="M")
393
+
394
+ msg = r"unsupported operand type\(s\) for \+: 'Timestamp' and 'Period'"
395
+ with pytest.raises(TypeError, match=msg):
396
+ ts + per
397
+
398
+ msg = r"unsupported operand type\(s\) for \+: 'Period' and 'Timestamp'"
399
+ with pytest.raises(TypeError, match=msg):
400
+ per + ts
401
+
402
+
403
+ class TestPeriodComparisons:
404
+ def test_period_comparison_same_freq(self):
405
+ jan = Period("2000-01", "M")
406
+ feb = Period("2000-02", "M")
407
+
408
+ assert not jan == feb
409
+ assert jan != feb
410
+ assert jan < feb
411
+ assert jan <= feb
412
+ assert not jan > feb
413
+ assert not jan >= feb
414
+
415
+ def test_period_comparison_same_period_different_object(self):
416
+ # Separate Period objects for the same period
417
+ left = Period("2000-01", "M")
418
+ right = Period("2000-01", "M")
419
+
420
+ assert left == right
421
+ assert left >= right
422
+ assert left <= right
423
+ assert not left < right
424
+ assert not left > right
425
+
426
+ def test_period_comparison_mismatched_freq(self):
427
+ jan = Period("2000-01", "M")
428
+ day = Period("2012-01-01", "D")
429
+
430
+ assert not jan == day
431
+ assert jan != day
432
+ msg = r"Input has different freq=D from Period\(freq=M\)"
433
+ with pytest.raises(IncompatibleFrequency, match=msg):
434
+ jan < day
435
+ with pytest.raises(IncompatibleFrequency, match=msg):
436
+ jan <= day
437
+ with pytest.raises(IncompatibleFrequency, match=msg):
438
+ jan > day
439
+ with pytest.raises(IncompatibleFrequency, match=msg):
440
+ jan >= day
441
+
442
+ def test_period_comparison_invalid_type(self):
443
+ jan = Period("2000-01", "M")
444
+
445
+ assert not jan == 1
446
+ assert jan != 1
447
+
448
+ int_or_per = "'(Period|int)'"
449
+ msg = f"not supported between instances of {int_or_per} and {int_or_per}"
450
+ for left, right in [(jan, 1), (1, jan)]:
451
+ with pytest.raises(TypeError, match=msg):
452
+ left > right
453
+ with pytest.raises(TypeError, match=msg):
454
+ left >= right
455
+ with pytest.raises(TypeError, match=msg):
456
+ left < right
457
+ with pytest.raises(TypeError, match=msg):
458
+ left <= right
459
+
460
+ def test_period_comparison_nat(self):
461
+ per = Period("2011-01-01", freq="D")
462
+
463
+ ts = Timestamp("2011-01-01")
464
+ # confirm Period('NaT') work identical with Timestamp('NaT')
465
+ for left, right in [
466
+ (NaT, per),
467
+ (per, NaT),
468
+ (NaT, ts),
469
+ (ts, NaT),
470
+ ]:
471
+ assert not left < right
472
+ assert not left > right
473
+ assert not left == right
474
+ assert left != right
475
+ assert not left <= right
476
+ assert not left >= right
477
+
478
+ @pytest.mark.parametrize(
479
+ "zerodim_arr, expected",
480
+ ((np.array(0), False), (np.array(Period("2000-01", "M")), True)),
481
+ )
482
+ def test_period_comparison_numpy_zerodim_arr(self, zerodim_arr, expected):
483
+ per = Period("2000-01", "M")
484
+
485
+ assert (per == zerodim_arr) is expected
486
+ assert (zerodim_arr == per) is expected
py311/lib/python3.11/site-packages/pandas/tests/scalar/period/test_asfreq.py ADDED
@@ -0,0 +1,828 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import pytest
2
+
3
+ from pandas._libs.tslibs.period import INVALID_FREQ_ERR_MSG
4
+ from pandas.errors import OutOfBoundsDatetime
5
+
6
+ from pandas import (
7
+ Period,
8
+ Timestamp,
9
+ offsets,
10
+ )
11
+ import pandas._testing as tm
12
+
13
+ bday_msg = "Period with BDay freq is deprecated"
14
+
15
+
16
+ class TestFreqConversion:
17
+ """Test frequency conversion of date objects"""
18
+
19
+ @pytest.mark.filterwarnings("ignore:Period with BDay:FutureWarning")
20
+ @pytest.mark.parametrize("freq", ["Y", "Q", "M", "W", "B", "D"])
21
+ def test_asfreq_near_zero(self, freq):
22
+ # GH#19643, GH#19650
23
+ per = Period("0001-01-01", freq=freq)
24
+ tup1 = (per.year, per.hour, per.day)
25
+
26
+ prev = per - 1
27
+ assert prev.ordinal == per.ordinal - 1
28
+ tup2 = (prev.year, prev.month, prev.day)
29
+ assert tup2 < tup1
30
+
31
+ def test_asfreq_near_zero_weekly(self):
32
+ # GH#19834
33
+ per1 = Period("0001-01-01", "D") + 6
34
+ per2 = Period("0001-01-01", "D") - 6
35
+ week1 = per1.asfreq("W")
36
+ week2 = per2.asfreq("W")
37
+ assert week1 != week2
38
+ assert week1.asfreq("D", "E") >= per1
39
+ assert week2.asfreq("D", "S") <= per2
40
+
41
+ def test_to_timestamp_out_of_bounds(self):
42
+ # GH#19643, used to incorrectly give Timestamp in 1754
43
+ with tm.assert_produces_warning(FutureWarning, match=bday_msg):
44
+ per = Period("0001-01-01", freq="B")
45
+ msg = "Out of bounds nanosecond timestamp"
46
+ with pytest.raises(OutOfBoundsDatetime, match=msg):
47
+ with tm.assert_produces_warning(FutureWarning, match=bday_msg):
48
+ per.to_timestamp()
49
+
50
+ def test_asfreq_corner(self):
51
+ val = Period(freq="Y", year=2007)
52
+ result1 = val.asfreq("5min")
53
+ result2 = val.asfreq("min")
54
+ expected = Period("2007-12-31 23:59", freq="min")
55
+ assert result1.ordinal == expected.ordinal
56
+ assert result1.freqstr == "5min"
57
+ assert result2.ordinal == expected.ordinal
58
+ assert result2.freqstr == "min"
59
+
60
+ def test_conv_annual(self):
61
+ # frequency conversion tests: from Annual Frequency
62
+
63
+ ival_A = Period(freq="Y", year=2007)
64
+
65
+ ival_AJAN = Period(freq="Y-JAN", year=2007)
66
+ ival_AJUN = Period(freq="Y-JUN", year=2007)
67
+ ival_ANOV = Period(freq="Y-NOV", year=2007)
68
+
69
+ ival_A_to_Q_start = Period(freq="Q", year=2007, quarter=1)
70
+ ival_A_to_Q_end = Period(freq="Q", year=2007, quarter=4)
71
+ ival_A_to_M_start = Period(freq="M", year=2007, month=1)
72
+ ival_A_to_M_end = Period(freq="M", year=2007, month=12)
73
+ ival_A_to_W_start = Period(freq="W", year=2007, month=1, day=1)
74
+ ival_A_to_W_end = Period(freq="W", year=2007, month=12, day=31)
75
+ with tm.assert_produces_warning(FutureWarning, match=bday_msg):
76
+ ival_A_to_B_start = Period(freq="B", year=2007, month=1, day=1)
77
+ ival_A_to_B_end = Period(freq="B", year=2007, month=12, day=31)
78
+ ival_A_to_D_start = Period(freq="D", year=2007, month=1, day=1)
79
+ ival_A_to_D_end = Period(freq="D", year=2007, month=12, day=31)
80
+ ival_A_to_H_start = Period(freq="h", year=2007, month=1, day=1, hour=0)
81
+ ival_A_to_H_end = Period(freq="h", year=2007, month=12, day=31, hour=23)
82
+ ival_A_to_T_start = Period(
83
+ freq="Min", year=2007, month=1, day=1, hour=0, minute=0
84
+ )
85
+ ival_A_to_T_end = Period(
86
+ freq="Min", year=2007, month=12, day=31, hour=23, minute=59
87
+ )
88
+ ival_A_to_S_start = Period(
89
+ freq="s", year=2007, month=1, day=1, hour=0, minute=0, second=0
90
+ )
91
+ ival_A_to_S_end = Period(
92
+ freq="s", year=2007, month=12, day=31, hour=23, minute=59, second=59
93
+ )
94
+
95
+ ival_AJAN_to_D_end = Period(freq="D", year=2007, month=1, day=31)
96
+ ival_AJAN_to_D_start = Period(freq="D", year=2006, month=2, day=1)
97
+ ival_AJUN_to_D_end = Period(freq="D", year=2007, month=6, day=30)
98
+ ival_AJUN_to_D_start = Period(freq="D", year=2006, month=7, day=1)
99
+ ival_ANOV_to_D_end = Period(freq="D", year=2007, month=11, day=30)
100
+ ival_ANOV_to_D_start = Period(freq="D", year=2006, month=12, day=1)
101
+
102
+ assert ival_A.asfreq("Q", "s") == ival_A_to_Q_start
103
+ assert ival_A.asfreq("Q", "e") == ival_A_to_Q_end
104
+ assert ival_A.asfreq("M", "s") == ival_A_to_M_start
105
+ assert ival_A.asfreq("M", "E") == ival_A_to_M_end
106
+ assert ival_A.asfreq("W", "s") == ival_A_to_W_start
107
+ assert ival_A.asfreq("W", "E") == ival_A_to_W_end
108
+ with tm.assert_produces_warning(FutureWarning, match=bday_msg):
109
+ assert ival_A.asfreq("B", "s") == ival_A_to_B_start
110
+ assert ival_A.asfreq("B", "E") == ival_A_to_B_end
111
+ assert ival_A.asfreq("D", "s") == ival_A_to_D_start
112
+ assert ival_A.asfreq("D", "E") == ival_A_to_D_end
113
+ msg = "'H' is deprecated and will be removed in a future version."
114
+ with tm.assert_produces_warning(FutureWarning, match=msg):
115
+ assert ival_A.asfreq("H", "s") == ival_A_to_H_start
116
+ assert ival_A.asfreq("H", "E") == ival_A_to_H_end
117
+ assert ival_A.asfreq("min", "s") == ival_A_to_T_start
118
+ assert ival_A.asfreq("min", "E") == ival_A_to_T_end
119
+ msg = "'T' is deprecated and will be removed in a future version."
120
+ with tm.assert_produces_warning(FutureWarning, match=msg):
121
+ assert ival_A.asfreq("T", "s") == ival_A_to_T_start
122
+ assert ival_A.asfreq("T", "E") == ival_A_to_T_end
123
+ msg = "'S' is deprecated and will be removed in a future version."
124
+ with tm.assert_produces_warning(FutureWarning, match=msg):
125
+ assert ival_A.asfreq("S", "S") == ival_A_to_S_start
126
+ assert ival_A.asfreq("S", "E") == ival_A_to_S_end
127
+
128
+ assert ival_AJAN.asfreq("D", "s") == ival_AJAN_to_D_start
129
+ assert ival_AJAN.asfreq("D", "E") == ival_AJAN_to_D_end
130
+
131
+ assert ival_AJUN.asfreq("D", "s") == ival_AJUN_to_D_start
132
+ assert ival_AJUN.asfreq("D", "E") == ival_AJUN_to_D_end
133
+
134
+ assert ival_ANOV.asfreq("D", "s") == ival_ANOV_to_D_start
135
+ assert ival_ANOV.asfreq("D", "E") == ival_ANOV_to_D_end
136
+
137
+ assert ival_A.asfreq("Y") == ival_A
138
+
139
+ def test_conv_quarterly(self):
140
+ # frequency conversion tests: from Quarterly Frequency
141
+
142
+ ival_Q = Period(freq="Q", year=2007, quarter=1)
143
+ ival_Q_end_of_year = Period(freq="Q", year=2007, quarter=4)
144
+
145
+ ival_QEJAN = Period(freq="Q-JAN", year=2007, quarter=1)
146
+ ival_QEJUN = Period(freq="Q-JUN", year=2007, quarter=1)
147
+
148
+ ival_Q_to_A = Period(freq="Y", year=2007)
149
+ ival_Q_to_M_start = Period(freq="M", year=2007, month=1)
150
+ ival_Q_to_M_end = Period(freq="M", year=2007, month=3)
151
+ ival_Q_to_W_start = Period(freq="W", year=2007, month=1, day=1)
152
+ ival_Q_to_W_end = Period(freq="W", year=2007, month=3, day=31)
153
+ with tm.assert_produces_warning(FutureWarning, match=bday_msg):
154
+ ival_Q_to_B_start = Period(freq="B", year=2007, month=1, day=1)
155
+ ival_Q_to_B_end = Period(freq="B", year=2007, month=3, day=30)
156
+ ival_Q_to_D_start = Period(freq="D", year=2007, month=1, day=1)
157
+ ival_Q_to_D_end = Period(freq="D", year=2007, month=3, day=31)
158
+ ival_Q_to_H_start = Period(freq="h", year=2007, month=1, day=1, hour=0)
159
+ ival_Q_to_H_end = Period(freq="h", year=2007, month=3, day=31, hour=23)
160
+ ival_Q_to_T_start = Period(
161
+ freq="Min", year=2007, month=1, day=1, hour=0, minute=0
162
+ )
163
+ ival_Q_to_T_end = Period(
164
+ freq="Min", year=2007, month=3, day=31, hour=23, minute=59
165
+ )
166
+ ival_Q_to_S_start = Period(
167
+ freq="s", year=2007, month=1, day=1, hour=0, minute=0, second=0
168
+ )
169
+ ival_Q_to_S_end = Period(
170
+ freq="s", year=2007, month=3, day=31, hour=23, minute=59, second=59
171
+ )
172
+
173
+ ival_QEJAN_to_D_start = Period(freq="D", year=2006, month=2, day=1)
174
+ ival_QEJAN_to_D_end = Period(freq="D", year=2006, month=4, day=30)
175
+
176
+ ival_QEJUN_to_D_start = Period(freq="D", year=2006, month=7, day=1)
177
+ ival_QEJUN_to_D_end = Period(freq="D", year=2006, month=9, day=30)
178
+
179
+ assert ival_Q.asfreq("Y") == ival_Q_to_A
180
+ assert ival_Q_end_of_year.asfreq("Y") == ival_Q_to_A
181
+
182
+ assert ival_Q.asfreq("M", "s") == ival_Q_to_M_start
183
+ assert ival_Q.asfreq("M", "E") == ival_Q_to_M_end
184
+ assert ival_Q.asfreq("W", "s") == ival_Q_to_W_start
185
+ assert ival_Q.asfreq("W", "E") == ival_Q_to_W_end
186
+ with tm.assert_produces_warning(FutureWarning, match=bday_msg):
187
+ assert ival_Q.asfreq("B", "s") == ival_Q_to_B_start
188
+ assert ival_Q.asfreq("B", "E") == ival_Q_to_B_end
189
+ assert ival_Q.asfreq("D", "s") == ival_Q_to_D_start
190
+ assert ival_Q.asfreq("D", "E") == ival_Q_to_D_end
191
+ assert ival_Q.asfreq("h", "s") == ival_Q_to_H_start
192
+ assert ival_Q.asfreq("h", "E") == ival_Q_to_H_end
193
+ assert ival_Q.asfreq("Min", "s") == ival_Q_to_T_start
194
+ assert ival_Q.asfreq("Min", "E") == ival_Q_to_T_end
195
+ assert ival_Q.asfreq("s", "s") == ival_Q_to_S_start
196
+ assert ival_Q.asfreq("s", "E") == ival_Q_to_S_end
197
+
198
+ assert ival_QEJAN.asfreq("D", "s") == ival_QEJAN_to_D_start
199
+ assert ival_QEJAN.asfreq("D", "E") == ival_QEJAN_to_D_end
200
+ assert ival_QEJUN.asfreq("D", "s") == ival_QEJUN_to_D_start
201
+ assert ival_QEJUN.asfreq("D", "E") == ival_QEJUN_to_D_end
202
+
203
+ assert ival_Q.asfreq("Q") == ival_Q
204
+
205
+ def test_conv_monthly(self):
206
+ # frequency conversion tests: from Monthly Frequency
207
+
208
+ ival_M = Period(freq="M", year=2007, month=1)
209
+ ival_M_end_of_year = Period(freq="M", year=2007, month=12)
210
+ ival_M_end_of_quarter = Period(freq="M", year=2007, month=3)
211
+ ival_M_to_A = Period(freq="Y", year=2007)
212
+ ival_M_to_Q = Period(freq="Q", year=2007, quarter=1)
213
+ ival_M_to_W_start = Period(freq="W", year=2007, month=1, day=1)
214
+ ival_M_to_W_end = Period(freq="W", year=2007, month=1, day=31)
215
+ with tm.assert_produces_warning(FutureWarning, match=bday_msg):
216
+ ival_M_to_B_start = Period(freq="B", year=2007, month=1, day=1)
217
+ ival_M_to_B_end = Period(freq="B", year=2007, month=1, day=31)
218
+ ival_M_to_D_start = Period(freq="D", year=2007, month=1, day=1)
219
+ ival_M_to_D_end = Period(freq="D", year=2007, month=1, day=31)
220
+ ival_M_to_H_start = Period(freq="h", year=2007, month=1, day=1, hour=0)
221
+ ival_M_to_H_end = Period(freq="h", year=2007, month=1, day=31, hour=23)
222
+ ival_M_to_T_start = Period(
223
+ freq="Min", year=2007, month=1, day=1, hour=0, minute=0
224
+ )
225
+ ival_M_to_T_end = Period(
226
+ freq="Min", year=2007, month=1, day=31, hour=23, minute=59
227
+ )
228
+ ival_M_to_S_start = Period(
229
+ freq="s", year=2007, month=1, day=1, hour=0, minute=0, second=0
230
+ )
231
+ ival_M_to_S_end = Period(
232
+ freq="s", year=2007, month=1, day=31, hour=23, minute=59, second=59
233
+ )
234
+
235
+ assert ival_M.asfreq("Y") == ival_M_to_A
236
+ assert ival_M_end_of_year.asfreq("Y") == ival_M_to_A
237
+ assert ival_M.asfreq("Q") == ival_M_to_Q
238
+ assert ival_M_end_of_quarter.asfreq("Q") == ival_M_to_Q
239
+
240
+ assert ival_M.asfreq("W", "s") == ival_M_to_W_start
241
+ assert ival_M.asfreq("W", "E") == ival_M_to_W_end
242
+ with tm.assert_produces_warning(FutureWarning, match=bday_msg):
243
+ assert ival_M.asfreq("B", "s") == ival_M_to_B_start
244
+ assert ival_M.asfreq("B", "E") == ival_M_to_B_end
245
+ assert ival_M.asfreq("D", "s") == ival_M_to_D_start
246
+ assert ival_M.asfreq("D", "E") == ival_M_to_D_end
247
+ assert ival_M.asfreq("h", "s") == ival_M_to_H_start
248
+ assert ival_M.asfreq("h", "E") == ival_M_to_H_end
249
+ assert ival_M.asfreq("Min", "s") == ival_M_to_T_start
250
+ assert ival_M.asfreq("Min", "E") == ival_M_to_T_end
251
+ assert ival_M.asfreq("s", "s") == ival_M_to_S_start
252
+ assert ival_M.asfreq("s", "E") == ival_M_to_S_end
253
+
254
+ assert ival_M.asfreq("M") == ival_M
255
+
256
+ def test_conv_weekly(self):
257
+ # frequency conversion tests: from Weekly Frequency
258
+ ival_W = Period(freq="W", year=2007, month=1, day=1)
259
+
260
+ ival_WSUN = Period(freq="W", year=2007, month=1, day=7)
261
+ ival_WSAT = Period(freq="W-SAT", year=2007, month=1, day=6)
262
+ ival_WFRI = Period(freq="W-FRI", year=2007, month=1, day=5)
263
+ ival_WTHU = Period(freq="W-THU", year=2007, month=1, day=4)
264
+ ival_WWED = Period(freq="W-WED", year=2007, month=1, day=3)
265
+ ival_WTUE = Period(freq="W-TUE", year=2007, month=1, day=2)
266
+ ival_WMON = Period(freq="W-MON", year=2007, month=1, day=1)
267
+
268
+ ival_WSUN_to_D_start = Period(freq="D", year=2007, month=1, day=1)
269
+ ival_WSUN_to_D_end = Period(freq="D", year=2007, month=1, day=7)
270
+ ival_WSAT_to_D_start = Period(freq="D", year=2006, month=12, day=31)
271
+ ival_WSAT_to_D_end = Period(freq="D", year=2007, month=1, day=6)
272
+ ival_WFRI_to_D_start = Period(freq="D", year=2006, month=12, day=30)
273
+ ival_WFRI_to_D_end = Period(freq="D", year=2007, month=1, day=5)
274
+ ival_WTHU_to_D_start = Period(freq="D", year=2006, month=12, day=29)
275
+ ival_WTHU_to_D_end = Period(freq="D", year=2007, month=1, day=4)
276
+ ival_WWED_to_D_start = Period(freq="D", year=2006, month=12, day=28)
277
+ ival_WWED_to_D_end = Period(freq="D", year=2007, month=1, day=3)
278
+ ival_WTUE_to_D_start = Period(freq="D", year=2006, month=12, day=27)
279
+ ival_WTUE_to_D_end = Period(freq="D", year=2007, month=1, day=2)
280
+ ival_WMON_to_D_start = Period(freq="D", year=2006, month=12, day=26)
281
+ ival_WMON_to_D_end = Period(freq="D", year=2007, month=1, day=1)
282
+
283
+ ival_W_end_of_year = Period(freq="W", year=2007, month=12, day=31)
284
+ ival_W_end_of_quarter = Period(freq="W", year=2007, month=3, day=31)
285
+ ival_W_end_of_month = Period(freq="W", year=2007, month=1, day=31)
286
+ ival_W_to_A = Period(freq="Y", year=2007)
287
+ ival_W_to_Q = Period(freq="Q", year=2007, quarter=1)
288
+ ival_W_to_M = Period(freq="M", year=2007, month=1)
289
+
290
+ if Period(freq="D", year=2007, month=12, day=31).weekday == 6:
291
+ ival_W_to_A_end_of_year = Period(freq="Y", year=2007)
292
+ else:
293
+ ival_W_to_A_end_of_year = Period(freq="Y", year=2008)
294
+
295
+ if Period(freq="D", year=2007, month=3, day=31).weekday == 6:
296
+ ival_W_to_Q_end_of_quarter = Period(freq="Q", year=2007, quarter=1)
297
+ else:
298
+ ival_W_to_Q_end_of_quarter = Period(freq="Q", year=2007, quarter=2)
299
+
300
+ if Period(freq="D", year=2007, month=1, day=31).weekday == 6:
301
+ ival_W_to_M_end_of_month = Period(freq="M", year=2007, month=1)
302
+ else:
303
+ ival_W_to_M_end_of_month = Period(freq="M", year=2007, month=2)
304
+
305
+ with tm.assert_produces_warning(FutureWarning, match=bday_msg):
306
+ ival_W_to_B_start = Period(freq="B", year=2007, month=1, day=1)
307
+ ival_W_to_B_end = Period(freq="B", year=2007, month=1, day=5)
308
+ ival_W_to_D_start = Period(freq="D", year=2007, month=1, day=1)
309
+ ival_W_to_D_end = Period(freq="D", year=2007, month=1, day=7)
310
+ ival_W_to_H_start = Period(freq="h", year=2007, month=1, day=1, hour=0)
311
+ ival_W_to_H_end = Period(freq="h", year=2007, month=1, day=7, hour=23)
312
+ ival_W_to_T_start = Period(
313
+ freq="Min", year=2007, month=1, day=1, hour=0, minute=0
314
+ )
315
+ ival_W_to_T_end = Period(
316
+ freq="Min", year=2007, month=1, day=7, hour=23, minute=59
317
+ )
318
+ ival_W_to_S_start = Period(
319
+ freq="s", year=2007, month=1, day=1, hour=0, minute=0, second=0
320
+ )
321
+ ival_W_to_S_end = Period(
322
+ freq="s", year=2007, month=1, day=7, hour=23, minute=59, second=59
323
+ )
324
+
325
+ assert ival_W.asfreq("Y") == ival_W_to_A
326
+ assert ival_W_end_of_year.asfreq("Y") == ival_W_to_A_end_of_year
327
+
328
+ assert ival_W.asfreq("Q") == ival_W_to_Q
329
+ assert ival_W_end_of_quarter.asfreq("Q") == ival_W_to_Q_end_of_quarter
330
+
331
+ assert ival_W.asfreq("M") == ival_W_to_M
332
+ assert ival_W_end_of_month.asfreq("M") == ival_W_to_M_end_of_month
333
+
334
+ with tm.assert_produces_warning(FutureWarning, match=bday_msg):
335
+ assert ival_W.asfreq("B", "s") == ival_W_to_B_start
336
+ assert ival_W.asfreq("B", "E") == ival_W_to_B_end
337
+
338
+ assert ival_W.asfreq("D", "s") == ival_W_to_D_start
339
+ assert ival_W.asfreq("D", "E") == ival_W_to_D_end
340
+
341
+ assert ival_WSUN.asfreq("D", "s") == ival_WSUN_to_D_start
342
+ assert ival_WSUN.asfreq("D", "E") == ival_WSUN_to_D_end
343
+ assert ival_WSAT.asfreq("D", "s") == ival_WSAT_to_D_start
344
+ assert ival_WSAT.asfreq("D", "E") == ival_WSAT_to_D_end
345
+ assert ival_WFRI.asfreq("D", "s") == ival_WFRI_to_D_start
346
+ assert ival_WFRI.asfreq("D", "E") == ival_WFRI_to_D_end
347
+ assert ival_WTHU.asfreq("D", "s") == ival_WTHU_to_D_start
348
+ assert ival_WTHU.asfreq("D", "E") == ival_WTHU_to_D_end
349
+ assert ival_WWED.asfreq("D", "s") == ival_WWED_to_D_start
350
+ assert ival_WWED.asfreq("D", "E") == ival_WWED_to_D_end
351
+ assert ival_WTUE.asfreq("D", "s") == ival_WTUE_to_D_start
352
+ assert ival_WTUE.asfreq("D", "E") == ival_WTUE_to_D_end
353
+ assert ival_WMON.asfreq("D", "s") == ival_WMON_to_D_start
354
+ assert ival_WMON.asfreq("D", "E") == ival_WMON_to_D_end
355
+
356
+ assert ival_W.asfreq("h", "s") == ival_W_to_H_start
357
+ assert ival_W.asfreq("h", "E") == ival_W_to_H_end
358
+ assert ival_W.asfreq("Min", "s") == ival_W_to_T_start
359
+ assert ival_W.asfreq("Min", "E") == ival_W_to_T_end
360
+ assert ival_W.asfreq("s", "s") == ival_W_to_S_start
361
+ assert ival_W.asfreq("s", "E") == ival_W_to_S_end
362
+
363
+ assert ival_W.asfreq("W") == ival_W
364
+
365
+ msg = INVALID_FREQ_ERR_MSG
366
+ with pytest.raises(ValueError, match=msg):
367
+ ival_W.asfreq("WK")
368
+
369
+ def test_conv_weekly_legacy(self):
370
+ # frequency conversion tests: from Weekly Frequency
371
+ msg = INVALID_FREQ_ERR_MSG
372
+ with pytest.raises(ValueError, match=msg):
373
+ Period(freq="WK", year=2007, month=1, day=1)
374
+
375
+ with pytest.raises(ValueError, match=msg):
376
+ Period(freq="WK-SAT", year=2007, month=1, day=6)
377
+ with pytest.raises(ValueError, match=msg):
378
+ Period(freq="WK-FRI", year=2007, month=1, day=5)
379
+ with pytest.raises(ValueError, match=msg):
380
+ Period(freq="WK-THU", year=2007, month=1, day=4)
381
+ with pytest.raises(ValueError, match=msg):
382
+ Period(freq="WK-WED", year=2007, month=1, day=3)
383
+ with pytest.raises(ValueError, match=msg):
384
+ Period(freq="WK-TUE", year=2007, month=1, day=2)
385
+ with pytest.raises(ValueError, match=msg):
386
+ Period(freq="WK-MON", year=2007, month=1, day=1)
387
+
388
+ def test_conv_business(self):
389
+ # frequency conversion tests: from Business Frequency"
390
+
391
+ with tm.assert_produces_warning(FutureWarning, match=bday_msg):
392
+ ival_B = Period(freq="B", year=2007, month=1, day=1)
393
+ ival_B_end_of_year = Period(freq="B", year=2007, month=12, day=31)
394
+ ival_B_end_of_quarter = Period(freq="B", year=2007, month=3, day=30)
395
+ ival_B_end_of_month = Period(freq="B", year=2007, month=1, day=31)
396
+ ival_B_end_of_week = Period(freq="B", year=2007, month=1, day=5)
397
+
398
+ ival_B_to_A = Period(freq="Y", year=2007)
399
+ ival_B_to_Q = Period(freq="Q", year=2007, quarter=1)
400
+ ival_B_to_M = Period(freq="M", year=2007, month=1)
401
+ ival_B_to_W = Period(freq="W", year=2007, month=1, day=7)
402
+ ival_B_to_D = Period(freq="D", year=2007, month=1, day=1)
403
+ ival_B_to_H_start = Period(freq="h", year=2007, month=1, day=1, hour=0)
404
+ ival_B_to_H_end = Period(freq="h", year=2007, month=1, day=1, hour=23)
405
+ ival_B_to_T_start = Period(
406
+ freq="Min", year=2007, month=1, day=1, hour=0, minute=0
407
+ )
408
+ ival_B_to_T_end = Period(
409
+ freq="Min", year=2007, month=1, day=1, hour=23, minute=59
410
+ )
411
+ ival_B_to_S_start = Period(
412
+ freq="s", year=2007, month=1, day=1, hour=0, minute=0, second=0
413
+ )
414
+ ival_B_to_S_end = Period(
415
+ freq="s", year=2007, month=1, day=1, hour=23, minute=59, second=59
416
+ )
417
+
418
+ assert ival_B.asfreq("Y") == ival_B_to_A
419
+ assert ival_B_end_of_year.asfreq("Y") == ival_B_to_A
420
+ assert ival_B.asfreq("Q") == ival_B_to_Q
421
+ assert ival_B_end_of_quarter.asfreq("Q") == ival_B_to_Q
422
+ assert ival_B.asfreq("M") == ival_B_to_M
423
+ assert ival_B_end_of_month.asfreq("M") == ival_B_to_M
424
+ assert ival_B.asfreq("W") == ival_B_to_W
425
+ assert ival_B_end_of_week.asfreq("W") == ival_B_to_W
426
+
427
+ assert ival_B.asfreq("D") == ival_B_to_D
428
+
429
+ assert ival_B.asfreq("h", "s") == ival_B_to_H_start
430
+ assert ival_B.asfreq("h", "E") == ival_B_to_H_end
431
+ assert ival_B.asfreq("Min", "s") == ival_B_to_T_start
432
+ assert ival_B.asfreq("Min", "E") == ival_B_to_T_end
433
+ assert ival_B.asfreq("s", "s") == ival_B_to_S_start
434
+ assert ival_B.asfreq("s", "E") == ival_B_to_S_end
435
+
436
+ with tm.assert_produces_warning(FutureWarning, match=bday_msg):
437
+ assert ival_B.asfreq("B") == ival_B
438
+
439
+ def test_conv_daily(self):
440
+ # frequency conversion tests: from Business Frequency"
441
+
442
+ ival_D = Period(freq="D", year=2007, month=1, day=1)
443
+ ival_D_end_of_year = Period(freq="D", year=2007, month=12, day=31)
444
+ ival_D_end_of_quarter = Period(freq="D", year=2007, month=3, day=31)
445
+ ival_D_end_of_month = Period(freq="D", year=2007, month=1, day=31)
446
+ ival_D_end_of_week = Period(freq="D", year=2007, month=1, day=7)
447
+
448
+ ival_D_friday = Period(freq="D", year=2007, month=1, day=5)
449
+ ival_D_saturday = Period(freq="D", year=2007, month=1, day=6)
450
+ ival_D_sunday = Period(freq="D", year=2007, month=1, day=7)
451
+
452
+ with tm.assert_produces_warning(FutureWarning, match=bday_msg):
453
+ ival_B_friday = Period(freq="B", year=2007, month=1, day=5)
454
+ ival_B_monday = Period(freq="B", year=2007, month=1, day=8)
455
+
456
+ ival_D_to_A = Period(freq="Y", year=2007)
457
+
458
+ ival_Deoq_to_AJAN = Period(freq="Y-JAN", year=2008)
459
+ ival_Deoq_to_AJUN = Period(freq="Y-JUN", year=2007)
460
+ ival_Deoq_to_ADEC = Period(freq="Y-DEC", year=2007)
461
+
462
+ ival_D_to_QEJAN = Period(freq="Q-JAN", year=2007, quarter=4)
463
+ ival_D_to_QEJUN = Period(freq="Q-JUN", year=2007, quarter=3)
464
+ ival_D_to_QEDEC = Period(freq="Q-DEC", year=2007, quarter=1)
465
+
466
+ ival_D_to_M = Period(freq="M", year=2007, month=1)
467
+ ival_D_to_W = Period(freq="W", year=2007, month=1, day=7)
468
+
469
+ ival_D_to_H_start = Period(freq="h", year=2007, month=1, day=1, hour=0)
470
+ ival_D_to_H_end = Period(freq="h", year=2007, month=1, day=1, hour=23)
471
+ ival_D_to_T_start = Period(
472
+ freq="Min", year=2007, month=1, day=1, hour=0, minute=0
473
+ )
474
+ ival_D_to_T_end = Period(
475
+ freq="Min", year=2007, month=1, day=1, hour=23, minute=59
476
+ )
477
+ ival_D_to_S_start = Period(
478
+ freq="s", year=2007, month=1, day=1, hour=0, minute=0, second=0
479
+ )
480
+ ival_D_to_S_end = Period(
481
+ freq="s", year=2007, month=1, day=1, hour=23, minute=59, second=59
482
+ )
483
+
484
+ assert ival_D.asfreq("Y") == ival_D_to_A
485
+
486
+ assert ival_D_end_of_quarter.asfreq("Y-JAN") == ival_Deoq_to_AJAN
487
+ assert ival_D_end_of_quarter.asfreq("Y-JUN") == ival_Deoq_to_AJUN
488
+ assert ival_D_end_of_quarter.asfreq("Y-DEC") == ival_Deoq_to_ADEC
489
+
490
+ assert ival_D_end_of_year.asfreq("Y") == ival_D_to_A
491
+ assert ival_D_end_of_quarter.asfreq("Q") == ival_D_to_QEDEC
492
+ assert ival_D.asfreq("Q-JAN") == ival_D_to_QEJAN
493
+ assert ival_D.asfreq("Q-JUN") == ival_D_to_QEJUN
494
+ assert ival_D.asfreq("Q-DEC") == ival_D_to_QEDEC
495
+ assert ival_D.asfreq("M") == ival_D_to_M
496
+ assert ival_D_end_of_month.asfreq("M") == ival_D_to_M
497
+ assert ival_D.asfreq("W") == ival_D_to_W
498
+ assert ival_D_end_of_week.asfreq("W") == ival_D_to_W
499
+
500
+ with tm.assert_produces_warning(FutureWarning, match=bday_msg):
501
+ assert ival_D_friday.asfreq("B") == ival_B_friday
502
+ assert ival_D_saturday.asfreq("B", "s") == ival_B_friday
503
+ assert ival_D_saturday.asfreq("B", "E") == ival_B_monday
504
+ assert ival_D_sunday.asfreq("B", "s") == ival_B_friday
505
+ assert ival_D_sunday.asfreq("B", "E") == ival_B_monday
506
+
507
+ assert ival_D.asfreq("h", "s") == ival_D_to_H_start
508
+ assert ival_D.asfreq("h", "E") == ival_D_to_H_end
509
+ assert ival_D.asfreq("Min", "s") == ival_D_to_T_start
510
+ assert ival_D.asfreq("Min", "E") == ival_D_to_T_end
511
+ assert ival_D.asfreq("s", "s") == ival_D_to_S_start
512
+ assert ival_D.asfreq("s", "E") == ival_D_to_S_end
513
+
514
+ assert ival_D.asfreq("D") == ival_D
515
+
516
+ def test_conv_hourly(self):
517
+ # frequency conversion tests: from Hourly Frequency"
518
+
519
+ ival_H = Period(freq="h", year=2007, month=1, day=1, hour=0)
520
+ ival_H_end_of_year = Period(freq="h", year=2007, month=12, day=31, hour=23)
521
+ ival_H_end_of_quarter = Period(freq="h", year=2007, month=3, day=31, hour=23)
522
+ ival_H_end_of_month = Period(freq="h", year=2007, month=1, day=31, hour=23)
523
+ ival_H_end_of_week = Period(freq="h", year=2007, month=1, day=7, hour=23)
524
+ ival_H_end_of_day = Period(freq="h", year=2007, month=1, day=1, hour=23)
525
+ ival_H_end_of_bus = Period(freq="h", year=2007, month=1, day=1, hour=23)
526
+
527
+ ival_H_to_A = Period(freq="Y", year=2007)
528
+ ival_H_to_Q = Period(freq="Q", year=2007, quarter=1)
529
+ ival_H_to_M = Period(freq="M", year=2007, month=1)
530
+ ival_H_to_W = Period(freq="W", year=2007, month=1, day=7)
531
+ ival_H_to_D = Period(freq="D", year=2007, month=1, day=1)
532
+ with tm.assert_produces_warning(FutureWarning, match=bday_msg):
533
+ ival_H_to_B = Period(freq="B", year=2007, month=1, day=1)
534
+
535
+ ival_H_to_T_start = Period(
536
+ freq="Min", year=2007, month=1, day=1, hour=0, minute=0
537
+ )
538
+ ival_H_to_T_end = Period(
539
+ freq="Min", year=2007, month=1, day=1, hour=0, minute=59
540
+ )
541
+ ival_H_to_S_start = Period(
542
+ freq="s", year=2007, month=1, day=1, hour=0, minute=0, second=0
543
+ )
544
+ ival_H_to_S_end = Period(
545
+ freq="s", year=2007, month=1, day=1, hour=0, minute=59, second=59
546
+ )
547
+
548
+ assert ival_H.asfreq("Y") == ival_H_to_A
549
+ assert ival_H_end_of_year.asfreq("Y") == ival_H_to_A
550
+ assert ival_H.asfreq("Q") == ival_H_to_Q
551
+ assert ival_H_end_of_quarter.asfreq("Q") == ival_H_to_Q
552
+ assert ival_H.asfreq("M") == ival_H_to_M
553
+ assert ival_H_end_of_month.asfreq("M") == ival_H_to_M
554
+ assert ival_H.asfreq("W") == ival_H_to_W
555
+ assert ival_H_end_of_week.asfreq("W") == ival_H_to_W
556
+ assert ival_H.asfreq("D") == ival_H_to_D
557
+ assert ival_H_end_of_day.asfreq("D") == ival_H_to_D
558
+ with tm.assert_produces_warning(FutureWarning, match=bday_msg):
559
+ assert ival_H.asfreq("B") == ival_H_to_B
560
+ assert ival_H_end_of_bus.asfreq("B") == ival_H_to_B
561
+
562
+ assert ival_H.asfreq("Min", "s") == ival_H_to_T_start
563
+ assert ival_H.asfreq("Min", "E") == ival_H_to_T_end
564
+ assert ival_H.asfreq("s", "s") == ival_H_to_S_start
565
+ assert ival_H.asfreq("s", "E") == ival_H_to_S_end
566
+
567
+ assert ival_H.asfreq("h") == ival_H
568
+
569
+ def test_conv_minutely(self):
570
+ # frequency conversion tests: from Minutely Frequency"
571
+
572
+ ival_T = Period(freq="Min", year=2007, month=1, day=1, hour=0, minute=0)
573
+ ival_T_end_of_year = Period(
574
+ freq="Min", year=2007, month=12, day=31, hour=23, minute=59
575
+ )
576
+ ival_T_end_of_quarter = Period(
577
+ freq="Min", year=2007, month=3, day=31, hour=23, minute=59
578
+ )
579
+ ival_T_end_of_month = Period(
580
+ freq="Min", year=2007, month=1, day=31, hour=23, minute=59
581
+ )
582
+ ival_T_end_of_week = Period(
583
+ freq="Min", year=2007, month=1, day=7, hour=23, minute=59
584
+ )
585
+ ival_T_end_of_day = Period(
586
+ freq="Min", year=2007, month=1, day=1, hour=23, minute=59
587
+ )
588
+ ival_T_end_of_bus = Period(
589
+ freq="Min", year=2007, month=1, day=1, hour=23, minute=59
590
+ )
591
+ ival_T_end_of_hour = Period(
592
+ freq="Min", year=2007, month=1, day=1, hour=0, minute=59
593
+ )
594
+
595
+ ival_T_to_A = Period(freq="Y", year=2007)
596
+ ival_T_to_Q = Period(freq="Q", year=2007, quarter=1)
597
+ ival_T_to_M = Period(freq="M", year=2007, month=1)
598
+ ival_T_to_W = Period(freq="W", year=2007, month=1, day=7)
599
+ ival_T_to_D = Period(freq="D", year=2007, month=1, day=1)
600
+ with tm.assert_produces_warning(FutureWarning, match=bday_msg):
601
+ ival_T_to_B = Period(freq="B", year=2007, month=1, day=1)
602
+ ival_T_to_H = Period(freq="h", year=2007, month=1, day=1, hour=0)
603
+
604
+ ival_T_to_S_start = Period(
605
+ freq="s", year=2007, month=1, day=1, hour=0, minute=0, second=0
606
+ )
607
+ ival_T_to_S_end = Period(
608
+ freq="s", year=2007, month=1, day=1, hour=0, minute=0, second=59
609
+ )
610
+
611
+ assert ival_T.asfreq("Y") == ival_T_to_A
612
+ assert ival_T_end_of_year.asfreq("Y") == ival_T_to_A
613
+ assert ival_T.asfreq("Q") == ival_T_to_Q
614
+ assert ival_T_end_of_quarter.asfreq("Q") == ival_T_to_Q
615
+ assert ival_T.asfreq("M") == ival_T_to_M
616
+ assert ival_T_end_of_month.asfreq("M") == ival_T_to_M
617
+ assert ival_T.asfreq("W") == ival_T_to_W
618
+ assert ival_T_end_of_week.asfreq("W") == ival_T_to_W
619
+ assert ival_T.asfreq("D") == ival_T_to_D
620
+ assert ival_T_end_of_day.asfreq("D") == ival_T_to_D
621
+ with tm.assert_produces_warning(FutureWarning, match=bday_msg):
622
+ assert ival_T.asfreq("B") == ival_T_to_B
623
+ assert ival_T_end_of_bus.asfreq("B") == ival_T_to_B
624
+ assert ival_T.asfreq("h") == ival_T_to_H
625
+ assert ival_T_end_of_hour.asfreq("h") == ival_T_to_H
626
+
627
+ assert ival_T.asfreq("s", "s") == ival_T_to_S_start
628
+ assert ival_T.asfreq("s", "E") == ival_T_to_S_end
629
+
630
+ assert ival_T.asfreq("Min") == ival_T
631
+
632
+ def test_conv_secondly(self):
633
+ # frequency conversion tests: from Secondly Frequency"
634
+
635
+ ival_S = Period(freq="s", year=2007, month=1, day=1, hour=0, minute=0, second=0)
636
+ ival_S_end_of_year = Period(
637
+ freq="s", year=2007, month=12, day=31, hour=23, minute=59, second=59
638
+ )
639
+ ival_S_end_of_quarter = Period(
640
+ freq="s", year=2007, month=3, day=31, hour=23, minute=59, second=59
641
+ )
642
+ ival_S_end_of_month = Period(
643
+ freq="s", year=2007, month=1, day=31, hour=23, minute=59, second=59
644
+ )
645
+ ival_S_end_of_week = Period(
646
+ freq="s", year=2007, month=1, day=7, hour=23, minute=59, second=59
647
+ )
648
+ ival_S_end_of_day = Period(
649
+ freq="s", year=2007, month=1, day=1, hour=23, minute=59, second=59
650
+ )
651
+ ival_S_end_of_bus = Period(
652
+ freq="s", year=2007, month=1, day=1, hour=23, minute=59, second=59
653
+ )
654
+ ival_S_end_of_hour = Period(
655
+ freq="s", year=2007, month=1, day=1, hour=0, minute=59, second=59
656
+ )
657
+ ival_S_end_of_minute = Period(
658
+ freq="s", year=2007, month=1, day=1, hour=0, minute=0, second=59
659
+ )
660
+
661
+ ival_S_to_A = Period(freq="Y", year=2007)
662
+ ival_S_to_Q = Period(freq="Q", year=2007, quarter=1)
663
+ ival_S_to_M = Period(freq="M", year=2007, month=1)
664
+ ival_S_to_W = Period(freq="W", year=2007, month=1, day=7)
665
+ ival_S_to_D = Period(freq="D", year=2007, month=1, day=1)
666
+ with tm.assert_produces_warning(FutureWarning, match=bday_msg):
667
+ ival_S_to_B = Period(freq="B", year=2007, month=1, day=1)
668
+ ival_S_to_H = Period(freq="h", year=2007, month=1, day=1, hour=0)
669
+ ival_S_to_T = Period(freq="Min", year=2007, month=1, day=1, hour=0, minute=0)
670
+
671
+ assert ival_S.asfreq("Y") == ival_S_to_A
672
+ assert ival_S_end_of_year.asfreq("Y") == ival_S_to_A
673
+ assert ival_S.asfreq("Q") == ival_S_to_Q
674
+ assert ival_S_end_of_quarter.asfreq("Q") == ival_S_to_Q
675
+ assert ival_S.asfreq("M") == ival_S_to_M
676
+ assert ival_S_end_of_month.asfreq("M") == ival_S_to_M
677
+ assert ival_S.asfreq("W") == ival_S_to_W
678
+ assert ival_S_end_of_week.asfreq("W") == ival_S_to_W
679
+ assert ival_S.asfreq("D") == ival_S_to_D
680
+ assert ival_S_end_of_day.asfreq("D") == ival_S_to_D
681
+ with tm.assert_produces_warning(FutureWarning, match=bday_msg):
682
+ assert ival_S.asfreq("B") == ival_S_to_B
683
+ assert ival_S_end_of_bus.asfreq("B") == ival_S_to_B
684
+ assert ival_S.asfreq("h") == ival_S_to_H
685
+ assert ival_S_end_of_hour.asfreq("h") == ival_S_to_H
686
+ assert ival_S.asfreq("Min") == ival_S_to_T
687
+ assert ival_S_end_of_minute.asfreq("Min") == ival_S_to_T
688
+
689
+ assert ival_S.asfreq("s") == ival_S
690
+
691
+ def test_conv_microsecond(self):
692
+ # GH#31475 Avoid floating point errors dropping the start_time to
693
+ # before the beginning of the Period
694
+ per = Period("2020-01-30 15:57:27.576166", freq="us")
695
+ assert per.ordinal == 1580399847576166
696
+
697
+ start = per.start_time
698
+ expected = Timestamp("2020-01-30 15:57:27.576166")
699
+ assert start == expected
700
+ assert start._value == per.ordinal * 1000
701
+
702
+ per2 = Period("2300-01-01", "us")
703
+ msg = "2300-01-01"
704
+ with pytest.raises(OutOfBoundsDatetime, match=msg):
705
+ per2.start_time
706
+ with pytest.raises(OutOfBoundsDatetime, match=msg):
707
+ per2.end_time
708
+
709
+ def test_asfreq_mult(self):
710
+ # normal freq to mult freq
711
+ p = Period(freq="Y", year=2007)
712
+ # ordinal will not change
713
+ for freq in ["3Y", offsets.YearEnd(3)]:
714
+ result = p.asfreq(freq)
715
+ expected = Period("2007", freq="3Y")
716
+
717
+ assert result == expected
718
+ assert result.ordinal == expected.ordinal
719
+ assert result.freq == expected.freq
720
+ # ordinal will not change
721
+ for freq in ["3Y", offsets.YearEnd(3)]:
722
+ result = p.asfreq(freq, how="S")
723
+ expected = Period("2007", freq="3Y")
724
+
725
+ assert result == expected
726
+ assert result.ordinal == expected.ordinal
727
+ assert result.freq == expected.freq
728
+
729
+ # mult freq to normal freq
730
+ p = Period(freq="3Y", year=2007)
731
+ # ordinal will change because how=E is the default
732
+ for freq in ["Y", offsets.YearEnd()]:
733
+ result = p.asfreq(freq)
734
+ expected = Period("2009", freq="Y")
735
+
736
+ assert result == expected
737
+ assert result.ordinal == expected.ordinal
738
+ assert result.freq == expected.freq
739
+ # ordinal will not change
740
+ for freq in ["Y", offsets.YearEnd()]:
741
+ result = p.asfreq(freq, how="s")
742
+ expected = Period("2007", freq="Y")
743
+
744
+ assert result == expected
745
+ assert result.ordinal == expected.ordinal
746
+ assert result.freq == expected.freq
747
+
748
+ p = Period(freq="Y", year=2007)
749
+ for freq in ["2M", offsets.MonthEnd(2)]:
750
+ result = p.asfreq(freq)
751
+ expected = Period("2007-12", freq="2M")
752
+
753
+ assert result == expected
754
+ assert result.ordinal == expected.ordinal
755
+ assert result.freq == expected.freq
756
+ for freq in ["2M", offsets.MonthEnd(2)]:
757
+ result = p.asfreq(freq, how="s")
758
+ expected = Period("2007-01", freq="2M")
759
+
760
+ assert result == expected
761
+ assert result.ordinal == expected.ordinal
762
+ assert result.freq == expected.freq
763
+
764
+ p = Period(freq="3Y", year=2007)
765
+ for freq in ["2M", offsets.MonthEnd(2)]:
766
+ result = p.asfreq(freq)
767
+ expected = Period("2009-12", freq="2M")
768
+
769
+ assert result == expected
770
+ assert result.ordinal == expected.ordinal
771
+ assert result.freq == expected.freq
772
+ for freq in ["2M", offsets.MonthEnd(2)]:
773
+ result = p.asfreq(freq, how="s")
774
+ expected = Period("2007-01", freq="2M")
775
+
776
+ assert result == expected
777
+ assert result.ordinal == expected.ordinal
778
+ assert result.freq == expected.freq
779
+
780
+ def test_asfreq_combined(self):
781
+ # normal freq to combined freq
782
+ p = Period("2007", freq="h")
783
+
784
+ # ordinal will not change
785
+ expected = Period("2007", freq="25h")
786
+ for freq, how in zip(["1D1h", "1h1D"], ["E", "S"]):
787
+ result = p.asfreq(freq, how=how)
788
+ assert result == expected
789
+ assert result.ordinal == expected.ordinal
790
+ assert result.freq == expected.freq
791
+
792
+ # combined freq to normal freq
793
+ p1 = Period(freq="1D1h", year=2007)
794
+ p2 = Period(freq="1h1D", year=2007)
795
+
796
+ # ordinal will change because how=E is the default
797
+ result1 = p1.asfreq("h")
798
+ result2 = p2.asfreq("h")
799
+ expected = Period("2007-01-02", freq="h")
800
+ assert result1 == expected
801
+ assert result1.ordinal == expected.ordinal
802
+ assert result1.freq == expected.freq
803
+ assert result2 == expected
804
+ assert result2.ordinal == expected.ordinal
805
+ assert result2.freq == expected.freq
806
+
807
+ # ordinal will not change
808
+ result1 = p1.asfreq("h", how="S")
809
+ result2 = p2.asfreq("h", how="S")
810
+ expected = Period("2007-01-01", freq="h")
811
+ assert result1 == expected
812
+ assert result1.ordinal == expected.ordinal
813
+ assert result1.freq == expected.freq
814
+ assert result2 == expected
815
+ assert result2.ordinal == expected.ordinal
816
+ assert result2.freq == expected.freq
817
+
818
+ def test_asfreq_MS(self):
819
+ initial = Period("2013")
820
+
821
+ assert initial.asfreq(freq="M", how="S") == Period("2013-01", "M")
822
+
823
+ msg = "MS is not supported as period frequency"
824
+ with pytest.raises(ValueError, match=msg):
825
+ initial.asfreq(freq="MS", how="S")
826
+
827
+ with pytest.raises(ValueError, match=msg):
828
+ Period("2013-01", "MS")
py311/lib/python3.11/site-packages/pandas/tests/scalar/period/test_period.py ADDED
@@ -0,0 +1,1158 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from datetime import (
2
+ date,
3
+ datetime,
4
+ timedelta,
5
+ )
6
+ import re
7
+
8
+ import numpy as np
9
+ import pytest
10
+
11
+ from pandas._libs.tslibs import iNaT
12
+ from pandas._libs.tslibs.ccalendar import (
13
+ DAYS,
14
+ MONTHS,
15
+ )
16
+ from pandas._libs.tslibs.np_datetime import OutOfBoundsDatetime
17
+ from pandas._libs.tslibs.parsing import DateParseError
18
+ from pandas._libs.tslibs.period import INVALID_FREQ_ERR_MSG
19
+ from pandas.compat import PY314
20
+
21
+ from pandas import (
22
+ NaT,
23
+ Period,
24
+ Timedelta,
25
+ Timestamp,
26
+ offsets,
27
+ )
28
+ import pandas._testing as tm
29
+
30
+ bday_msg = "Period with BDay freq is deprecated"
31
+
32
+
33
+ class TestPeriodDisallowedFreqs:
34
+ @pytest.mark.parametrize(
35
+ "freq, freq_msg",
36
+ [
37
+ (offsets.BYearBegin(), "BYearBegin"),
38
+ (offsets.YearBegin(2), "YearBegin"),
39
+ (offsets.QuarterBegin(startingMonth=12), "QuarterBegin"),
40
+ (offsets.BusinessMonthEnd(2), "BusinessMonthEnd"),
41
+ ],
42
+ )
43
+ def test_offsets_not_supported(self, freq, freq_msg):
44
+ # GH#55785
45
+ msg = re.escape(f"{freq} is not supported as period frequency")
46
+ with pytest.raises(ValueError, match=msg):
47
+ Period(year=2014, freq=freq)
48
+
49
+ def test_custom_business_day_freq_raises(self):
50
+ # GH#52534
51
+ msg = "C is not supported as period frequency"
52
+ with pytest.raises(ValueError, match=msg):
53
+ Period("2023-04-10", freq="C")
54
+ msg = f"{offsets.CustomBusinessDay().base} is not supported as period frequency"
55
+ with pytest.raises(ValueError, match=msg):
56
+ Period("2023-04-10", freq=offsets.CustomBusinessDay())
57
+
58
+ def test_invalid_frequency_error_message(self):
59
+ msg = "WOM-1MON is not supported as period frequency"
60
+ with pytest.raises(ValueError, match=msg):
61
+ Period("2012-01-02", freq="WOM-1MON")
62
+
63
+ def test_invalid_frequency_period_error_message(self):
64
+ msg = "for Period, please use 'M' instead of 'ME'"
65
+ with pytest.raises(ValueError, match=msg):
66
+ Period("2012-01-02", freq="ME")
67
+
68
+
69
+ class TestPeriodConstruction:
70
+ def test_from_td64nat_raises(self):
71
+ # GH#44507
72
+ td = NaT.to_numpy("m8[ns]")
73
+
74
+ msg = "Value must be Period, string, integer, or datetime"
75
+ with pytest.raises(ValueError, match=msg):
76
+ Period(td)
77
+
78
+ with pytest.raises(ValueError, match=msg):
79
+ Period(td, freq="D")
80
+
81
+ def test_construction(self):
82
+ i1 = Period("1/1/2005", freq="M")
83
+ i2 = Period("Jan 2005")
84
+
85
+ assert i1 == i2
86
+
87
+ # GH#54105 - Period can be confusingly instantiated with lowercase freq
88
+ # TODO: raise in the future an error when passing lowercase freq
89
+ i1 = Period("2005", freq="Y")
90
+ i2 = Period("2005")
91
+
92
+ assert i1 == i2
93
+
94
+ i4 = Period("2005", freq="M")
95
+ assert i1 != i4
96
+
97
+ i1 = Period.now(freq="Q")
98
+ i2 = Period(datetime.now(), freq="Q")
99
+
100
+ assert i1 == i2
101
+
102
+ # Pass in freq as a keyword argument sometimes as a test for
103
+ # https://github.com/pandas-dev/pandas/issues/53369
104
+ i1 = Period.now(freq="D")
105
+ i2 = Period(datetime.now(), freq="D")
106
+ i3 = Period.now(offsets.Day())
107
+
108
+ assert i1 == i2
109
+ assert i1 == i3
110
+
111
+ i1 = Period("1982", freq="min")
112
+ msg = "'MIN' is deprecated and will be removed in a future version."
113
+ with tm.assert_produces_warning(FutureWarning, match=msg):
114
+ i2 = Period("1982", freq="MIN")
115
+ assert i1 == i2
116
+
117
+ i1 = Period(year=2005, month=3, day=1, freq="D")
118
+ i2 = Period("3/1/2005", freq="D")
119
+ assert i1 == i2
120
+
121
+ i3 = Period(year=2005, month=3, day=1, freq="d")
122
+ assert i1 == i3
123
+
124
+ i1 = Period("2007-01-01 09:00:00.001")
125
+ expected = Period(datetime(2007, 1, 1, 9, 0, 0, 1000), freq="ms")
126
+ assert i1 == expected
127
+
128
+ expected = Period("2007-01-01 09:00:00.001", freq="ms")
129
+ assert i1 == expected
130
+
131
+ i1 = Period("2007-01-01 09:00:00.00101")
132
+ expected = Period(datetime(2007, 1, 1, 9, 0, 0, 1010), freq="us")
133
+ assert i1 == expected
134
+
135
+ expected = Period("2007-01-01 09:00:00.00101", freq="us")
136
+ assert i1 == expected
137
+
138
+ msg = "Must supply freq for ordinal value"
139
+ with pytest.raises(ValueError, match=msg):
140
+ Period(ordinal=200701)
141
+
142
+ msg = "Invalid frequency: X"
143
+ with pytest.raises(ValueError, match=msg):
144
+ Period("2007-1-1", freq="X")
145
+
146
+ def test_tuple_freq_disallowed(self):
147
+ # GH#34703 tuple freq disallowed
148
+ with pytest.raises(TypeError, match="pass as a string instead"):
149
+ Period("1982", freq=("Min", 1))
150
+
151
+ with pytest.raises(TypeError, match="pass as a string instead"):
152
+ Period("2006-12-31", ("w", 1))
153
+
154
+ def test_construction_from_timestamp_nanos(self):
155
+ # GH#46811 don't drop nanos from Timestamp
156
+ ts = Timestamp("2022-04-20 09:23:24.123456789")
157
+ per = Period(ts, freq="ns")
158
+
159
+ # should losslessly round-trip, not lose the 789
160
+ rt = per.to_timestamp()
161
+ assert rt == ts
162
+
163
+ # same thing but from a datetime64 object
164
+ dt64 = ts.asm8
165
+ per2 = Period(dt64, freq="ns")
166
+ rt2 = per2.to_timestamp()
167
+ assert rt2.asm8 == dt64
168
+
169
+ def test_construction_bday(self):
170
+ # Biz day construction, roll forward if non-weekday
171
+ with tm.assert_produces_warning(FutureWarning, match=bday_msg):
172
+ i1 = Period("3/10/12", freq="B")
173
+ i2 = Period("3/10/12", freq="D")
174
+ assert i1 == i2.asfreq("B")
175
+ i2 = Period("3/11/12", freq="D")
176
+ assert i1 == i2.asfreq("B")
177
+ i2 = Period("3/12/12", freq="D")
178
+ assert i1 == i2.asfreq("B")
179
+
180
+ i3 = Period("3/10/12", freq="b")
181
+ assert i1 == i3
182
+
183
+ i1 = Period(year=2012, month=3, day=10, freq="B")
184
+ i2 = Period("3/12/12", freq="B")
185
+ assert i1 == i2
186
+
187
+ def test_construction_quarter(self):
188
+ i1 = Period(year=2005, quarter=1, freq="Q")
189
+ i2 = Period("1/1/2005", freq="Q")
190
+ assert i1 == i2
191
+
192
+ i1 = Period(year=2005, quarter=3, freq="Q")
193
+ i2 = Period("9/1/2005", freq="Q")
194
+ assert i1 == i2
195
+
196
+ i1 = Period("2005Q1")
197
+ i2 = Period(year=2005, quarter=1, freq="Q")
198
+ i3 = Period("2005q1")
199
+ assert i1 == i2
200
+ assert i1 == i3
201
+
202
+ i1 = Period("05Q1")
203
+ assert i1 == i2
204
+ lower = Period("05q1")
205
+ assert i1 == lower
206
+
207
+ i1 = Period("1Q2005")
208
+ assert i1 == i2
209
+ lower = Period("1q2005")
210
+ assert i1 == lower
211
+
212
+ i1 = Period("1Q05")
213
+ assert i1 == i2
214
+ lower = Period("1q05")
215
+ assert i1 == lower
216
+
217
+ i1 = Period("4Q1984")
218
+ assert i1.year == 1984
219
+ lower = Period("4q1984")
220
+ assert i1 == lower
221
+
222
+ def test_construction_month(self):
223
+ expected = Period("2007-01", freq="M")
224
+ i1 = Period("200701", freq="M")
225
+ assert i1 == expected
226
+
227
+ i1 = Period("200701", freq="M")
228
+ assert i1 == expected
229
+
230
+ i1 = Period(200701, freq="M")
231
+ assert i1 == expected
232
+
233
+ i1 = Period(ordinal=200701, freq="M")
234
+ assert i1.year == 18695
235
+
236
+ i1 = Period(datetime(2007, 1, 1), freq="M")
237
+ i2 = Period("200701", freq="M")
238
+ assert i1 == i2
239
+
240
+ i1 = Period(date(2007, 1, 1), freq="M")
241
+ i2 = Period(datetime(2007, 1, 1), freq="M")
242
+ i3 = Period(np.datetime64("2007-01-01"), freq="M")
243
+ i4 = Period("2007-01-01 00:00:00", freq="M")
244
+ i5 = Period("2007-01-01 00:00:00.000", freq="M")
245
+ assert i1 == i2
246
+ assert i1 == i3
247
+ assert i1 == i4
248
+ assert i1 == i5
249
+
250
+ def test_period_constructor_offsets(self):
251
+ assert Period("1/1/2005", freq=offsets.MonthEnd()) == Period(
252
+ "1/1/2005", freq="M"
253
+ )
254
+ assert Period("2005", freq=offsets.YearEnd()) == Period("2005", freq="Y")
255
+ assert Period("2005", freq=offsets.MonthEnd()) == Period("2005", freq="M")
256
+ with tm.assert_produces_warning(FutureWarning, match=bday_msg):
257
+ assert Period("3/10/12", freq=offsets.BusinessDay()) == Period(
258
+ "3/10/12", freq="B"
259
+ )
260
+ assert Period("3/10/12", freq=offsets.Day()) == Period("3/10/12", freq="D")
261
+
262
+ assert Period(
263
+ year=2005, quarter=1, freq=offsets.QuarterEnd(startingMonth=12)
264
+ ) == Period(year=2005, quarter=1, freq="Q")
265
+ assert Period(
266
+ year=2005, quarter=2, freq=offsets.QuarterEnd(startingMonth=12)
267
+ ) == Period(year=2005, quarter=2, freq="Q")
268
+
269
+ assert Period(year=2005, month=3, day=1, freq=offsets.Day()) == Period(
270
+ year=2005, month=3, day=1, freq="D"
271
+ )
272
+ with tm.assert_produces_warning(FutureWarning, match=bday_msg):
273
+ assert Period(year=2012, month=3, day=10, freq=offsets.BDay()) == Period(
274
+ year=2012, month=3, day=10, freq="B"
275
+ )
276
+
277
+ expected = Period("2005-03-01", freq="3D")
278
+ assert Period(year=2005, month=3, day=1, freq=offsets.Day(3)) == expected
279
+ assert Period(year=2005, month=3, day=1, freq="3D") == expected
280
+
281
+ with tm.assert_produces_warning(FutureWarning, match=bday_msg):
282
+ assert Period(year=2012, month=3, day=10, freq=offsets.BDay(3)) == Period(
283
+ year=2012, month=3, day=10, freq="3B"
284
+ )
285
+
286
+ assert Period(200701, freq=offsets.MonthEnd()) == Period(200701, freq="M")
287
+
288
+ i1 = Period(ordinal=200701, freq=offsets.MonthEnd())
289
+ i2 = Period(ordinal=200701, freq="M")
290
+ assert i1 == i2
291
+ assert i1.year == 18695
292
+ assert i2.year == 18695
293
+
294
+ i1 = Period(datetime(2007, 1, 1), freq="M")
295
+ i2 = Period("200701", freq="M")
296
+ assert i1 == i2
297
+
298
+ i1 = Period(date(2007, 1, 1), freq="M")
299
+ i2 = Period(datetime(2007, 1, 1), freq="M")
300
+ i3 = Period(np.datetime64("2007-01-01"), freq="M")
301
+ i4 = Period("2007-01-01 00:00:00", freq="M")
302
+ i5 = Period("2007-01-01 00:00:00.000", freq="M")
303
+ assert i1 == i2
304
+ assert i1 == i3
305
+ assert i1 == i4
306
+ assert i1 == i5
307
+
308
+ i1 = Period("2007-01-01 09:00:00.001")
309
+ expected = Period(datetime(2007, 1, 1, 9, 0, 0, 1000), freq="ms")
310
+ assert i1 == expected
311
+
312
+ expected = Period("2007-01-01 09:00:00.001", freq="ms")
313
+ assert i1 == expected
314
+
315
+ i1 = Period("2007-01-01 09:00:00.00101")
316
+ expected = Period(datetime(2007, 1, 1, 9, 0, 0, 1010), freq="us")
317
+ assert i1 == expected
318
+
319
+ expected = Period("2007-01-01 09:00:00.00101", freq="us")
320
+ assert i1 == expected
321
+
322
+ def test_invalid_arguments(self):
323
+ msg = "Must supply freq for datetime value"
324
+ with pytest.raises(ValueError, match=msg):
325
+ Period(datetime.now())
326
+ with pytest.raises(ValueError, match=msg):
327
+ Period(datetime.now().date())
328
+
329
+ msg = "Value must be Period, string, integer, or datetime"
330
+ with pytest.raises(ValueError, match=msg):
331
+ Period(1.6, freq="D")
332
+ msg = "Ordinal must be an integer"
333
+ with pytest.raises(ValueError, match=msg):
334
+ Period(ordinal=1.6, freq="D")
335
+ msg = "Only value or ordinal but not both should be given but not both"
336
+ with pytest.raises(ValueError, match=msg):
337
+ Period(ordinal=2, value=1, freq="D")
338
+
339
+ msg = "If value is None, freq cannot be None"
340
+ with pytest.raises(ValueError, match=msg):
341
+ Period(month=1)
342
+
343
+ msg = '^Given date string "-2000" not likely a datetime$'
344
+ with pytest.raises(ValueError, match=msg):
345
+ Period("-2000", "Y")
346
+ if PY314:
347
+ msg = "day 0 must be in range 1..31 for month 1 in year 1: 0"
348
+ else:
349
+ msg = "day is out of range for month"
350
+ with pytest.raises(DateParseError, match=msg):
351
+ Period("0", "Y")
352
+ msg = "Unknown datetime string format, unable to parse"
353
+ with pytest.raises(DateParseError, match=msg):
354
+ Period("1/1/-2000", "Y")
355
+
356
+ def test_constructor_corner(self):
357
+ expected = Period("2007-01", freq="2M")
358
+ assert Period(year=2007, month=1, freq="2M") == expected
359
+
360
+ assert Period(None) is NaT
361
+
362
+ p = Period("2007-01-01", freq="D")
363
+
364
+ result = Period(p, freq="Y")
365
+ exp = Period("2007", freq="Y")
366
+ assert result == exp
367
+
368
+ def test_constructor_infer_freq(self):
369
+ p = Period("2007-01-01")
370
+ assert p.freq == "D"
371
+
372
+ p = Period("2007-01-01 07")
373
+ assert p.freq == "h"
374
+
375
+ p = Period("2007-01-01 07:10")
376
+ assert p.freq == "min"
377
+
378
+ p = Period("2007-01-01 07:10:15")
379
+ assert p.freq == "s"
380
+
381
+ p = Period("2007-01-01 07:10:15.123")
382
+ assert p.freq == "ms"
383
+
384
+ # We see that there are 6 digits after the decimal, so get microsecond
385
+ # even though they are all zeros.
386
+ p = Period("2007-01-01 07:10:15.123000")
387
+ assert p.freq == "us"
388
+
389
+ p = Period("2007-01-01 07:10:15.123400")
390
+ assert p.freq == "us"
391
+
392
+ def test_multiples(self):
393
+ result1 = Period("1989", freq="2Y")
394
+ result2 = Period("1989", freq="Y")
395
+ assert result1.ordinal == result2.ordinal
396
+ assert result1.freqstr == "2Y-DEC"
397
+ assert result2.freqstr == "Y-DEC"
398
+ assert result1.freq == offsets.YearEnd(2)
399
+ assert result2.freq == offsets.YearEnd()
400
+
401
+ assert (result1 + 1).ordinal == result1.ordinal + 2
402
+ assert (1 + result1).ordinal == result1.ordinal + 2
403
+ assert (result1 - 1).ordinal == result2.ordinal - 2
404
+ assert (-1 + result1).ordinal == result2.ordinal - 2
405
+
406
+ @pytest.mark.parametrize("month", MONTHS)
407
+ def test_period_cons_quarterly(self, month):
408
+ # bugs in scikits.timeseries
409
+ freq = f"Q-{month}"
410
+ exp = Period("1989Q3", freq=freq)
411
+ assert "1989Q3" in str(exp)
412
+ stamp = exp.to_timestamp("D", how="end")
413
+ p = Period(stamp, freq=freq)
414
+ assert p == exp
415
+
416
+ stamp = exp.to_timestamp("3D", how="end")
417
+ p = Period(stamp, freq=freq)
418
+ assert p == exp
419
+
420
+ @pytest.mark.parametrize("month", MONTHS)
421
+ def test_period_cons_annual(self, month):
422
+ # bugs in scikits.timeseries
423
+ freq = f"Y-{month}"
424
+ exp = Period("1989", freq=freq)
425
+ stamp = exp.to_timestamp("D", how="end") + timedelta(days=30)
426
+ p = Period(stamp, freq=freq)
427
+
428
+ assert p == exp + 1
429
+ assert isinstance(p, Period)
430
+
431
+ @pytest.mark.parametrize("day", DAYS)
432
+ @pytest.mark.parametrize("num", range(10, 17))
433
+ def test_period_cons_weekly(self, num, day):
434
+ daystr = f"2011-02-{num}"
435
+ freq = f"W-{day}"
436
+
437
+ result = Period(daystr, freq=freq)
438
+ expected = Period(daystr, freq="D").asfreq(freq)
439
+ assert result == expected
440
+ assert isinstance(result, Period)
441
+
442
+ def test_parse_week_str_roundstrip(self):
443
+ # GH#50803
444
+ per = Period("2017-01-23/2017-01-29")
445
+ assert per.freq.freqstr == "W-SUN"
446
+
447
+ per = Period("2017-01-24/2017-01-30")
448
+ assert per.freq.freqstr == "W-MON"
449
+
450
+ msg = "Could not parse as weekly-freq Period"
451
+ with pytest.raises(ValueError, match=msg):
452
+ # not 6 days apart
453
+ Period("2016-01-23/2017-01-29")
454
+
455
+ def test_period_from_ordinal(self):
456
+ p = Period("2011-01", freq="M")
457
+ res = Period._from_ordinal(p.ordinal, freq=p.freq)
458
+ assert p == res
459
+ assert isinstance(res, Period)
460
+
461
+ @pytest.mark.parametrize("freq", ["Y", "M", "D", "h"])
462
+ def test_construct_from_nat_string_and_freq(self, freq):
463
+ per = Period("NaT", freq=freq)
464
+ assert per is NaT
465
+
466
+ per = Period("NaT", freq="2" + freq)
467
+ assert per is NaT
468
+
469
+ per = Period("NaT", freq="3" + freq)
470
+ assert per is NaT
471
+
472
+ def test_period_cons_nat(self):
473
+ p = Period("nat", freq="W-SUN")
474
+ assert p is NaT
475
+
476
+ p = Period(iNaT, freq="D")
477
+ assert p is NaT
478
+
479
+ p = Period(iNaT, freq="3D")
480
+ assert p is NaT
481
+
482
+ p = Period(iNaT, freq="1D1h")
483
+ assert p is NaT
484
+
485
+ p = Period("NaT")
486
+ assert p is NaT
487
+
488
+ p = Period(iNaT)
489
+ assert p is NaT
490
+
491
+ def test_period_cons_mult(self):
492
+ p1 = Period("2011-01", freq="3M")
493
+ p2 = Period("2011-01", freq="M")
494
+ assert p1.ordinal == p2.ordinal
495
+
496
+ assert p1.freq == offsets.MonthEnd(3)
497
+ assert p1.freqstr == "3M"
498
+
499
+ assert p2.freq == offsets.MonthEnd()
500
+ assert p2.freqstr == "M"
501
+
502
+ result = p1 + 1
503
+ assert result.ordinal == (p2 + 3).ordinal
504
+
505
+ assert result.freq == p1.freq
506
+ assert result.freqstr == "3M"
507
+
508
+ result = p1 - 1
509
+ assert result.ordinal == (p2 - 3).ordinal
510
+ assert result.freq == p1.freq
511
+ assert result.freqstr == "3M"
512
+
513
+ msg = "Frequency must be positive, because it represents span: -3M"
514
+ with pytest.raises(ValueError, match=msg):
515
+ Period("2011-01", freq="-3M")
516
+
517
+ msg = "Frequency must be positive, because it represents span: 0M"
518
+ with pytest.raises(ValueError, match=msg):
519
+ Period("2011-01", freq="0M")
520
+
521
+ def test_period_cons_combined(self):
522
+ p = [
523
+ (
524
+ Period("2011-01", freq="1D1h"),
525
+ Period("2011-01", freq="1h1D"),
526
+ Period("2011-01", freq="h"),
527
+ ),
528
+ (
529
+ Period(ordinal=1, freq="1D1h"),
530
+ Period(ordinal=1, freq="1h1D"),
531
+ Period(ordinal=1, freq="h"),
532
+ ),
533
+ ]
534
+
535
+ for p1, p2, p3 in p:
536
+ assert p1.ordinal == p3.ordinal
537
+ assert p2.ordinal == p3.ordinal
538
+
539
+ assert p1.freq == offsets.Hour(25)
540
+ assert p1.freqstr == "25h"
541
+
542
+ assert p2.freq == offsets.Hour(25)
543
+ assert p2.freqstr == "25h"
544
+
545
+ assert p3.freq == offsets.Hour()
546
+ assert p3.freqstr == "h"
547
+
548
+ result = p1 + 1
549
+ assert result.ordinal == (p3 + 25).ordinal
550
+ assert result.freq == p1.freq
551
+ assert result.freqstr == "25h"
552
+
553
+ result = p2 + 1
554
+ assert result.ordinal == (p3 + 25).ordinal
555
+ assert result.freq == p2.freq
556
+ assert result.freqstr == "25h"
557
+
558
+ result = p1 - 1
559
+ assert result.ordinal == (p3 - 25).ordinal
560
+ assert result.freq == p1.freq
561
+ assert result.freqstr == "25h"
562
+
563
+ result = p2 - 1
564
+ assert result.ordinal == (p3 - 25).ordinal
565
+ assert result.freq == p2.freq
566
+ assert result.freqstr == "25h"
567
+
568
+ msg = "Frequency must be positive, because it represents span: -25h"
569
+ with pytest.raises(ValueError, match=msg):
570
+ Period("2011-01", freq="-1D1h")
571
+ with pytest.raises(ValueError, match=msg):
572
+ Period("2011-01", freq="-1h1D")
573
+ with pytest.raises(ValueError, match=msg):
574
+ Period(ordinal=1, freq="-1D1h")
575
+ with pytest.raises(ValueError, match=msg):
576
+ Period(ordinal=1, freq="-1h1D")
577
+
578
+ msg = "Frequency must be positive, because it represents span: 0D"
579
+ with pytest.raises(ValueError, match=msg):
580
+ Period("2011-01", freq="0D0h")
581
+ with pytest.raises(ValueError, match=msg):
582
+ Period(ordinal=1, freq="0D0h")
583
+
584
+ # You can only combine together day and intraday offsets
585
+ msg = "Invalid frequency: 1W1D"
586
+ with pytest.raises(ValueError, match=msg):
587
+ Period("2011-01", freq="1W1D")
588
+ msg = "Invalid frequency: 1D1W"
589
+ with pytest.raises(ValueError, match=msg):
590
+ Period("2011-01", freq="1D1W")
591
+
592
+ @pytest.mark.parametrize("day", ["1970/01/01 ", "2020-12-31 ", "1981/09/13 "])
593
+ @pytest.mark.parametrize("hour", ["00:00:00", "00:00:01", "23:59:59", "12:00:59"])
594
+ @pytest.mark.parametrize(
595
+ "sec_float, expected",
596
+ [
597
+ (".000000001", 1),
598
+ (".000000999", 999),
599
+ (".123456789", 789),
600
+ (".999999999", 999),
601
+ (".999999000", 0),
602
+ # Test femtoseconds, attoseconds, picoseconds are dropped like Timestamp
603
+ (".999999001123", 1),
604
+ (".999999001123456", 1),
605
+ (".999999001123456789", 1),
606
+ ],
607
+ )
608
+ def test_period_constructor_nanosecond(self, day, hour, sec_float, expected):
609
+ # GH 34621
610
+
611
+ assert Period(day + hour + sec_float).start_time.nanosecond == expected
612
+
613
+ @pytest.mark.parametrize("hour", range(24))
614
+ def test_period_large_ordinal(self, hour):
615
+ # Issue #36430
616
+ # Integer overflow for Period over the maximum timestamp
617
+ p = Period(ordinal=2562048 + hour, freq="1h")
618
+ assert p.hour == hour
619
+
620
+
621
+ class TestPeriodMethods:
622
+ def test_round_trip(self):
623
+ p = Period("2000Q1")
624
+ new_p = tm.round_trip_pickle(p)
625
+ assert new_p == p
626
+
627
+ def test_hash(self):
628
+ assert hash(Period("2011-01", freq="M")) == hash(Period("2011-01", freq="M"))
629
+
630
+ assert hash(Period("2011-01-01", freq="D")) != hash(Period("2011-01", freq="M"))
631
+
632
+ assert hash(Period("2011-01", freq="3M")) != hash(Period("2011-01", freq="2M"))
633
+
634
+ assert hash(Period("2011-01", freq="M")) != hash(Period("2011-02", freq="M"))
635
+
636
+ # --------------------------------------------------------------
637
+ # to_timestamp
638
+
639
+ def test_to_timestamp_mult(self):
640
+ p = Period("2011-01", freq="M")
641
+ assert p.to_timestamp(how="S") == Timestamp("2011-01-01")
642
+ expected = Timestamp("2011-02-01") - Timedelta(1, "ns")
643
+ assert p.to_timestamp(how="E") == expected
644
+
645
+ p = Period("2011-01", freq="3M")
646
+ assert p.to_timestamp(how="S") == Timestamp("2011-01-01")
647
+ expected = Timestamp("2011-04-01") - Timedelta(1, "ns")
648
+ assert p.to_timestamp(how="E") == expected
649
+
650
+ @pytest.mark.filterwarnings(
651
+ "ignore:Period with BDay freq is deprecated:FutureWarning"
652
+ )
653
+ def test_to_timestamp(self):
654
+ p = Period("1982", freq="Y")
655
+ start_ts = p.to_timestamp(how="S")
656
+ aliases = ["s", "StarT", "BEGIn"]
657
+ for a in aliases:
658
+ assert start_ts == p.to_timestamp("D", how=a)
659
+ # freq with mult should not affect to the result
660
+ assert start_ts == p.to_timestamp("3D", how=a)
661
+
662
+ end_ts = p.to_timestamp(how="E")
663
+ aliases = ["e", "end", "FINIsH"]
664
+ for a in aliases:
665
+ assert end_ts == p.to_timestamp("D", how=a)
666
+ assert end_ts == p.to_timestamp("3D", how=a)
667
+
668
+ from_lst = ["Y", "Q", "M", "W", "B", "D", "h", "Min", "s"]
669
+
670
+ def _ex(p):
671
+ if p.freq == "B":
672
+ return p.start_time + Timedelta(days=1, nanoseconds=-1)
673
+ return Timestamp((p + p.freq).start_time._value - 1)
674
+
675
+ for fcode in from_lst:
676
+ p = Period("1982", freq=fcode)
677
+ result = p.to_timestamp().to_period(fcode)
678
+ assert result == p
679
+
680
+ assert p.start_time == p.to_timestamp(how="S")
681
+
682
+ assert p.end_time == _ex(p)
683
+
684
+ # Frequency other than daily
685
+
686
+ p = Period("1985", freq="Y")
687
+
688
+ result = p.to_timestamp("h", how="end")
689
+ expected = Timestamp(1986, 1, 1) - Timedelta(1, "ns")
690
+ assert result == expected
691
+ result = p.to_timestamp("3h", how="end")
692
+ assert result == expected
693
+
694
+ result = p.to_timestamp("min", how="end")
695
+ expected = Timestamp(1986, 1, 1) - Timedelta(1, "ns")
696
+ assert result == expected
697
+ result = p.to_timestamp("2min", how="end")
698
+ assert result == expected
699
+
700
+ result = p.to_timestamp(how="end")
701
+ expected = Timestamp(1986, 1, 1) - Timedelta(1, "ns")
702
+ assert result == expected
703
+
704
+ expected = datetime(1985, 1, 1)
705
+ result = p.to_timestamp("h", how="start")
706
+ assert result == expected
707
+ result = p.to_timestamp("min", how="start")
708
+ assert result == expected
709
+ result = p.to_timestamp("s", how="start")
710
+ assert result == expected
711
+ result = p.to_timestamp("3h", how="start")
712
+ assert result == expected
713
+ result = p.to_timestamp("5s", how="start")
714
+ assert result == expected
715
+
716
+ def test_to_timestamp_business_end(self):
717
+ with tm.assert_produces_warning(FutureWarning, match=bday_msg):
718
+ per = Period("1990-01-05", "B") # Friday
719
+ result = per.to_timestamp("B", how="E")
720
+
721
+ expected = Timestamp("1990-01-06") - Timedelta(nanoseconds=1)
722
+ assert result == expected
723
+
724
+ @pytest.mark.parametrize(
725
+ "ts, expected",
726
+ [
727
+ ("1970-01-01 00:00:00", 0),
728
+ ("1970-01-01 00:00:00.000001", 1),
729
+ ("1970-01-01 00:00:00.00001", 10),
730
+ ("1970-01-01 00:00:00.499", 499000),
731
+ ("1999-12-31 23:59:59.999", 999000),
732
+ ("1999-12-31 23:59:59.999999", 999999),
733
+ ("2050-12-31 23:59:59.5", 500000),
734
+ ("2050-12-31 23:59:59.500001", 500001),
735
+ ("2050-12-31 23:59:59.123456", 123456),
736
+ ],
737
+ )
738
+ @pytest.mark.parametrize("freq", [None, "us", "ns"])
739
+ def test_to_timestamp_microsecond(self, ts, expected, freq):
740
+ # GH 24444
741
+ result = Period(ts).to_timestamp(freq=freq).microsecond
742
+ assert result == expected
743
+
744
+ # --------------------------------------------------------------
745
+ # Rendering: __repr__, strftime, etc
746
+
747
+ @pytest.mark.parametrize(
748
+ "str_ts,freq,str_res,str_freq",
749
+ (
750
+ ("Jan-2000", None, "2000-01", "M"),
751
+ ("2000-12-15", None, "2000-12-15", "D"),
752
+ (
753
+ "2000-12-15 13:45:26.123456789",
754
+ "ns",
755
+ "2000-12-15 13:45:26.123456789",
756
+ "ns",
757
+ ),
758
+ ("2000-12-15 13:45:26.123456789", "us", "2000-12-15 13:45:26.123456", "us"),
759
+ ("2000-12-15 13:45:26.123456", None, "2000-12-15 13:45:26.123456", "us"),
760
+ ("2000-12-15 13:45:26.123456789", "ms", "2000-12-15 13:45:26.123", "ms"),
761
+ ("2000-12-15 13:45:26.123", None, "2000-12-15 13:45:26.123", "ms"),
762
+ ("2000-12-15 13:45:26", "s", "2000-12-15 13:45:26", "s"),
763
+ ("2000-12-15 13:45:26", "min", "2000-12-15 13:45", "min"),
764
+ ("2000-12-15 13:45:26", "h", "2000-12-15 13:00", "h"),
765
+ ("2000-12-15", "Y", "2000", "Y-DEC"),
766
+ ("2000-12-15", "Q", "2000Q4", "Q-DEC"),
767
+ ("2000-12-15", "M", "2000-12", "M"),
768
+ ("2000-12-15", "W", "2000-12-11/2000-12-17", "W-SUN"),
769
+ ("2000-12-15", "D", "2000-12-15", "D"),
770
+ ("2000-12-15", "B", "2000-12-15", "B"),
771
+ ),
772
+ )
773
+ @pytest.mark.filterwarnings(
774
+ "ignore:Period with BDay freq is deprecated:FutureWarning"
775
+ )
776
+ def test_repr(self, str_ts, freq, str_res, str_freq):
777
+ p = Period(str_ts, freq=freq)
778
+ assert str(p) == str_res
779
+ assert repr(p) == f"Period('{str_res}', '{str_freq}')"
780
+
781
+ def test_repr_nat(self):
782
+ p = Period("nat", freq="M")
783
+ assert repr(NaT) in repr(p)
784
+
785
+ def test_strftime(self):
786
+ # GH#3363
787
+ p = Period("2000-1-1 12:34:12", freq="s")
788
+ res = p.strftime("%Y-%m-%d %H:%M:%S")
789
+ assert res == "2000-01-01 12:34:12"
790
+ assert isinstance(res, str)
791
+
792
+
793
+ class TestPeriodProperties:
794
+ """Test properties such as year, month, weekday, etc...."""
795
+
796
+ @pytest.mark.parametrize("freq", ["Y", "M", "D", "h"])
797
+ def test_is_leap_year(self, freq):
798
+ # GH 13727
799
+ p = Period("2000-01-01 00:00:00", freq=freq)
800
+ assert p.is_leap_year
801
+ assert isinstance(p.is_leap_year, bool)
802
+
803
+ p = Period("1999-01-01 00:00:00", freq=freq)
804
+ assert not p.is_leap_year
805
+
806
+ p = Period("2004-01-01 00:00:00", freq=freq)
807
+ assert p.is_leap_year
808
+
809
+ p = Period("2100-01-01 00:00:00", freq=freq)
810
+ assert not p.is_leap_year
811
+
812
+ def test_quarterly_negative_ordinals(self):
813
+ p = Period(ordinal=-1, freq="Q-DEC")
814
+ assert p.year == 1969
815
+ assert p.quarter == 4
816
+ assert isinstance(p, Period)
817
+
818
+ p = Period(ordinal=-2, freq="Q-DEC")
819
+ assert p.year == 1969
820
+ assert p.quarter == 3
821
+ assert isinstance(p, Period)
822
+
823
+ p = Period(ordinal=-2, freq="M")
824
+ assert p.year == 1969
825
+ assert p.month == 11
826
+ assert isinstance(p, Period)
827
+
828
+ def test_freq_str(self):
829
+ i1 = Period("1982", freq="Min")
830
+ assert i1.freq == offsets.Minute()
831
+ assert i1.freqstr == "min"
832
+
833
+ @pytest.mark.filterwarnings(
834
+ "ignore:Period with BDay freq is deprecated:FutureWarning"
835
+ )
836
+ def test_period_deprecated_freq(self):
837
+ cases = {
838
+ "M": ["MTH", "MONTH", "MONTHLY", "Mth", "month", "monthly"],
839
+ "B": ["BUS", "BUSINESS", "BUSINESSLY", "WEEKDAY", "bus"],
840
+ "D": ["DAY", "DLY", "DAILY", "Day", "Dly", "Daily"],
841
+ "h": ["HR", "HOUR", "HRLY", "HOURLY", "hr", "Hour", "HRly"],
842
+ "min": ["minute", "MINUTE", "MINUTELY", "minutely"],
843
+ "s": ["sec", "SEC", "SECOND", "SECONDLY", "second"],
844
+ "ms": ["MILLISECOND", "MILLISECONDLY", "millisecond"],
845
+ "us": ["MICROSECOND", "MICROSECONDLY", "microsecond"],
846
+ "ns": ["NANOSECOND", "NANOSECONDLY", "nanosecond"],
847
+ }
848
+
849
+ msg = INVALID_FREQ_ERR_MSG
850
+ for exp, freqs in cases.items():
851
+ for freq in freqs:
852
+ with pytest.raises(ValueError, match=msg):
853
+ Period("2016-03-01 09:00", freq=freq)
854
+ with pytest.raises(ValueError, match=msg):
855
+ Period(ordinal=1, freq=freq)
856
+
857
+ # check supported freq-aliases still works
858
+ p1 = Period("2016-03-01 09:00", freq=exp)
859
+ p2 = Period(ordinal=1, freq=exp)
860
+ assert isinstance(p1, Period)
861
+ assert isinstance(p2, Period)
862
+
863
+ @staticmethod
864
+ def _period_constructor(bound, offset):
865
+ return Period(
866
+ year=bound.year,
867
+ month=bound.month,
868
+ day=bound.day,
869
+ hour=bound.hour,
870
+ minute=bound.minute,
871
+ second=bound.second + offset,
872
+ freq="us",
873
+ )
874
+
875
+ @pytest.mark.parametrize("bound, offset", [(Timestamp.min, -1), (Timestamp.max, 1)])
876
+ @pytest.mark.parametrize("period_property", ["start_time", "end_time"])
877
+ def test_outer_bounds_start_and_end_time(self, bound, offset, period_property):
878
+ # GH #13346
879
+ period = TestPeriodProperties._period_constructor(bound, offset)
880
+ with pytest.raises(OutOfBoundsDatetime, match="Out of bounds nanosecond"):
881
+ getattr(period, period_property)
882
+
883
+ @pytest.mark.parametrize("bound, offset", [(Timestamp.min, -1), (Timestamp.max, 1)])
884
+ @pytest.mark.parametrize("period_property", ["start_time", "end_time"])
885
+ def test_inner_bounds_start_and_end_time(self, bound, offset, period_property):
886
+ # GH #13346
887
+ period = TestPeriodProperties._period_constructor(bound, -offset)
888
+ expected = period.to_timestamp().round(freq="s")
889
+ assert getattr(period, period_property).round(freq="s") == expected
890
+ expected = (bound - offset * Timedelta(1, unit="s")).floor("s")
891
+ assert getattr(period, period_property).floor("s") == expected
892
+
893
+ def test_start_time(self):
894
+ freq_lst = ["Y", "Q", "M", "D", "h", "min", "s"]
895
+ xp = datetime(2012, 1, 1)
896
+ for f in freq_lst:
897
+ p = Period("2012", freq=f)
898
+ assert p.start_time == xp
899
+ with tm.assert_produces_warning(FutureWarning, match=bday_msg):
900
+ assert Period("2012", freq="B").start_time == datetime(2012, 1, 2)
901
+ assert Period("2012", freq="W").start_time == datetime(2011, 12, 26)
902
+
903
+ def test_end_time(self):
904
+ p = Period("2012", freq="Y")
905
+
906
+ def _ex(*args):
907
+ return Timestamp(Timestamp(datetime(*args)).as_unit("ns")._value - 1)
908
+
909
+ xp = _ex(2013, 1, 1)
910
+ assert xp == p.end_time
911
+
912
+ p = Period("2012", freq="Q")
913
+ xp = _ex(2012, 4, 1)
914
+ assert xp == p.end_time
915
+
916
+ p = Period("2012", freq="M")
917
+ xp = _ex(2012, 2, 1)
918
+ assert xp == p.end_time
919
+
920
+ p = Period("2012", freq="D")
921
+ xp = _ex(2012, 1, 2)
922
+ assert xp == p.end_time
923
+
924
+ p = Period("2012", freq="h")
925
+ xp = _ex(2012, 1, 1, 1)
926
+ assert xp == p.end_time
927
+
928
+ with tm.assert_produces_warning(FutureWarning, match=bday_msg):
929
+ p = Period("2012", freq="B")
930
+ xp = _ex(2012, 1, 3)
931
+ assert xp == p.end_time
932
+
933
+ p = Period("2012", freq="W")
934
+ xp = _ex(2012, 1, 2)
935
+ assert xp == p.end_time
936
+
937
+ # Test for GH 11738
938
+ p = Period("2012", freq="15D")
939
+ xp = _ex(2012, 1, 16)
940
+ assert xp == p.end_time
941
+
942
+ p = Period("2012", freq="1D1h")
943
+ xp = _ex(2012, 1, 2, 1)
944
+ assert xp == p.end_time
945
+
946
+ p = Period("2012", freq="1h1D")
947
+ xp = _ex(2012, 1, 2, 1)
948
+ assert xp == p.end_time
949
+
950
+ def test_end_time_business_friday(self):
951
+ # GH#34449
952
+ with tm.assert_produces_warning(FutureWarning, match=bday_msg):
953
+ per = Period("1990-01-05", "B")
954
+ result = per.end_time
955
+
956
+ expected = Timestamp("1990-01-06") - Timedelta(nanoseconds=1)
957
+ assert result == expected
958
+
959
+ def test_anchor_week_end_time(self):
960
+ def _ex(*args):
961
+ return Timestamp(Timestamp(datetime(*args)).as_unit("ns")._value - 1)
962
+
963
+ p = Period("2013-1-1", "W-SAT")
964
+ xp = _ex(2013, 1, 6)
965
+ assert p.end_time == xp
966
+
967
+ def test_properties_annually(self):
968
+ # Test properties on Periods with annually frequency.
969
+ a_date = Period(freq="Y", year=2007)
970
+ assert a_date.year == 2007
971
+
972
+ def test_properties_quarterly(self):
973
+ # Test properties on Periods with daily frequency.
974
+ qedec_date = Period(freq="Q-DEC", year=2007, quarter=1)
975
+ qejan_date = Period(freq="Q-JAN", year=2007, quarter=1)
976
+ qejun_date = Period(freq="Q-JUN", year=2007, quarter=1)
977
+ #
978
+ for x in range(3):
979
+ for qd in (qedec_date, qejan_date, qejun_date):
980
+ assert (qd + x).qyear == 2007
981
+ assert (qd + x).quarter == x + 1
982
+
983
+ def test_properties_monthly(self):
984
+ # Test properties on Periods with daily frequency.
985
+ m_date = Period(freq="M", year=2007, month=1)
986
+ for x in range(11):
987
+ m_ival_x = m_date + x
988
+ assert m_ival_x.year == 2007
989
+ if 1 <= x + 1 <= 3:
990
+ assert m_ival_x.quarter == 1
991
+ elif 4 <= x + 1 <= 6:
992
+ assert m_ival_x.quarter == 2
993
+ elif 7 <= x + 1 <= 9:
994
+ assert m_ival_x.quarter == 3
995
+ elif 10 <= x + 1 <= 12:
996
+ assert m_ival_x.quarter == 4
997
+ assert m_ival_x.month == x + 1
998
+
999
+ def test_properties_weekly(self):
1000
+ # Test properties on Periods with daily frequency.
1001
+ w_date = Period(freq="W", year=2007, month=1, day=7)
1002
+ #
1003
+ assert w_date.year == 2007
1004
+ assert w_date.quarter == 1
1005
+ assert w_date.month == 1
1006
+ assert w_date.week == 1
1007
+ assert (w_date - 1).week == 52
1008
+ assert w_date.days_in_month == 31
1009
+ assert Period(freq="W", year=2012, month=2, day=1).days_in_month == 29
1010
+
1011
+ def test_properties_weekly_legacy(self):
1012
+ # Test properties on Periods with daily frequency.
1013
+ w_date = Period(freq="W", year=2007, month=1, day=7)
1014
+ assert w_date.year == 2007
1015
+ assert w_date.quarter == 1
1016
+ assert w_date.month == 1
1017
+ assert w_date.week == 1
1018
+ assert (w_date - 1).week == 52
1019
+ assert w_date.days_in_month == 31
1020
+
1021
+ exp = Period(freq="W", year=2012, month=2, day=1)
1022
+ assert exp.days_in_month == 29
1023
+
1024
+ msg = INVALID_FREQ_ERR_MSG
1025
+ with pytest.raises(ValueError, match=msg):
1026
+ Period(freq="WK", year=2007, month=1, day=7)
1027
+
1028
+ def test_properties_daily(self):
1029
+ # Test properties on Periods with daily frequency.
1030
+ with tm.assert_produces_warning(FutureWarning, match=bday_msg):
1031
+ b_date = Period(freq="B", year=2007, month=1, day=1)
1032
+ #
1033
+ assert b_date.year == 2007
1034
+ assert b_date.quarter == 1
1035
+ assert b_date.month == 1
1036
+ assert b_date.day == 1
1037
+ assert b_date.weekday == 0
1038
+ assert b_date.dayofyear == 1
1039
+ assert b_date.days_in_month == 31
1040
+ with tm.assert_produces_warning(FutureWarning, match=bday_msg):
1041
+ assert Period(freq="B", year=2012, month=2, day=1).days_in_month == 29
1042
+
1043
+ d_date = Period(freq="D", year=2007, month=1, day=1)
1044
+
1045
+ assert d_date.year == 2007
1046
+ assert d_date.quarter == 1
1047
+ assert d_date.month == 1
1048
+ assert d_date.day == 1
1049
+ assert d_date.weekday == 0
1050
+ assert d_date.dayofyear == 1
1051
+ assert d_date.days_in_month == 31
1052
+ assert Period(freq="D", year=2012, month=2, day=1).days_in_month == 29
1053
+
1054
+ def test_properties_hourly(self):
1055
+ # Test properties on Periods with hourly frequency.
1056
+ h_date1 = Period(freq="h", year=2007, month=1, day=1, hour=0)
1057
+ h_date2 = Period(freq="2h", year=2007, month=1, day=1, hour=0)
1058
+
1059
+ for h_date in [h_date1, h_date2]:
1060
+ assert h_date.year == 2007
1061
+ assert h_date.quarter == 1
1062
+ assert h_date.month == 1
1063
+ assert h_date.day == 1
1064
+ assert h_date.weekday == 0
1065
+ assert h_date.dayofyear == 1
1066
+ assert h_date.hour == 0
1067
+ assert h_date.days_in_month == 31
1068
+ assert (
1069
+ Period(freq="h", year=2012, month=2, day=1, hour=0).days_in_month == 29
1070
+ )
1071
+
1072
+ def test_properties_minutely(self):
1073
+ # Test properties on Periods with minutely frequency.
1074
+ t_date = Period(freq="Min", year=2007, month=1, day=1, hour=0, minute=0)
1075
+ #
1076
+ assert t_date.quarter == 1
1077
+ assert t_date.month == 1
1078
+ assert t_date.day == 1
1079
+ assert t_date.weekday == 0
1080
+ assert t_date.dayofyear == 1
1081
+ assert t_date.hour == 0
1082
+ assert t_date.minute == 0
1083
+ assert t_date.days_in_month == 31
1084
+ assert (
1085
+ Period(freq="D", year=2012, month=2, day=1, hour=0, minute=0).days_in_month
1086
+ == 29
1087
+ )
1088
+
1089
+ def test_properties_secondly(self):
1090
+ # Test properties on Periods with secondly frequency.
1091
+ s_date = Period(
1092
+ freq="Min", year=2007, month=1, day=1, hour=0, minute=0, second=0
1093
+ )
1094
+ #
1095
+ assert s_date.year == 2007
1096
+ assert s_date.quarter == 1
1097
+ assert s_date.month == 1
1098
+ assert s_date.day == 1
1099
+ assert s_date.weekday == 0
1100
+ assert s_date.dayofyear == 1
1101
+ assert s_date.hour == 0
1102
+ assert s_date.minute == 0
1103
+ assert s_date.second == 0
1104
+ assert s_date.days_in_month == 31
1105
+ assert (
1106
+ Period(
1107
+ freq="Min", year=2012, month=2, day=1, hour=0, minute=0, second=0
1108
+ ).days_in_month
1109
+ == 29
1110
+ )
1111
+
1112
+
1113
+ class TestPeriodComparisons:
1114
+ def test_sort_periods(self):
1115
+ jan = Period("2000-01", "M")
1116
+ feb = Period("2000-02", "M")
1117
+ mar = Period("2000-03", "M")
1118
+ periods = [mar, jan, feb]
1119
+ correctPeriods = [jan, feb, mar]
1120
+ assert sorted(periods) == correctPeriods
1121
+
1122
+
1123
+ def test_period_immutable():
1124
+ # see gh-17116
1125
+ msg = "not writable"
1126
+
1127
+ per = Period("2014Q1")
1128
+ with pytest.raises(AttributeError, match=msg):
1129
+ per.ordinal = 14
1130
+
1131
+ freq = per.freq
1132
+ with pytest.raises(AttributeError, match=msg):
1133
+ per.freq = 2 * freq
1134
+
1135
+
1136
+ def test_small_year_parsing():
1137
+ per1 = Period("0001-01-07", "D")
1138
+ assert per1.year == 1
1139
+ assert per1.day == 7
1140
+
1141
+
1142
+ def test_negone_ordinals():
1143
+ freqs = ["Y", "M", "Q", "D", "h", "min", "s"]
1144
+
1145
+ period = Period(ordinal=-1, freq="D")
1146
+ for freq in freqs:
1147
+ repr(period.asfreq(freq))
1148
+
1149
+ for freq in freqs:
1150
+ period = Period(ordinal=-1, freq=freq)
1151
+ repr(period)
1152
+ assert period.year == 1969
1153
+
1154
+ with tm.assert_produces_warning(FutureWarning, match=bday_msg):
1155
+ period = Period(ordinal=-1, freq="B")
1156
+ repr(period)
1157
+ period = Period(ordinal=-1, freq="W")
1158
+ repr(period)
py311/lib/python3.11/site-packages/pandas/tests/scalar/timedelta/__init__.py ADDED
File without changes
py311/lib/python3.11/site-packages/pandas/tests/scalar/timedelta/methods/__init__.py ADDED
File without changes
py311/lib/python3.11/site-packages/pandas/tests/scalar/timedelta/methods/test_as_unit.py ADDED
@@ -0,0 +1,80 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import pytest
2
+
3
+ from pandas._libs.tslibs.dtypes import NpyDatetimeUnit
4
+ from pandas.errors import OutOfBoundsTimedelta
5
+
6
+ from pandas import Timedelta
7
+
8
+
9
+ class TestAsUnit:
10
+ def test_as_unit(self):
11
+ td = Timedelta(days=1)
12
+
13
+ assert td.as_unit("ns") is td
14
+
15
+ res = td.as_unit("us")
16
+ assert res._value == td._value // 1000
17
+ assert res._creso == NpyDatetimeUnit.NPY_FR_us.value
18
+
19
+ rt = res.as_unit("ns")
20
+ assert rt._value == td._value
21
+ assert rt._creso == td._creso
22
+
23
+ res = td.as_unit("ms")
24
+ assert res._value == td._value // 1_000_000
25
+ assert res._creso == NpyDatetimeUnit.NPY_FR_ms.value
26
+
27
+ rt = res.as_unit("ns")
28
+ assert rt._value == td._value
29
+ assert rt._creso == td._creso
30
+
31
+ res = td.as_unit("s")
32
+ assert res._value == td._value // 1_000_000_000
33
+ assert res._creso == NpyDatetimeUnit.NPY_FR_s.value
34
+
35
+ rt = res.as_unit("ns")
36
+ assert rt._value == td._value
37
+ assert rt._creso == td._creso
38
+
39
+ def test_as_unit_overflows(self):
40
+ # microsecond that would be just out of bounds for nano
41
+ us = 9223372800000000
42
+ td = Timedelta._from_value_and_reso(us, NpyDatetimeUnit.NPY_FR_us.value)
43
+
44
+ msg = "Cannot cast 106752 days 00:00:00 to unit='ns' without overflow"
45
+ with pytest.raises(OutOfBoundsTimedelta, match=msg):
46
+ td.as_unit("ns")
47
+
48
+ res = td.as_unit("ms")
49
+ assert res._value == us // 1000
50
+ assert res._creso == NpyDatetimeUnit.NPY_FR_ms.value
51
+
52
+ def test_as_unit_rounding(self):
53
+ td = Timedelta(microseconds=1500)
54
+ res = td.as_unit("ms")
55
+
56
+ expected = Timedelta(milliseconds=1)
57
+ assert res == expected
58
+
59
+ assert res._creso == NpyDatetimeUnit.NPY_FR_ms.value
60
+ assert res._value == 1
61
+
62
+ with pytest.raises(ValueError, match="Cannot losslessly convert units"):
63
+ td.as_unit("ms", round_ok=False)
64
+
65
+ def test_as_unit_non_nano(self):
66
+ # case where we are going neither to nor from nano
67
+ td = Timedelta(days=1).as_unit("ms")
68
+ assert td.days == 1
69
+ assert td._value == 86_400_000
70
+ assert td.components.days == 1
71
+ assert td._d == 1
72
+ assert td.total_seconds() == 86400
73
+
74
+ res = td.as_unit("us")
75
+ assert res._value == 86_400_000_000
76
+ assert res.components.days == 1
77
+ assert res.components.hours == 0
78
+ assert res._d == 1
79
+ assert res._h == 0
80
+ assert res.total_seconds() == 86400
py311/lib/python3.11/site-packages/pandas/tests/scalar/timedelta/methods/test_round.py ADDED
@@ -0,0 +1,187 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from hypothesis import (
2
+ given,
3
+ strategies as st,
4
+ )
5
+ import numpy as np
6
+ import pytest
7
+
8
+ from pandas._libs import lib
9
+ from pandas._libs.tslibs import iNaT
10
+ from pandas.errors import OutOfBoundsTimedelta
11
+
12
+ from pandas import Timedelta
13
+
14
+
15
+ class TestTimedeltaRound:
16
+ @pytest.mark.parametrize(
17
+ "freq,s1,s2",
18
+ [
19
+ # This first case has s1, s2 being the same as t1,t2 below
20
+ (
21
+ "ns",
22
+ Timedelta("1 days 02:34:56.789123456"),
23
+ Timedelta("-1 days 02:34:56.789123456"),
24
+ ),
25
+ (
26
+ "us",
27
+ Timedelta("1 days 02:34:56.789123000"),
28
+ Timedelta("-1 days 02:34:56.789123000"),
29
+ ),
30
+ (
31
+ "ms",
32
+ Timedelta("1 days 02:34:56.789000000"),
33
+ Timedelta("-1 days 02:34:56.789000000"),
34
+ ),
35
+ ("s", Timedelta("1 days 02:34:57"), Timedelta("-1 days 02:34:57")),
36
+ ("2s", Timedelta("1 days 02:34:56"), Timedelta("-1 days 02:34:56")),
37
+ ("5s", Timedelta("1 days 02:34:55"), Timedelta("-1 days 02:34:55")),
38
+ ("min", Timedelta("1 days 02:35:00"), Timedelta("-1 days 02:35:00")),
39
+ ("12min", Timedelta("1 days 02:36:00"), Timedelta("-1 days 02:36:00")),
40
+ ("h", Timedelta("1 days 03:00:00"), Timedelta("-1 days 03:00:00")),
41
+ ("d", Timedelta("1 days"), Timedelta("-1 days")),
42
+ ],
43
+ )
44
+ def test_round(self, freq, s1, s2):
45
+ t1 = Timedelta("1 days 02:34:56.789123456")
46
+ t2 = Timedelta("-1 days 02:34:56.789123456")
47
+
48
+ r1 = t1.round(freq)
49
+ assert r1 == s1
50
+ r2 = t2.round(freq)
51
+ assert r2 == s2
52
+
53
+ def test_round_invalid(self):
54
+ t1 = Timedelta("1 days 02:34:56.789123456")
55
+
56
+ for freq, msg in [
57
+ ("YE", "<YearEnd: month=12> is a non-fixed frequency"),
58
+ ("ME", "<MonthEnd> is a non-fixed frequency"),
59
+ ("foobar", "Invalid frequency: foobar"),
60
+ ]:
61
+ with pytest.raises(ValueError, match=msg):
62
+ t1.round(freq)
63
+
64
+ @pytest.mark.skip_ubsan
65
+ def test_round_implementation_bounds(self):
66
+ # See also: analogous test for Timestamp
67
+ # GH#38964
68
+ result = Timedelta.min.ceil("s")
69
+ expected = Timedelta.min + Timedelta(seconds=1) - Timedelta(145224193)
70
+ assert result == expected
71
+
72
+ result = Timedelta.max.floor("s")
73
+ expected = Timedelta.max - Timedelta(854775807)
74
+ assert result == expected
75
+
76
+ msg = (
77
+ r"Cannot round -106752 days \+00:12:43.145224193 to freq=s without overflow"
78
+ )
79
+ with pytest.raises(OutOfBoundsTimedelta, match=msg):
80
+ Timedelta.min.floor("s")
81
+ with pytest.raises(OutOfBoundsTimedelta, match=msg):
82
+ Timedelta.min.round("s")
83
+
84
+ msg = "Cannot round 106751 days 23:47:16.854775807 to freq=s without overflow"
85
+ with pytest.raises(OutOfBoundsTimedelta, match=msg):
86
+ Timedelta.max.ceil("s")
87
+ with pytest.raises(OutOfBoundsTimedelta, match=msg):
88
+ Timedelta.max.round("s")
89
+
90
+ @pytest.mark.skip_ubsan
91
+ @given(val=st.integers(min_value=iNaT + 1, max_value=lib.i8max))
92
+ @pytest.mark.parametrize(
93
+ "method", [Timedelta.round, Timedelta.floor, Timedelta.ceil]
94
+ )
95
+ def test_round_sanity(self, val, method):
96
+ cls = Timedelta
97
+ err_cls = OutOfBoundsTimedelta
98
+
99
+ val = np.int64(val)
100
+ td = cls(val)
101
+
102
+ def checker(ts, nanos, unit):
103
+ # First check that we do raise in cases where we should
104
+ if nanos == 1:
105
+ pass
106
+ else:
107
+ div, mod = divmod(ts._value, nanos)
108
+ diff = int(nanos - mod)
109
+ lb = ts._value - mod
110
+ assert lb <= ts._value # i.e. no overflows with python ints
111
+ ub = ts._value + diff
112
+ assert ub > ts._value # i.e. no overflows with python ints
113
+
114
+ msg = "without overflow"
115
+ if mod == 0:
116
+ # We should never be raising in this
117
+ pass
118
+ elif method is cls.ceil:
119
+ if ub > cls.max._value:
120
+ with pytest.raises(err_cls, match=msg):
121
+ method(ts, unit)
122
+ return
123
+ elif method is cls.floor:
124
+ if lb < cls.min._value:
125
+ with pytest.raises(err_cls, match=msg):
126
+ method(ts, unit)
127
+ return
128
+ elif mod >= diff:
129
+ if ub > cls.max._value:
130
+ with pytest.raises(err_cls, match=msg):
131
+ method(ts, unit)
132
+ return
133
+ elif lb < cls.min._value:
134
+ with pytest.raises(err_cls, match=msg):
135
+ method(ts, unit)
136
+ return
137
+
138
+ res = method(ts, unit)
139
+
140
+ td = res - ts
141
+ diff = abs(td._value)
142
+ assert diff < nanos
143
+ assert res._value % nanos == 0
144
+
145
+ if method is cls.round:
146
+ assert diff <= nanos / 2
147
+ elif method is cls.floor:
148
+ assert res <= ts
149
+ elif method is cls.ceil:
150
+ assert res >= ts
151
+
152
+ nanos = 1
153
+ checker(td, nanos, "ns")
154
+
155
+ nanos = 1000
156
+ checker(td, nanos, "us")
157
+
158
+ nanos = 1_000_000
159
+ checker(td, nanos, "ms")
160
+
161
+ nanos = 1_000_000_000
162
+ checker(td, nanos, "s")
163
+
164
+ nanos = 60 * 1_000_000_000
165
+ checker(td, nanos, "min")
166
+
167
+ nanos = 60 * 60 * 1_000_000_000
168
+ checker(td, nanos, "h")
169
+
170
+ nanos = 24 * 60 * 60 * 1_000_000_000
171
+ checker(td, nanos, "D")
172
+
173
+ @pytest.mark.parametrize("unit", ["ns", "us", "ms", "s"])
174
+ def test_round_non_nano(self, unit):
175
+ td = Timedelta("1 days 02:34:57").as_unit(unit)
176
+
177
+ res = td.round("min")
178
+ assert res == Timedelta("1 days 02:35:00")
179
+ assert res._creso == td._creso
180
+
181
+ res = td.floor("min")
182
+ assert res == Timedelta("1 days 02:34:00")
183
+ assert res._creso == td._creso
184
+
185
+ res = td.ceil("min")
186
+ assert res == Timedelta("1 days 02:35:00")
187
+ assert res._creso == td._creso
py311/lib/python3.11/site-packages/pandas/tests/scalar/timedelta/test_arithmetic.py ADDED
@@ -0,0 +1,1183 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ Tests for scalar Timedelta arithmetic ops
3
+ """
4
+ from datetime import (
5
+ datetime,
6
+ timedelta,
7
+ )
8
+ import operator
9
+
10
+ import numpy as np
11
+ import pytest
12
+
13
+ from pandas.errors import OutOfBoundsTimedelta
14
+
15
+ import pandas as pd
16
+ from pandas import (
17
+ NaT,
18
+ Timedelta,
19
+ Timestamp,
20
+ offsets,
21
+ )
22
+ import pandas._testing as tm
23
+ from pandas.core import ops
24
+
25
+
26
+ class TestTimedeltaAdditionSubtraction:
27
+ """
28
+ Tests for Timedelta methods:
29
+
30
+ __add__, __radd__,
31
+ __sub__, __rsub__
32
+ """
33
+
34
+ @pytest.mark.parametrize(
35
+ "ten_seconds",
36
+ [
37
+ Timedelta(10, unit="s"),
38
+ timedelta(seconds=10),
39
+ np.timedelta64(10, "s"),
40
+ np.timedelta64(10000000000, "ns"),
41
+ offsets.Second(10),
42
+ ],
43
+ )
44
+ def test_td_add_sub_ten_seconds(self, ten_seconds):
45
+ # GH#6808
46
+ base = Timestamp("20130101 09:01:12.123456")
47
+ expected_add = Timestamp("20130101 09:01:22.123456")
48
+ expected_sub = Timestamp("20130101 09:01:02.123456")
49
+
50
+ result = base + ten_seconds
51
+ assert result == expected_add
52
+
53
+ result = base - ten_seconds
54
+ assert result == expected_sub
55
+
56
+ @pytest.mark.parametrize(
57
+ "one_day_ten_secs",
58
+ [
59
+ Timedelta("1 day, 00:00:10"),
60
+ Timedelta("1 days, 00:00:10"),
61
+ timedelta(days=1, seconds=10),
62
+ np.timedelta64(1, "D") + np.timedelta64(10, "s"),
63
+ offsets.Day() + offsets.Second(10),
64
+ ],
65
+ )
66
+ def test_td_add_sub_one_day_ten_seconds(self, one_day_ten_secs):
67
+ # GH#6808
68
+ base = Timestamp("20130102 09:01:12.123456")
69
+ expected_add = Timestamp("20130103 09:01:22.123456")
70
+ expected_sub = Timestamp("20130101 09:01:02.123456")
71
+
72
+ result = base + one_day_ten_secs
73
+ assert result == expected_add
74
+
75
+ result = base - one_day_ten_secs
76
+ assert result == expected_sub
77
+
78
+ @pytest.mark.parametrize("op", [operator.add, ops.radd])
79
+ def test_td_add_datetimelike_scalar(self, op):
80
+ # GH#19738
81
+ td = Timedelta(10, unit="d")
82
+
83
+ result = op(td, datetime(2016, 1, 1))
84
+ if op is operator.add:
85
+ # datetime + Timedelta does _not_ call Timedelta.__radd__,
86
+ # so we get a datetime back instead of a Timestamp
87
+ assert isinstance(result, Timestamp)
88
+ assert result == Timestamp(2016, 1, 11)
89
+
90
+ result = op(td, Timestamp("2018-01-12 18:09"))
91
+ assert isinstance(result, Timestamp)
92
+ assert result == Timestamp("2018-01-22 18:09")
93
+
94
+ result = op(td, np.datetime64("2018-01-12"))
95
+ assert isinstance(result, Timestamp)
96
+ assert result == Timestamp("2018-01-22")
97
+
98
+ result = op(td, NaT)
99
+ assert result is NaT
100
+
101
+ def test_td_add_timestamp_overflow(self):
102
+ ts = Timestamp("1700-01-01").as_unit("ns")
103
+ msg = "Cannot cast 259987 from D to 'ns' without overflow."
104
+ with pytest.raises(OutOfBoundsTimedelta, match=msg):
105
+ ts + Timedelta(13 * 19999, unit="D")
106
+
107
+ msg = "Cannot cast 259987 days 00:00:00 to unit='ns' without overflow"
108
+ with pytest.raises(OutOfBoundsTimedelta, match=msg):
109
+ ts + timedelta(days=13 * 19999)
110
+
111
+ @pytest.mark.parametrize("op", [operator.add, ops.radd])
112
+ def test_td_add_td(self, op):
113
+ td = Timedelta(10, unit="d")
114
+
115
+ result = op(td, Timedelta(days=10))
116
+ assert isinstance(result, Timedelta)
117
+ assert result == Timedelta(days=20)
118
+
119
+ @pytest.mark.parametrize("op", [operator.add, ops.radd])
120
+ def test_td_add_pytimedelta(self, op):
121
+ td = Timedelta(10, unit="d")
122
+ result = op(td, timedelta(days=9))
123
+ assert isinstance(result, Timedelta)
124
+ assert result == Timedelta(days=19)
125
+
126
+ @pytest.mark.parametrize("op", [operator.add, ops.radd])
127
+ def test_td_add_timedelta64(self, op):
128
+ td = Timedelta(10, unit="d")
129
+ result = op(td, np.timedelta64(-4, "D"))
130
+ assert isinstance(result, Timedelta)
131
+ assert result == Timedelta(days=6)
132
+
133
+ @pytest.mark.parametrize("op", [operator.add, ops.radd])
134
+ def test_td_add_offset(self, op):
135
+ td = Timedelta(10, unit="d")
136
+
137
+ result = op(td, offsets.Hour(6))
138
+ assert isinstance(result, Timedelta)
139
+ assert result == Timedelta(days=10, hours=6)
140
+
141
+ def test_td_sub_td(self):
142
+ td = Timedelta(10, unit="d")
143
+ expected = Timedelta(0, unit="ns")
144
+ result = td - td
145
+ assert isinstance(result, Timedelta)
146
+ assert result == expected
147
+
148
+ def test_td_sub_pytimedelta(self):
149
+ td = Timedelta(10, unit="d")
150
+ expected = Timedelta(0, unit="ns")
151
+
152
+ result = td - td.to_pytimedelta()
153
+ assert isinstance(result, Timedelta)
154
+ assert result == expected
155
+
156
+ result = td.to_pytimedelta() - td
157
+ assert isinstance(result, Timedelta)
158
+ assert result == expected
159
+
160
+ def test_td_sub_timedelta64(self):
161
+ td = Timedelta(10, unit="d")
162
+ expected = Timedelta(0, unit="ns")
163
+
164
+ result = td - td.to_timedelta64()
165
+ assert isinstance(result, Timedelta)
166
+ assert result == expected
167
+
168
+ result = td.to_timedelta64() - td
169
+ assert isinstance(result, Timedelta)
170
+ assert result == expected
171
+
172
+ def test_td_sub_nat(self):
173
+ # In this context pd.NaT is treated as timedelta-like
174
+ td = Timedelta(10, unit="d")
175
+ result = td - NaT
176
+ assert result is NaT
177
+
178
+ def test_td_sub_td64_nat(self):
179
+ td = Timedelta(10, unit="d")
180
+ td_nat = np.timedelta64("NaT")
181
+
182
+ result = td - td_nat
183
+ assert result is NaT
184
+
185
+ result = td_nat - td
186
+ assert result is NaT
187
+
188
+ def test_td_sub_offset(self):
189
+ td = Timedelta(10, unit="d")
190
+ result = td - offsets.Hour(1)
191
+ assert isinstance(result, Timedelta)
192
+ assert result == Timedelta(239, unit="h")
193
+
194
+ def test_td_add_sub_numeric_raises(self):
195
+ td = Timedelta(10, unit="d")
196
+ msg = "unsupported operand type"
197
+ for other in [2, 2.0, np.int64(2), np.float64(2)]:
198
+ with pytest.raises(TypeError, match=msg):
199
+ td + other
200
+ with pytest.raises(TypeError, match=msg):
201
+ other + td
202
+ with pytest.raises(TypeError, match=msg):
203
+ td - other
204
+ with pytest.raises(TypeError, match=msg):
205
+ other - td
206
+
207
+ def test_td_add_sub_int_ndarray(self):
208
+ td = Timedelta("1 day")
209
+ other = np.array([1])
210
+
211
+ msg = r"unsupported operand type\(s\) for \+: 'Timedelta' and 'int'"
212
+ with pytest.raises(TypeError, match=msg):
213
+ td + np.array([1])
214
+
215
+ msg = "|".join(
216
+ [
217
+ (
218
+ r"unsupported operand type\(s\) for \+: 'numpy.ndarray' "
219
+ "and 'Timedelta'"
220
+ ),
221
+ # This message goes on to say "Please do not rely on this error;
222
+ # it may not be given on all Python implementations"
223
+ "Concatenation operation is not implemented for NumPy arrays",
224
+ ]
225
+ )
226
+ with pytest.raises(TypeError, match=msg):
227
+ other + td
228
+ msg = r"unsupported operand type\(s\) for -: 'Timedelta' and 'int'"
229
+ with pytest.raises(TypeError, match=msg):
230
+ td - other
231
+ msg = r"unsupported operand type\(s\) for -: 'numpy.ndarray' and 'Timedelta'"
232
+ with pytest.raises(TypeError, match=msg):
233
+ other - td
234
+
235
+ def test_td_rsub_nat(self):
236
+ td = Timedelta(10, unit="d")
237
+ result = NaT - td
238
+ assert result is NaT
239
+
240
+ result = np.datetime64("NaT") - td
241
+ assert result is NaT
242
+
243
+ def test_td_rsub_offset(self):
244
+ result = offsets.Hour(1) - Timedelta(10, unit="d")
245
+ assert isinstance(result, Timedelta)
246
+ assert result == Timedelta(-239, unit="h")
247
+
248
+ def test_td_sub_timedeltalike_object_dtype_array(self):
249
+ # GH#21980
250
+ arr = np.array([Timestamp("20130101 9:01"), Timestamp("20121230 9:02")])
251
+ exp = np.array([Timestamp("20121231 9:01"), Timestamp("20121229 9:02")])
252
+ res = arr - Timedelta("1D")
253
+ tm.assert_numpy_array_equal(res, exp)
254
+
255
+ def test_td_sub_mixed_most_timedeltalike_object_dtype_array(self):
256
+ # GH#21980
257
+ now = Timestamp("2021-11-09 09:54:00")
258
+ arr = np.array([now, Timedelta("1D"), np.timedelta64(2, "h")])
259
+ exp = np.array(
260
+ [
261
+ now - Timedelta("1D"),
262
+ Timedelta("0D"),
263
+ np.timedelta64(2, "h") - Timedelta("1D"),
264
+ ]
265
+ )
266
+ res = arr - Timedelta("1D")
267
+ tm.assert_numpy_array_equal(res, exp)
268
+
269
+ def test_td_rsub_mixed_most_timedeltalike_object_dtype_array(self):
270
+ # GH#21980
271
+ now = Timestamp("2021-11-09 09:54:00")
272
+ arr = np.array([now, Timedelta("1D"), np.timedelta64(2, "h")])
273
+ msg = r"unsupported operand type\(s\) for \-: 'Timedelta' and 'Timestamp'"
274
+ with pytest.raises(TypeError, match=msg):
275
+ Timedelta("1D") - arr
276
+
277
+ @pytest.mark.parametrize("op", [operator.add, ops.radd])
278
+ def test_td_add_timedeltalike_object_dtype_array(self, op):
279
+ # GH#21980
280
+ arr = np.array([Timestamp("20130101 9:01"), Timestamp("20121230 9:02")])
281
+ exp = np.array([Timestamp("20130102 9:01"), Timestamp("20121231 9:02")])
282
+ res = op(arr, Timedelta("1D"))
283
+ tm.assert_numpy_array_equal(res, exp)
284
+
285
+ @pytest.mark.parametrize("op", [operator.add, ops.radd])
286
+ def test_td_add_mixed_timedeltalike_object_dtype_array(self, op):
287
+ # GH#21980
288
+ now = Timestamp("2021-11-09 09:54:00")
289
+ arr = np.array([now, Timedelta("1D")])
290
+ exp = np.array([now + Timedelta("1D"), Timedelta("2D")])
291
+ res = op(arr, Timedelta("1D"))
292
+ tm.assert_numpy_array_equal(res, exp)
293
+
294
+ def test_td_add_sub_td64_ndarray(self):
295
+ td = Timedelta("1 day")
296
+
297
+ other = np.array([td.to_timedelta64()])
298
+ expected = np.array([Timedelta("2 Days").to_timedelta64()])
299
+
300
+ result = td + other
301
+ tm.assert_numpy_array_equal(result, expected)
302
+ result = other + td
303
+ tm.assert_numpy_array_equal(result, expected)
304
+
305
+ result = td - other
306
+ tm.assert_numpy_array_equal(result, expected * 0)
307
+ result = other - td
308
+ tm.assert_numpy_array_equal(result, expected * 0)
309
+
310
+ def test_td_add_sub_dt64_ndarray(self):
311
+ td = Timedelta("1 day")
312
+ other = np.array(["2000-01-01"], dtype="M8[ns]")
313
+
314
+ expected = np.array(["2000-01-02"], dtype="M8[ns]")
315
+ tm.assert_numpy_array_equal(td + other, expected)
316
+ tm.assert_numpy_array_equal(other + td, expected)
317
+
318
+ expected = np.array(["1999-12-31"], dtype="M8[ns]")
319
+ tm.assert_numpy_array_equal(-td + other, expected)
320
+ tm.assert_numpy_array_equal(other - td, expected)
321
+
322
+ def test_td_add_sub_ndarray_0d(self):
323
+ td = Timedelta("1 day")
324
+ other = np.array(td.asm8)
325
+
326
+ result = td + other
327
+ assert isinstance(result, Timedelta)
328
+ assert result == 2 * td
329
+
330
+ result = other + td
331
+ assert isinstance(result, Timedelta)
332
+ assert result == 2 * td
333
+
334
+ result = other - td
335
+ assert isinstance(result, Timedelta)
336
+ assert result == 0 * td
337
+
338
+ result = td - other
339
+ assert isinstance(result, Timedelta)
340
+ assert result == 0 * td
341
+
342
+
343
+ class TestTimedeltaMultiplicationDivision:
344
+ """
345
+ Tests for Timedelta methods:
346
+
347
+ __mul__, __rmul__,
348
+ __div__, __rdiv__,
349
+ __truediv__, __rtruediv__,
350
+ __floordiv__, __rfloordiv__,
351
+ __mod__, __rmod__,
352
+ __divmod__, __rdivmod__
353
+ """
354
+
355
+ # ---------------------------------------------------------------
356
+ # Timedelta.__mul__, __rmul__
357
+
358
+ @pytest.mark.parametrize(
359
+ "td_nat", [NaT, np.timedelta64("NaT", "ns"), np.timedelta64("NaT")]
360
+ )
361
+ @pytest.mark.parametrize("op", [operator.mul, ops.rmul])
362
+ def test_td_mul_nat(self, op, td_nat):
363
+ # GH#19819
364
+ td = Timedelta(10, unit="d")
365
+ typs = "|".join(["numpy.timedelta64", "NaTType", "Timedelta"])
366
+ msg = "|".join(
367
+ [
368
+ rf"unsupported operand type\(s\) for \*: '{typs}' and '{typs}'",
369
+ r"ufunc '?multiply'? cannot use operands with types",
370
+ ]
371
+ )
372
+ with pytest.raises(TypeError, match=msg):
373
+ op(td, td_nat)
374
+
375
+ @pytest.mark.parametrize("nan", [np.nan, np.float64("NaN"), float("nan")])
376
+ @pytest.mark.parametrize("op", [operator.mul, ops.rmul])
377
+ def test_td_mul_nan(self, op, nan):
378
+ # np.float64('NaN') has a 'dtype' attr, avoid treating as array
379
+ td = Timedelta(10, unit="d")
380
+ result = op(td, nan)
381
+ assert result is NaT
382
+
383
+ @pytest.mark.parametrize("op", [operator.mul, ops.rmul])
384
+ def test_td_mul_scalar(self, op):
385
+ # GH#19738
386
+ td = Timedelta(minutes=3)
387
+
388
+ result = op(td, 2)
389
+ assert result == Timedelta(minutes=6)
390
+
391
+ result = op(td, 1.5)
392
+ assert result == Timedelta(minutes=4, seconds=30)
393
+
394
+ assert op(td, np.nan) is NaT
395
+
396
+ assert op(-1, td)._value == -1 * td._value
397
+ assert op(-1.0, td)._value == -1.0 * td._value
398
+
399
+ msg = "unsupported operand type"
400
+ with pytest.raises(TypeError, match=msg):
401
+ # timedelta * datetime is gibberish
402
+ op(td, Timestamp(2016, 1, 2))
403
+
404
+ with pytest.raises(TypeError, match=msg):
405
+ # invalid multiply with another timedelta
406
+ op(td, td)
407
+
408
+ def test_td_mul_numeric_ndarray(self):
409
+ td = Timedelta("1 day")
410
+ other = np.array([2])
411
+ expected = np.array([Timedelta("2 Days").to_timedelta64()])
412
+
413
+ result = td * other
414
+ tm.assert_numpy_array_equal(result, expected)
415
+
416
+ result = other * td
417
+ tm.assert_numpy_array_equal(result, expected)
418
+
419
+ def test_td_mul_numeric_ndarray_0d(self):
420
+ td = Timedelta("1 day")
421
+ other = np.array(2, dtype=np.int64)
422
+ assert other.ndim == 0
423
+ expected = Timedelta("2 days")
424
+
425
+ res = td * other
426
+ assert type(res) is Timedelta
427
+ assert res == expected
428
+
429
+ res = other * td
430
+ assert type(res) is Timedelta
431
+ assert res == expected
432
+
433
+ def test_td_mul_td64_ndarray_invalid(self):
434
+ td = Timedelta("1 day")
435
+ other = np.array([Timedelta("2 Days").to_timedelta64()])
436
+
437
+ msg = (
438
+ "ufunc '?multiply'? cannot use operands with types "
439
+ rf"dtype\('{tm.ENDIAN}m8\[ns\]'\) and dtype\('{tm.ENDIAN}m8\[ns\]'\)"
440
+ )
441
+ with pytest.raises(TypeError, match=msg):
442
+ td * other
443
+ with pytest.raises(TypeError, match=msg):
444
+ other * td
445
+
446
+ # ---------------------------------------------------------------
447
+ # Timedelta.__div__, __truediv__
448
+
449
+ def test_td_div_timedeltalike_scalar(self):
450
+ # GH#19738
451
+ td = Timedelta(10, unit="d")
452
+
453
+ result = td / offsets.Hour(1)
454
+ assert result == 240
455
+
456
+ assert td / td == 1
457
+ assert td / np.timedelta64(60, "h") == 4
458
+
459
+ assert np.isnan(td / NaT)
460
+
461
+ def test_td_div_td64_non_nano(self):
462
+ # truediv
463
+ td = Timedelta("1 days 2 hours 3 ns")
464
+ result = td / np.timedelta64(1, "D")
465
+ assert result == td._value / (86400 * 10**9)
466
+ result = td / np.timedelta64(1, "s")
467
+ assert result == td._value / 10**9
468
+ result = td / np.timedelta64(1, "ns")
469
+ assert result == td._value
470
+
471
+ # floordiv
472
+ td = Timedelta("1 days 2 hours 3 ns")
473
+ result = td // np.timedelta64(1, "D")
474
+ assert result == 1
475
+ result = td // np.timedelta64(1, "s")
476
+ assert result == 93600
477
+ result = td // np.timedelta64(1, "ns")
478
+ assert result == td._value
479
+
480
+ def test_td_div_numeric_scalar(self):
481
+ # GH#19738
482
+ td = Timedelta(10, unit="d")
483
+
484
+ result = td / 2
485
+ assert isinstance(result, Timedelta)
486
+ assert result == Timedelta(days=5)
487
+
488
+ result = td / 5
489
+ assert isinstance(result, Timedelta)
490
+ assert result == Timedelta(days=2)
491
+
492
+ @pytest.mark.parametrize(
493
+ "nan",
494
+ [
495
+ np.nan,
496
+ np.float64("NaN"),
497
+ float("nan"),
498
+ ],
499
+ )
500
+ def test_td_div_nan(self, nan):
501
+ # np.float64('NaN') has a 'dtype' attr, avoid treating as array
502
+ td = Timedelta(10, unit="d")
503
+ result = td / nan
504
+ assert result is NaT
505
+
506
+ result = td // nan
507
+ assert result is NaT
508
+
509
+ def test_td_div_td64_ndarray(self):
510
+ td = Timedelta("1 day")
511
+
512
+ other = np.array([Timedelta("2 Days").to_timedelta64()])
513
+ expected = np.array([0.5])
514
+
515
+ result = td / other
516
+ tm.assert_numpy_array_equal(result, expected)
517
+
518
+ result = other / td
519
+ tm.assert_numpy_array_equal(result, expected * 4)
520
+
521
+ def test_td_div_ndarray_0d(self):
522
+ td = Timedelta("1 day")
523
+
524
+ other = np.array(1)
525
+ res = td / other
526
+ assert isinstance(res, Timedelta)
527
+ assert res == td
528
+
529
+ # ---------------------------------------------------------------
530
+ # Timedelta.__rdiv__
531
+
532
+ def test_td_rdiv_timedeltalike_scalar(self):
533
+ # GH#19738
534
+ td = Timedelta(10, unit="d")
535
+ result = offsets.Hour(1) / td
536
+ assert result == 1 / 240.0
537
+
538
+ assert np.timedelta64(60, "h") / td == 0.25
539
+
540
+ def test_td_rdiv_na_scalar(self):
541
+ # GH#31869 None gets cast to NaT
542
+ td = Timedelta(10, unit="d")
543
+
544
+ result = NaT / td
545
+ assert np.isnan(result)
546
+
547
+ result = None / td
548
+ assert np.isnan(result)
549
+
550
+ result = np.timedelta64("NaT") / td
551
+ assert np.isnan(result)
552
+
553
+ msg = r"unsupported operand type\(s\) for /: 'numpy.datetime64' and 'Timedelta'"
554
+ with pytest.raises(TypeError, match=msg):
555
+ np.datetime64("NaT") / td
556
+
557
+ msg = r"unsupported operand type\(s\) for /: 'float' and 'Timedelta'"
558
+ with pytest.raises(TypeError, match=msg):
559
+ np.nan / td
560
+
561
+ def test_td_rdiv_ndarray(self):
562
+ td = Timedelta(10, unit="d")
563
+
564
+ arr = np.array([td], dtype=object)
565
+ result = arr / td
566
+ expected = np.array([1], dtype=np.float64)
567
+ tm.assert_numpy_array_equal(result, expected)
568
+
569
+ arr = np.array([None])
570
+ result = arr / td
571
+ expected = np.array([np.nan])
572
+ tm.assert_numpy_array_equal(result, expected)
573
+
574
+ arr = np.array([np.nan], dtype=object)
575
+ msg = r"unsupported operand type\(s\) for /: 'float' and 'Timedelta'"
576
+ with pytest.raises(TypeError, match=msg):
577
+ arr / td
578
+
579
+ arr = np.array([np.nan], dtype=np.float64)
580
+ msg = "cannot use operands with types dtype"
581
+ with pytest.raises(TypeError, match=msg):
582
+ arr / td
583
+
584
+ def test_td_rdiv_ndarray_0d(self):
585
+ td = Timedelta(10, unit="d")
586
+
587
+ arr = np.array(td.asm8)
588
+
589
+ assert arr / td == 1
590
+
591
+ # ---------------------------------------------------------------
592
+ # Timedelta.__floordiv__
593
+
594
+ def test_td_floordiv_timedeltalike_scalar(self):
595
+ # GH#18846
596
+ td = Timedelta(hours=3, minutes=4)
597
+ scalar = Timedelta(hours=3, minutes=3)
598
+
599
+ assert td // scalar == 1
600
+ assert -td // scalar.to_pytimedelta() == -2
601
+ assert (2 * td) // scalar.to_timedelta64() == 2
602
+
603
+ def test_td_floordiv_null_scalar(self):
604
+ # GH#18846
605
+ td = Timedelta(hours=3, minutes=4)
606
+
607
+ assert td // np.nan is NaT
608
+ assert np.isnan(td // NaT)
609
+ assert np.isnan(td // np.timedelta64("NaT"))
610
+
611
+ def test_td_floordiv_offsets(self):
612
+ # GH#19738
613
+ td = Timedelta(hours=3, minutes=4)
614
+ assert td // offsets.Hour(1) == 3
615
+ assert td // offsets.Minute(2) == 92
616
+
617
+ def test_td_floordiv_invalid_scalar(self):
618
+ # GH#18846
619
+ td = Timedelta(hours=3, minutes=4)
620
+
621
+ msg = "|".join(
622
+ [
623
+ r"Invalid dtype datetime64\[D\] for __floordiv__",
624
+ "'dtype' is an invalid keyword argument for this function",
625
+ "this function got an unexpected keyword argument 'dtype'",
626
+ r"ufunc '?floor_divide'? cannot use operands with types",
627
+ ]
628
+ )
629
+ with pytest.raises(TypeError, match=msg):
630
+ td // np.datetime64("2016-01-01", dtype="datetime64[us]")
631
+
632
+ def test_td_floordiv_numeric_scalar(self):
633
+ # GH#18846
634
+ td = Timedelta(hours=3, minutes=4)
635
+
636
+ expected = Timedelta(hours=1, minutes=32)
637
+ assert td // 2 == expected
638
+ assert td // 2.0 == expected
639
+ assert td // np.float64(2.0) == expected
640
+ assert td // np.int32(2.0) == expected
641
+ assert td // np.uint8(2.0) == expected
642
+
643
+ def test_td_floordiv_timedeltalike_array(self):
644
+ # GH#18846
645
+ td = Timedelta(hours=3, minutes=4)
646
+ scalar = Timedelta(hours=3, minutes=3)
647
+
648
+ # Array-like others
649
+ assert td // np.array(scalar.to_timedelta64()) == 1
650
+
651
+ res = (3 * td) // np.array([scalar.to_timedelta64()])
652
+ expected = np.array([3], dtype=np.int64)
653
+ tm.assert_numpy_array_equal(res, expected)
654
+
655
+ res = (10 * td) // np.array([scalar.to_timedelta64(), np.timedelta64("NaT")])
656
+ expected = np.array([10, np.nan])
657
+ tm.assert_numpy_array_equal(res, expected)
658
+
659
+ def test_td_floordiv_numeric_series(self):
660
+ # GH#18846
661
+ td = Timedelta(hours=3, minutes=4)
662
+ ser = pd.Series([1], dtype=np.int64)
663
+ res = td // ser
664
+ assert res.dtype.kind == "m"
665
+
666
+ # ---------------------------------------------------------------
667
+ # Timedelta.__rfloordiv__
668
+
669
+ def test_td_rfloordiv_timedeltalike_scalar(self):
670
+ # GH#18846
671
+ td = Timedelta(hours=3, minutes=3)
672
+ scalar = Timedelta(hours=3, minutes=4)
673
+
674
+ # scalar others
675
+ # x // Timedelta is defined only for timedelta-like x. int-like,
676
+ # float-like, and date-like, in particular, should all either
677
+ # a) raise TypeError directly or
678
+ # b) return NotImplemented, following which the reversed
679
+ # operation will raise TypeError.
680
+ assert td.__rfloordiv__(scalar) == 1
681
+ assert (-td).__rfloordiv__(scalar.to_pytimedelta()) == -2
682
+ assert (2 * td).__rfloordiv__(scalar.to_timedelta64()) == 0
683
+
684
+ def test_td_rfloordiv_null_scalar(self):
685
+ # GH#18846
686
+ td = Timedelta(hours=3, minutes=3)
687
+
688
+ assert np.isnan(td.__rfloordiv__(NaT))
689
+ assert np.isnan(td.__rfloordiv__(np.timedelta64("NaT")))
690
+
691
+ def test_td_rfloordiv_offsets(self):
692
+ # GH#19738
693
+ assert offsets.Hour(1) // Timedelta(minutes=25) == 2
694
+
695
+ def test_td_rfloordiv_invalid_scalar(self):
696
+ # GH#18846
697
+ td = Timedelta(hours=3, minutes=3)
698
+
699
+ dt64 = np.datetime64("2016-01-01", "us")
700
+
701
+ assert td.__rfloordiv__(dt64) is NotImplemented
702
+
703
+ msg = (
704
+ r"unsupported operand type\(s\) for //: 'numpy.datetime64' and 'Timedelta'"
705
+ )
706
+ with pytest.raises(TypeError, match=msg):
707
+ dt64 // td
708
+
709
+ def test_td_rfloordiv_numeric_scalar(self):
710
+ # GH#18846
711
+ td = Timedelta(hours=3, minutes=3)
712
+
713
+ assert td.__rfloordiv__(np.nan) is NotImplemented
714
+ assert td.__rfloordiv__(3.5) is NotImplemented
715
+ assert td.__rfloordiv__(2) is NotImplemented
716
+ assert td.__rfloordiv__(np.float64(2.0)) is NotImplemented
717
+ assert td.__rfloordiv__(np.uint8(9)) is NotImplemented
718
+ assert td.__rfloordiv__(np.int32(2.0)) is NotImplemented
719
+
720
+ msg = r"unsupported operand type\(s\) for //: '.*' and 'Timedelta"
721
+ with pytest.raises(TypeError, match=msg):
722
+ np.float64(2.0) // td
723
+ with pytest.raises(TypeError, match=msg):
724
+ np.uint8(9) // td
725
+ with pytest.raises(TypeError, match=msg):
726
+ # deprecated GH#19761, enforced GH#29797
727
+ np.int32(2.0) // td
728
+
729
+ def test_td_rfloordiv_timedeltalike_array(self):
730
+ # GH#18846
731
+ td = Timedelta(hours=3, minutes=3)
732
+ scalar = Timedelta(hours=3, minutes=4)
733
+
734
+ # Array-like others
735
+ assert td.__rfloordiv__(np.array(scalar.to_timedelta64())) == 1
736
+
737
+ res = td.__rfloordiv__(np.array([(3 * scalar).to_timedelta64()]))
738
+ expected = np.array([3], dtype=np.int64)
739
+ tm.assert_numpy_array_equal(res, expected)
740
+
741
+ arr = np.array([(10 * scalar).to_timedelta64(), np.timedelta64("NaT")])
742
+ res = td.__rfloordiv__(arr)
743
+ expected = np.array([10, np.nan])
744
+ tm.assert_numpy_array_equal(res, expected)
745
+
746
+ def test_td_rfloordiv_intarray(self):
747
+ # deprecated GH#19761, enforced GH#29797
748
+ ints = np.array([1349654400, 1349740800, 1349827200, 1349913600]) * 10**9
749
+
750
+ msg = "Invalid dtype"
751
+ with pytest.raises(TypeError, match=msg):
752
+ ints // Timedelta(1, unit="s")
753
+
754
+ def test_td_rfloordiv_numeric_series(self):
755
+ # GH#18846
756
+ td = Timedelta(hours=3, minutes=3)
757
+ ser = pd.Series([1], dtype=np.int64)
758
+ res = td.__rfloordiv__(ser)
759
+ assert res is NotImplemented
760
+
761
+ msg = "Invalid dtype"
762
+ with pytest.raises(TypeError, match=msg):
763
+ # Deprecated GH#19761, enforced GH#29797
764
+ ser // td
765
+
766
+ # ----------------------------------------------------------------
767
+ # Timedelta.__mod__, __rmod__
768
+
769
+ def test_mod_timedeltalike(self):
770
+ # GH#19365
771
+ td = Timedelta(hours=37)
772
+
773
+ # Timedelta-like others
774
+ result = td % Timedelta(hours=6)
775
+ assert isinstance(result, Timedelta)
776
+ assert result == Timedelta(hours=1)
777
+
778
+ result = td % timedelta(minutes=60)
779
+ assert isinstance(result, Timedelta)
780
+ assert result == Timedelta(0)
781
+
782
+ result = td % NaT
783
+ assert result is NaT
784
+
785
+ def test_mod_timedelta64_nat(self):
786
+ # GH#19365
787
+ td = Timedelta(hours=37)
788
+
789
+ result = td % np.timedelta64("NaT", "ns")
790
+ assert result is NaT
791
+
792
+ def test_mod_timedelta64(self):
793
+ # GH#19365
794
+ td = Timedelta(hours=37)
795
+
796
+ result = td % np.timedelta64(2, "h")
797
+ assert isinstance(result, Timedelta)
798
+ assert result == Timedelta(hours=1)
799
+
800
+ def test_mod_offset(self):
801
+ # GH#19365
802
+ td = Timedelta(hours=37)
803
+
804
+ result = td % offsets.Hour(5)
805
+ assert isinstance(result, Timedelta)
806
+ assert result == Timedelta(hours=2)
807
+
808
+ def test_mod_numeric(self):
809
+ # GH#19365
810
+ td = Timedelta(hours=37)
811
+
812
+ # Numeric Others
813
+ result = td % 2
814
+ assert isinstance(result, Timedelta)
815
+ assert result == Timedelta(0)
816
+
817
+ result = td % 1e12
818
+ assert isinstance(result, Timedelta)
819
+ assert result == Timedelta(minutes=3, seconds=20)
820
+
821
+ result = td % int(1e12)
822
+ assert isinstance(result, Timedelta)
823
+ assert result == Timedelta(minutes=3, seconds=20)
824
+
825
+ def test_mod_invalid(self):
826
+ # GH#19365
827
+ td = Timedelta(hours=37)
828
+ msg = "unsupported operand type"
829
+ with pytest.raises(TypeError, match=msg):
830
+ td % Timestamp("2018-01-22")
831
+
832
+ with pytest.raises(TypeError, match=msg):
833
+ td % []
834
+
835
+ def test_rmod_pytimedelta(self):
836
+ # GH#19365
837
+ td = Timedelta(minutes=3)
838
+
839
+ result = timedelta(minutes=4) % td
840
+ assert isinstance(result, Timedelta)
841
+ assert result == Timedelta(minutes=1)
842
+
843
+ def test_rmod_timedelta64(self):
844
+ # GH#19365
845
+ td = Timedelta(minutes=3)
846
+ result = np.timedelta64(5, "m") % td
847
+ assert isinstance(result, Timedelta)
848
+ assert result == Timedelta(minutes=2)
849
+
850
+ def test_rmod_invalid(self):
851
+ # GH#19365
852
+ td = Timedelta(minutes=3)
853
+
854
+ msg = "unsupported operand"
855
+ with pytest.raises(TypeError, match=msg):
856
+ Timestamp("2018-01-22") % td
857
+
858
+ with pytest.raises(TypeError, match=msg):
859
+ 15 % td
860
+
861
+ with pytest.raises(TypeError, match=msg):
862
+ 16.0 % td
863
+
864
+ msg = "Invalid dtype int"
865
+ with pytest.raises(TypeError, match=msg):
866
+ np.array([22, 24]) % td
867
+
868
+ # ----------------------------------------------------------------
869
+ # Timedelta.__divmod__, __rdivmod__
870
+
871
+ def test_divmod_numeric(self):
872
+ # GH#19365
873
+ td = Timedelta(days=2, hours=6)
874
+
875
+ result = divmod(td, 53 * 3600 * 1e9)
876
+ assert result[0] == Timedelta(1, unit="ns")
877
+ assert isinstance(result[1], Timedelta)
878
+ assert result[1] == Timedelta(hours=1)
879
+
880
+ assert result
881
+ result = divmod(td, np.nan)
882
+ assert result[0] is NaT
883
+ assert result[1] is NaT
884
+
885
+ def test_divmod(self):
886
+ # GH#19365
887
+ td = Timedelta(days=2, hours=6)
888
+
889
+ result = divmod(td, timedelta(days=1))
890
+ assert result[0] == 2
891
+ assert isinstance(result[1], Timedelta)
892
+ assert result[1] == Timedelta(hours=6)
893
+
894
+ result = divmod(td, 54)
895
+ assert result[0] == Timedelta(hours=1)
896
+ assert isinstance(result[1], Timedelta)
897
+ assert result[1] == Timedelta(0)
898
+
899
+ result = divmod(td, NaT)
900
+ assert np.isnan(result[0])
901
+ assert result[1] is NaT
902
+
903
+ def test_divmod_offset(self):
904
+ # GH#19365
905
+ td = Timedelta(days=2, hours=6)
906
+
907
+ result = divmod(td, offsets.Hour(-4))
908
+ assert result[0] == -14
909
+ assert isinstance(result[1], Timedelta)
910
+ assert result[1] == Timedelta(hours=-2)
911
+
912
+ def test_divmod_invalid(self):
913
+ # GH#19365
914
+ td = Timedelta(days=2, hours=6)
915
+
916
+ msg = r"unsupported operand type\(s\) for //: 'Timedelta' and 'Timestamp'"
917
+ with pytest.raises(TypeError, match=msg):
918
+ divmod(td, Timestamp("2018-01-22"))
919
+
920
+ def test_rdivmod_pytimedelta(self):
921
+ # GH#19365
922
+ result = divmod(timedelta(days=2, hours=6), Timedelta(days=1))
923
+ assert result[0] == 2
924
+ assert isinstance(result[1], Timedelta)
925
+ assert result[1] == Timedelta(hours=6)
926
+
927
+ def test_rdivmod_offset(self):
928
+ result = divmod(offsets.Hour(54), Timedelta(hours=-4))
929
+ assert result[0] == -14
930
+ assert isinstance(result[1], Timedelta)
931
+ assert result[1] == Timedelta(hours=-2)
932
+
933
+ def test_rdivmod_invalid(self):
934
+ # GH#19365
935
+ td = Timedelta(minutes=3)
936
+ msg = "unsupported operand type"
937
+
938
+ with pytest.raises(TypeError, match=msg):
939
+ divmod(Timestamp("2018-01-22"), td)
940
+
941
+ with pytest.raises(TypeError, match=msg):
942
+ divmod(15, td)
943
+
944
+ with pytest.raises(TypeError, match=msg):
945
+ divmod(16.0, td)
946
+
947
+ msg = "Invalid dtype int"
948
+ with pytest.raises(TypeError, match=msg):
949
+ divmod(np.array([22, 24]), td)
950
+
951
+ # ----------------------------------------------------------------
952
+
953
+ @pytest.mark.parametrize(
954
+ "op", [operator.mul, ops.rmul, operator.truediv, ops.rdiv, ops.rsub]
955
+ )
956
+ @pytest.mark.parametrize(
957
+ "arr",
958
+ [
959
+ np.array([Timestamp("20130101 9:01"), Timestamp("20121230 9:02")]),
960
+ np.array([Timestamp("2021-11-09 09:54:00"), Timedelta("1D")]),
961
+ ],
962
+ )
963
+ def test_td_op_timedelta_timedeltalike_array(self, op, arr):
964
+ msg = "unsupported operand type|cannot use operands with types"
965
+ with pytest.raises(TypeError, match=msg):
966
+ op(arr, Timedelta("1D"))
967
+
968
+
969
+ class TestTimedeltaComparison:
970
+ @pytest.mark.skip_ubsan
971
+ def test_compare_pytimedelta_bounds(self):
972
+ # GH#49021 don't overflow on comparison with very large pytimedeltas
973
+
974
+ for unit in ["ns", "us"]:
975
+ tdmax = Timedelta.max.as_unit(unit).max
976
+ tdmin = Timedelta.min.as_unit(unit).min
977
+
978
+ assert tdmax < timedelta.max
979
+ assert tdmax <= timedelta.max
980
+ assert not tdmax > timedelta.max
981
+ assert not tdmax >= timedelta.max
982
+ assert tdmax != timedelta.max
983
+ assert not tdmax == timedelta.max
984
+
985
+ assert tdmin > timedelta.min
986
+ assert tdmin >= timedelta.min
987
+ assert not tdmin < timedelta.min
988
+ assert not tdmin <= timedelta.min
989
+ assert tdmin != timedelta.min
990
+ assert not tdmin == timedelta.min
991
+
992
+ # But the "ms" and "s"-reso bounds extend pass pytimedelta
993
+ for unit in ["ms", "s"]:
994
+ tdmax = Timedelta.max.as_unit(unit).max
995
+ tdmin = Timedelta.min.as_unit(unit).min
996
+
997
+ assert tdmax > timedelta.max
998
+ assert tdmax >= timedelta.max
999
+ assert not tdmax < timedelta.max
1000
+ assert not tdmax <= timedelta.max
1001
+ assert tdmax != timedelta.max
1002
+ assert not tdmax == timedelta.max
1003
+
1004
+ assert tdmin < timedelta.min
1005
+ assert tdmin <= timedelta.min
1006
+ assert not tdmin > timedelta.min
1007
+ assert not tdmin >= timedelta.min
1008
+ assert tdmin != timedelta.min
1009
+ assert not tdmin == timedelta.min
1010
+
1011
+ def test_compare_pytimedelta_bounds2(self):
1012
+ # a pytimedelta outside the microsecond bounds
1013
+ pytd = timedelta(days=999999999, seconds=86399)
1014
+ # NB: np.timedelta64(td, "s"") incorrectly overflows
1015
+ td64 = np.timedelta64(pytd.days, "D") + np.timedelta64(pytd.seconds, "s")
1016
+ td = Timedelta(td64)
1017
+ assert td.days == pytd.days
1018
+ assert td.seconds == pytd.seconds
1019
+
1020
+ assert td == pytd
1021
+ assert not td != pytd
1022
+ assert not td < pytd
1023
+ assert not td > pytd
1024
+ assert td <= pytd
1025
+ assert td >= pytd
1026
+
1027
+ td2 = td - Timedelta(seconds=1).as_unit("s")
1028
+ assert td2 != pytd
1029
+ assert not td2 == pytd
1030
+ assert td2 < pytd
1031
+ assert td2 <= pytd
1032
+ assert not td2 > pytd
1033
+ assert not td2 >= pytd
1034
+
1035
+ def test_compare_tick(self, tick_classes):
1036
+ cls = tick_classes
1037
+
1038
+ off = cls(4)
1039
+ td = off._as_pd_timedelta
1040
+ assert isinstance(td, Timedelta)
1041
+
1042
+ assert td == off
1043
+ assert not td != off
1044
+ assert td <= off
1045
+ assert td >= off
1046
+ assert not td < off
1047
+ assert not td > off
1048
+
1049
+ assert not td == 2 * off
1050
+ assert td != 2 * off
1051
+ assert td <= 2 * off
1052
+ assert td < 2 * off
1053
+ assert not td >= 2 * off
1054
+ assert not td > 2 * off
1055
+
1056
+ def test_comparison_object_array(self):
1057
+ # analogous to GH#15183
1058
+ td = Timedelta("2 days")
1059
+ other = Timedelta("3 hours")
1060
+
1061
+ arr = np.array([other, td], dtype=object)
1062
+ res = arr == td
1063
+ expected = np.array([False, True], dtype=bool)
1064
+ assert (res == expected).all()
1065
+
1066
+ # 2D case
1067
+ arr = np.array([[other, td], [td, other]], dtype=object)
1068
+ res = arr != td
1069
+ expected = np.array([[True, False], [False, True]], dtype=bool)
1070
+ assert res.shape == expected.shape
1071
+ assert (res == expected).all()
1072
+
1073
+ def test_compare_timedelta_ndarray(self):
1074
+ # GH#11835
1075
+ periods = [Timedelta("0 days 01:00:00"), Timedelta("0 days 01:00:00")]
1076
+ arr = np.array(periods)
1077
+ result = arr[0] > arr
1078
+ expected = np.array([False, False])
1079
+ tm.assert_numpy_array_equal(result, expected)
1080
+
1081
+ def test_compare_td64_ndarray(self):
1082
+ # GG#33441
1083
+ arr = np.arange(5).astype("timedelta64[ns]")
1084
+ td = Timedelta(arr[1])
1085
+
1086
+ expected = np.array([False, True, False, False, False], dtype=bool)
1087
+
1088
+ result = td == arr
1089
+ tm.assert_numpy_array_equal(result, expected)
1090
+
1091
+ result = arr == td
1092
+ tm.assert_numpy_array_equal(result, expected)
1093
+
1094
+ result = td != arr
1095
+ tm.assert_numpy_array_equal(result, ~expected)
1096
+
1097
+ result = arr != td
1098
+ tm.assert_numpy_array_equal(result, ~expected)
1099
+
1100
+ def test_compare_custom_object(self):
1101
+ """
1102
+ Make sure non supported operations on Timedelta returns NonImplemented
1103
+ and yields to other operand (GH#20829).
1104
+ """
1105
+
1106
+ class CustomClass:
1107
+ def __init__(self, cmp_result=None) -> None:
1108
+ self.cmp_result = cmp_result
1109
+
1110
+ def generic_result(self):
1111
+ if self.cmp_result is None:
1112
+ return NotImplemented
1113
+ else:
1114
+ return self.cmp_result
1115
+
1116
+ def __eq__(self, other):
1117
+ return self.generic_result()
1118
+
1119
+ def __gt__(self, other):
1120
+ return self.generic_result()
1121
+
1122
+ t = Timedelta("1s")
1123
+
1124
+ assert t != "string"
1125
+ assert t != 1
1126
+ assert t != CustomClass()
1127
+ assert t != CustomClass(cmp_result=False)
1128
+
1129
+ assert t < CustomClass(cmp_result=True)
1130
+ assert not t < CustomClass(cmp_result=False)
1131
+
1132
+ assert t == CustomClass(cmp_result=True)
1133
+
1134
+ @pytest.mark.parametrize("val", ["string", 1])
1135
+ def test_compare_unknown_type(self, val):
1136
+ # GH#20829
1137
+ t = Timedelta("1s")
1138
+ msg = "not supported between instances of 'Timedelta' and '(int|str)'"
1139
+ with pytest.raises(TypeError, match=msg):
1140
+ t >= val
1141
+ with pytest.raises(TypeError, match=msg):
1142
+ t > val
1143
+ with pytest.raises(TypeError, match=msg):
1144
+ t <= val
1145
+ with pytest.raises(TypeError, match=msg):
1146
+ t < val
1147
+
1148
+
1149
+ def test_ops_notimplemented():
1150
+ class Other:
1151
+ pass
1152
+
1153
+ other = Other()
1154
+
1155
+ td = Timedelta("1 day")
1156
+ assert td.__add__(other) is NotImplemented
1157
+ assert td.__sub__(other) is NotImplemented
1158
+ assert td.__truediv__(other) is NotImplemented
1159
+ assert td.__mul__(other) is NotImplemented
1160
+ assert td.__floordiv__(other) is NotImplemented
1161
+
1162
+
1163
+ def test_ops_error_str():
1164
+ # GH#13624
1165
+ td = Timedelta("1 day")
1166
+
1167
+ for left, right in [(td, "a"), ("a", td)]:
1168
+ msg = "|".join(
1169
+ [
1170
+ "unsupported operand type",
1171
+ r'can only concatenate str \(not "Timedelta"\) to str',
1172
+ "must be str, not Timedelta",
1173
+ ]
1174
+ )
1175
+ with pytest.raises(TypeError, match=msg):
1176
+ left + right
1177
+
1178
+ msg = "not supported between instances of"
1179
+ with pytest.raises(TypeError, match=msg):
1180
+ left > right
1181
+
1182
+ assert not left == right # pylint: disable=unneeded-not
1183
+ assert left != right
py311/lib/python3.11/site-packages/pandas/tests/scalar/timedelta/test_constructors.py ADDED
@@ -0,0 +1,698 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from datetime import timedelta
2
+ from itertools import product
3
+
4
+ import numpy as np
5
+ import pytest
6
+
7
+ from pandas._libs.tslibs import OutOfBoundsTimedelta
8
+ from pandas._libs.tslibs.dtypes import NpyDatetimeUnit
9
+
10
+ from pandas import (
11
+ Index,
12
+ NaT,
13
+ Timedelta,
14
+ TimedeltaIndex,
15
+ offsets,
16
+ to_timedelta,
17
+ )
18
+ import pandas._testing as tm
19
+
20
+
21
+ class TestTimedeltaConstructorUnitKeyword:
22
+ @pytest.mark.parametrize("unit", ["Y", "y", "M"])
23
+ def test_unit_m_y_raises(self, unit):
24
+ msg = "Units 'M', 'Y', and 'y' are no longer supported"
25
+
26
+ with pytest.raises(ValueError, match=msg):
27
+ Timedelta(10, unit)
28
+
29
+ with pytest.raises(ValueError, match=msg):
30
+ to_timedelta(10, unit)
31
+
32
+ with pytest.raises(ValueError, match=msg):
33
+ to_timedelta([1, 2], unit)
34
+
35
+ @pytest.mark.parametrize(
36
+ "unit,unit_depr",
37
+ [
38
+ ("h", "H"),
39
+ ("min", "T"),
40
+ ("s", "S"),
41
+ ("ms", "L"),
42
+ ("ns", "N"),
43
+ ("us", "U"),
44
+ ],
45
+ )
46
+ def test_units_H_T_S_L_N_U_deprecated(self, unit, unit_depr):
47
+ # GH#52536
48
+ msg = f"'{unit_depr}' is deprecated and will be removed in a future version."
49
+
50
+ expected = Timedelta(1, unit=unit)
51
+ with tm.assert_produces_warning(FutureWarning, match=msg):
52
+ result = Timedelta(1, unit=unit_depr)
53
+ tm.assert_equal(result, expected)
54
+
55
+ @pytest.mark.parametrize(
56
+ "unit, np_unit",
57
+ [(value, "W") for value in ["W", "w"]]
58
+ + [(value, "D") for value in ["D", "d", "days", "day", "Days", "Day"]]
59
+ + [
60
+ (value, "m")
61
+ for value in [
62
+ "m",
63
+ "minute",
64
+ "min",
65
+ "minutes",
66
+ "Minute",
67
+ "Min",
68
+ "Minutes",
69
+ ]
70
+ ]
71
+ + [
72
+ (value, "s")
73
+ for value in [
74
+ "s",
75
+ "seconds",
76
+ "sec",
77
+ "second",
78
+ "Seconds",
79
+ "Sec",
80
+ "Second",
81
+ ]
82
+ ]
83
+ + [
84
+ (value, "ms")
85
+ for value in [
86
+ "ms",
87
+ "milliseconds",
88
+ "millisecond",
89
+ "milli",
90
+ "millis",
91
+ "MS",
92
+ "Milliseconds",
93
+ "Millisecond",
94
+ "Milli",
95
+ "Millis",
96
+ ]
97
+ ]
98
+ + [
99
+ (value, "us")
100
+ for value in [
101
+ "us",
102
+ "microseconds",
103
+ "microsecond",
104
+ "micro",
105
+ "micros",
106
+ "u",
107
+ "US",
108
+ "Microseconds",
109
+ "Microsecond",
110
+ "Micro",
111
+ "Micros",
112
+ "U",
113
+ ]
114
+ ]
115
+ + [
116
+ (value, "ns")
117
+ for value in [
118
+ "ns",
119
+ "nanoseconds",
120
+ "nanosecond",
121
+ "nano",
122
+ "nanos",
123
+ "n",
124
+ "NS",
125
+ "Nanoseconds",
126
+ "Nanosecond",
127
+ "Nano",
128
+ "Nanos",
129
+ "N",
130
+ ]
131
+ ],
132
+ )
133
+ @pytest.mark.parametrize("wrapper", [np.array, list, Index])
134
+ def test_unit_parser(self, unit, np_unit, wrapper):
135
+ # validate all units, GH 6855, GH 21762
136
+ # array-likes
137
+ expected = TimedeltaIndex(
138
+ [np.timedelta64(i, np_unit) for i in np.arange(5).tolist()],
139
+ dtype="m8[ns]",
140
+ )
141
+ # TODO(2.0): the desired output dtype may have non-nano resolution
142
+ msg = f"'{unit}' is deprecated and will be removed in a future version."
143
+
144
+ if (unit, np_unit) in (("u", "us"), ("U", "us"), ("n", "ns"), ("N", "ns")):
145
+ warn = FutureWarning
146
+ else:
147
+ warn = FutureWarning
148
+ msg = "The 'unit' keyword in TimedeltaIndex construction is deprecated"
149
+ with tm.assert_produces_warning(warn, match=msg):
150
+ result = to_timedelta(wrapper(range(5)), unit=unit)
151
+ tm.assert_index_equal(result, expected)
152
+ result = TimedeltaIndex(wrapper(range(5)), unit=unit)
153
+ tm.assert_index_equal(result, expected)
154
+
155
+ str_repr = [f"{x}{unit}" for x in np.arange(5)]
156
+ result = to_timedelta(wrapper(str_repr))
157
+ tm.assert_index_equal(result, expected)
158
+ result = to_timedelta(wrapper(str_repr))
159
+ tm.assert_index_equal(result, expected)
160
+
161
+ # scalar
162
+ expected = Timedelta(np.timedelta64(2, np_unit).astype("timedelta64[ns]"))
163
+ result = to_timedelta(2, unit=unit)
164
+ assert result == expected
165
+ result = Timedelta(2, unit=unit)
166
+ assert result == expected
167
+
168
+ result = to_timedelta(f"2{unit}")
169
+ assert result == expected
170
+ result = Timedelta(f"2{unit}")
171
+ assert result == expected
172
+
173
+
174
+ def test_construct_from_kwargs_overflow():
175
+ # GH#55503
176
+ msg = "seconds=86400000000000000000, milliseconds=0, microseconds=0, nanoseconds=0"
177
+ with pytest.raises(OutOfBoundsTimedelta, match=msg):
178
+ Timedelta(days=10**6)
179
+ msg = "seconds=60000000000000000000, milliseconds=0, microseconds=0, nanoseconds=0"
180
+ with pytest.raises(OutOfBoundsTimedelta, match=msg):
181
+ Timedelta(minutes=10**9)
182
+
183
+
184
+ def test_construct_with_weeks_unit_overflow():
185
+ # GH#47268 don't silently wrap around
186
+ with pytest.raises(OutOfBoundsTimedelta, match="without overflow"):
187
+ Timedelta(1000000000000000000, unit="W")
188
+
189
+ with pytest.raises(OutOfBoundsTimedelta, match="without overflow"):
190
+ Timedelta(1000000000000000000.0, unit="W")
191
+
192
+
193
+ def test_construct_from_td64_with_unit():
194
+ # ignore the unit, as it may cause silently overflows leading to incorrect
195
+ # results, and in non-overflow cases is irrelevant GH#46827
196
+ obj = np.timedelta64(123456789000000000, "h")
197
+
198
+ with pytest.raises(OutOfBoundsTimedelta, match="123456789000000000 hours"):
199
+ Timedelta(obj, unit="ps")
200
+
201
+ with pytest.raises(OutOfBoundsTimedelta, match="123456789000000000 hours"):
202
+ Timedelta(obj, unit="ns")
203
+
204
+ with pytest.raises(OutOfBoundsTimedelta, match="123456789000000000 hours"):
205
+ Timedelta(obj)
206
+
207
+
208
+ def test_from_td64_retain_resolution():
209
+ # case where we retain millisecond resolution
210
+ obj = np.timedelta64(12345, "ms")
211
+
212
+ td = Timedelta(obj)
213
+ assert td._value == obj.view("i8")
214
+ assert td._creso == NpyDatetimeUnit.NPY_FR_ms.value
215
+
216
+ # Case where we cast to nearest-supported reso
217
+ obj2 = np.timedelta64(1234, "D")
218
+ td2 = Timedelta(obj2)
219
+ assert td2._creso == NpyDatetimeUnit.NPY_FR_s.value
220
+ assert td2 == obj2
221
+ assert td2.days == 1234
222
+
223
+ # Case that _would_ overflow if we didn't support non-nano
224
+ obj3 = np.timedelta64(1000000000000000000, "us")
225
+ td3 = Timedelta(obj3)
226
+ assert td3.total_seconds() == 1000000000000
227
+ assert td3._creso == NpyDatetimeUnit.NPY_FR_us.value
228
+
229
+
230
+ def test_from_pytimedelta_us_reso():
231
+ # pytimedelta has microsecond resolution, so Timedelta(pytd) inherits that
232
+ td = timedelta(days=4, minutes=3)
233
+ result = Timedelta(td)
234
+ assert result.to_pytimedelta() == td
235
+ assert result._creso == NpyDatetimeUnit.NPY_FR_us.value
236
+
237
+
238
+ def test_from_tick_reso():
239
+ tick = offsets.Nano()
240
+ assert Timedelta(tick)._creso == NpyDatetimeUnit.NPY_FR_ns.value
241
+
242
+ tick = offsets.Micro()
243
+ assert Timedelta(tick)._creso == NpyDatetimeUnit.NPY_FR_us.value
244
+
245
+ tick = offsets.Milli()
246
+ assert Timedelta(tick)._creso == NpyDatetimeUnit.NPY_FR_ms.value
247
+
248
+ tick = offsets.Second()
249
+ assert Timedelta(tick)._creso == NpyDatetimeUnit.NPY_FR_s.value
250
+
251
+ # everything above Second gets cast to the closest supported reso: second
252
+ tick = offsets.Minute()
253
+ assert Timedelta(tick)._creso == NpyDatetimeUnit.NPY_FR_s.value
254
+
255
+ tick = offsets.Hour()
256
+ assert Timedelta(tick)._creso == NpyDatetimeUnit.NPY_FR_s.value
257
+
258
+ tick = offsets.Day()
259
+ assert Timedelta(tick)._creso == NpyDatetimeUnit.NPY_FR_s.value
260
+
261
+
262
+ def test_construction():
263
+ expected = np.timedelta64(10, "D").astype("m8[ns]").view("i8")
264
+ assert Timedelta(10, unit="d")._value == expected
265
+ assert Timedelta(10.0, unit="d")._value == expected
266
+ assert Timedelta("10 days")._value == expected
267
+ assert Timedelta(days=10)._value == expected
268
+ assert Timedelta(days=10.0)._value == expected
269
+
270
+ expected += np.timedelta64(10, "s").astype("m8[ns]").view("i8")
271
+ assert Timedelta("10 days 00:00:10")._value == expected
272
+ assert Timedelta(days=10, seconds=10)._value == expected
273
+ assert Timedelta(days=10, milliseconds=10 * 1000)._value == expected
274
+ assert Timedelta(days=10, microseconds=10 * 1000 * 1000)._value == expected
275
+
276
+ # rounding cases
277
+ assert Timedelta(82739999850000)._value == 82739999850000
278
+ assert "0 days 22:58:59.999850" in str(Timedelta(82739999850000))
279
+ assert Timedelta(123072001000000)._value == 123072001000000
280
+ assert "1 days 10:11:12.001" in str(Timedelta(123072001000000))
281
+
282
+ # string conversion with/without leading zero
283
+ # GH#9570
284
+ assert Timedelta("0:00:00") == timedelta(hours=0)
285
+ assert Timedelta("00:00:00") == timedelta(hours=0)
286
+ assert Timedelta("-1:00:00") == -timedelta(hours=1)
287
+ assert Timedelta("-01:00:00") == -timedelta(hours=1)
288
+
289
+ # more strings & abbrevs
290
+ # GH#8190
291
+ assert Timedelta("1 h") == timedelta(hours=1)
292
+ assert Timedelta("1 hour") == timedelta(hours=1)
293
+ assert Timedelta("1 hr") == timedelta(hours=1)
294
+ assert Timedelta("1 hours") == timedelta(hours=1)
295
+ assert Timedelta("-1 hours") == -timedelta(hours=1)
296
+ assert Timedelta("1 m") == timedelta(minutes=1)
297
+ assert Timedelta("1.5 m") == timedelta(seconds=90)
298
+ assert Timedelta("1 minute") == timedelta(minutes=1)
299
+ assert Timedelta("1 minutes") == timedelta(minutes=1)
300
+ assert Timedelta("1 s") == timedelta(seconds=1)
301
+ assert Timedelta("1 second") == timedelta(seconds=1)
302
+ assert Timedelta("1 seconds") == timedelta(seconds=1)
303
+ assert Timedelta("1 ms") == timedelta(milliseconds=1)
304
+ assert Timedelta("1 milli") == timedelta(milliseconds=1)
305
+ assert Timedelta("1 millisecond") == timedelta(milliseconds=1)
306
+ assert Timedelta("1 us") == timedelta(microseconds=1)
307
+ assert Timedelta("1 µs") == timedelta(microseconds=1)
308
+ assert Timedelta("1 micros") == timedelta(microseconds=1)
309
+ assert Timedelta("1 microsecond") == timedelta(microseconds=1)
310
+ assert Timedelta("1.5 microsecond") == Timedelta("00:00:00.000001500")
311
+ assert Timedelta("1 ns") == Timedelta("00:00:00.000000001")
312
+ assert Timedelta("1 nano") == Timedelta("00:00:00.000000001")
313
+ assert Timedelta("1 nanosecond") == Timedelta("00:00:00.000000001")
314
+
315
+ # combos
316
+ assert Timedelta("10 days 1 hour") == timedelta(days=10, hours=1)
317
+ assert Timedelta("10 days 1 h") == timedelta(days=10, hours=1)
318
+ assert Timedelta("10 days 1 h 1m 1s") == timedelta(
319
+ days=10, hours=1, minutes=1, seconds=1
320
+ )
321
+ assert Timedelta("-10 days 1 h 1m 1s") == -timedelta(
322
+ days=10, hours=1, minutes=1, seconds=1
323
+ )
324
+ assert Timedelta("-10 days 1 h 1m 1s") == -timedelta(
325
+ days=10, hours=1, minutes=1, seconds=1
326
+ )
327
+ assert Timedelta("-10 days 1 h 1m 1s 3us") == -timedelta(
328
+ days=10, hours=1, minutes=1, seconds=1, microseconds=3
329
+ )
330
+ assert Timedelta("-10 days 1 h 1.5m 1s 3us") == -timedelta(
331
+ days=10, hours=1, minutes=1, seconds=31, microseconds=3
332
+ )
333
+
334
+ # Currently invalid as it has a - on the hh:mm:dd part
335
+ # (only allowed on the days)
336
+ msg = "only leading negative signs are allowed"
337
+ with pytest.raises(ValueError, match=msg):
338
+ Timedelta("-10 days -1 h 1.5m 1s 3us")
339
+
340
+ # only leading neg signs are allowed
341
+ with pytest.raises(ValueError, match=msg):
342
+ Timedelta("10 days -1 h 1.5m 1s 3us")
343
+
344
+ # no units specified
345
+ msg = "no units specified"
346
+ with pytest.raises(ValueError, match=msg):
347
+ Timedelta("3.1415")
348
+
349
+ # invalid construction
350
+ msg = "cannot construct a Timedelta"
351
+ with pytest.raises(ValueError, match=msg):
352
+ Timedelta()
353
+
354
+ msg = "unit abbreviation w/o a number"
355
+ with pytest.raises(ValueError, match=msg):
356
+ Timedelta("foo")
357
+
358
+ msg = (
359
+ "cannot construct a Timedelta from "
360
+ "the passed arguments, allowed keywords are "
361
+ )
362
+ with pytest.raises(ValueError, match=msg):
363
+ Timedelta(day=10)
364
+
365
+ # floats
366
+ expected = np.timedelta64(10, "s").astype("m8[ns]").view("i8") + np.timedelta64(
367
+ 500, "ms"
368
+ ).astype("m8[ns]").view("i8")
369
+ assert Timedelta(10.5, unit="s")._value == expected
370
+
371
+ # offset
372
+ assert to_timedelta(offsets.Hour(2)) == Timedelta(hours=2)
373
+ assert Timedelta(offsets.Hour(2)) == Timedelta(hours=2)
374
+ assert Timedelta(offsets.Second(2)) == Timedelta(seconds=2)
375
+
376
+ # GH#11995: unicode
377
+ expected = Timedelta("1h")
378
+ result = Timedelta("1h")
379
+ assert result == expected
380
+ assert to_timedelta(offsets.Hour(2)) == Timedelta("0 days, 02:00:00")
381
+
382
+ msg = "unit abbreviation w/o a number"
383
+ with pytest.raises(ValueError, match=msg):
384
+ Timedelta("foo bar")
385
+
386
+
387
+ @pytest.mark.parametrize(
388
+ "item",
389
+ list(
390
+ {
391
+ "days": "D",
392
+ "seconds": "s",
393
+ "microseconds": "us",
394
+ "milliseconds": "ms",
395
+ "minutes": "m",
396
+ "hours": "h",
397
+ "weeks": "W",
398
+ }.items()
399
+ ),
400
+ )
401
+ @pytest.mark.parametrize(
402
+ "npdtype", [np.int64, np.int32, np.int16, np.float64, np.float32, np.float16]
403
+ )
404
+ def test_td_construction_with_np_dtypes(npdtype, item):
405
+ # GH#8757: test construction with np dtypes
406
+ pykwarg, npkwarg = item
407
+ expected = np.timedelta64(1, npkwarg).astype("m8[ns]").view("i8")
408
+ assert Timedelta(**{pykwarg: npdtype(1)})._value == expected
409
+
410
+
411
+ @pytest.mark.parametrize(
412
+ "val",
413
+ [
414
+ "1s",
415
+ "-1s",
416
+ "1us",
417
+ "-1us",
418
+ "1 day",
419
+ "-1 day",
420
+ "-23:59:59.999999",
421
+ "-1 days +23:59:59.999999",
422
+ "-1ns",
423
+ "1ns",
424
+ "-23:59:59.999999999",
425
+ ],
426
+ )
427
+ def test_td_from_repr_roundtrip(val):
428
+ # round-trip both for string and value
429
+ td = Timedelta(val)
430
+ assert Timedelta(td._value) == td
431
+
432
+ assert Timedelta(str(td)) == td
433
+ assert Timedelta(td._repr_base(format="all")) == td
434
+ assert Timedelta(td._repr_base()) == td
435
+
436
+
437
+ def test_overflow_on_construction():
438
+ # GH#3374
439
+ value = Timedelta("1day")._value * 20169940
440
+ msg = "Cannot cast 1742682816000000000000 from ns to 'ns' without overflow"
441
+ with pytest.raises(OutOfBoundsTimedelta, match=msg):
442
+ Timedelta(value)
443
+
444
+ # xref GH#17637
445
+ msg = "Cannot cast 139993 from D to 'ns' without overflow"
446
+ with pytest.raises(OutOfBoundsTimedelta, match=msg):
447
+ Timedelta(7 * 19999, unit="D")
448
+
449
+ # used to overflow before non-ns support
450
+ td = Timedelta(timedelta(days=13 * 19999))
451
+ assert td._creso == NpyDatetimeUnit.NPY_FR_us.value
452
+ assert td.days == 13 * 19999
453
+
454
+
455
+ @pytest.mark.parametrize(
456
+ "val, unit",
457
+ [
458
+ (15251, "W"), # 1
459
+ (106752, "D"), # change from previous:
460
+ (2562048, "h"), # 0 hours
461
+ (153722868, "m"), # 13 minutes
462
+ (9223372037, "s"), # 44 seconds
463
+ ],
464
+ )
465
+ def test_construction_out_of_bounds_td64ns(val, unit):
466
+ # TODO: parametrize over units just above/below the implementation bounds
467
+ # once GH#38964 is resolved
468
+
469
+ # Timedelta.max is just under 106752 days
470
+ td64 = np.timedelta64(val, unit)
471
+ assert td64.astype("m8[ns]").view("i8") < 0 # i.e. naive astype will be wrong
472
+
473
+ td = Timedelta(td64)
474
+ if unit != "M":
475
+ # with unit="M" the conversion to "s" is poorly defined
476
+ # (and numpy issues DeprecationWarning)
477
+ assert td.asm8 == td64
478
+ assert td.asm8.dtype == "m8[s]"
479
+ msg = r"Cannot cast 1067\d\d days .* to unit='ns' without overflow"
480
+ with pytest.raises(OutOfBoundsTimedelta, match=msg):
481
+ td.as_unit("ns")
482
+
483
+ # But just back in bounds and we are OK
484
+ assert Timedelta(td64 - 1) == td64 - 1
485
+
486
+ td64 *= -1
487
+ assert td64.astype("m8[ns]").view("i8") > 0 # i.e. naive astype will be wrong
488
+
489
+ td2 = Timedelta(td64)
490
+ msg = r"Cannot cast -1067\d\d days .* to unit='ns' without overflow"
491
+ with pytest.raises(OutOfBoundsTimedelta, match=msg):
492
+ td2.as_unit("ns")
493
+
494
+ # But just back in bounds and we are OK
495
+ assert Timedelta(td64 + 1) == td64 + 1
496
+
497
+
498
+ @pytest.mark.parametrize(
499
+ "val, unit",
500
+ [
501
+ (15251 * 10**9, "W"),
502
+ (106752 * 10**9, "D"),
503
+ (2562048 * 10**9, "h"),
504
+ (153722868 * 10**9, "m"),
505
+ ],
506
+ )
507
+ def test_construction_out_of_bounds_td64s(val, unit):
508
+ td64 = np.timedelta64(val, unit)
509
+ with pytest.raises(OutOfBoundsTimedelta, match=str(td64)):
510
+ Timedelta(td64)
511
+
512
+ # But just back in bounds and we are OK
513
+ assert Timedelta(td64 - 10**9) == td64 - 10**9
514
+
515
+
516
+ @pytest.mark.parametrize(
517
+ "fmt,exp",
518
+ [
519
+ (
520
+ "P6DT0H50M3.010010012S",
521
+ Timedelta(
522
+ days=6,
523
+ minutes=50,
524
+ seconds=3,
525
+ milliseconds=10,
526
+ microseconds=10,
527
+ nanoseconds=12,
528
+ ),
529
+ ),
530
+ (
531
+ "P-6DT0H50M3.010010012S",
532
+ Timedelta(
533
+ days=-6,
534
+ minutes=50,
535
+ seconds=3,
536
+ milliseconds=10,
537
+ microseconds=10,
538
+ nanoseconds=12,
539
+ ),
540
+ ),
541
+ ("P4DT12H30M5S", Timedelta(days=4, hours=12, minutes=30, seconds=5)),
542
+ ("P0DT0H0M0.000000123S", Timedelta(nanoseconds=123)),
543
+ ("P0DT0H0M0.00001S", Timedelta(microseconds=10)),
544
+ ("P0DT0H0M0.001S", Timedelta(milliseconds=1)),
545
+ ("P0DT0H1M0S", Timedelta(minutes=1)),
546
+ ("P1DT25H61M61S", Timedelta(days=1, hours=25, minutes=61, seconds=61)),
547
+ ("PT1S", Timedelta(seconds=1)),
548
+ ("PT0S", Timedelta(seconds=0)),
549
+ ("P1WT0S", Timedelta(days=7, seconds=0)),
550
+ ("P1D", Timedelta(days=1)),
551
+ ("P1DT1H", Timedelta(days=1, hours=1)),
552
+ ("P1W", Timedelta(days=7)),
553
+ ("PT300S", Timedelta(seconds=300)),
554
+ ("P1DT0H0M00000000000S", Timedelta(days=1)),
555
+ ("PT-6H3M", Timedelta(hours=-6, minutes=3)),
556
+ ("-PT6H3M", Timedelta(hours=-6, minutes=-3)),
557
+ ("-PT-6H+3M", Timedelta(hours=6, minutes=-3)),
558
+ ],
559
+ )
560
+ def test_iso_constructor(fmt, exp):
561
+ assert Timedelta(fmt) == exp
562
+
563
+
564
+ @pytest.mark.parametrize(
565
+ "fmt",
566
+ [
567
+ "PPPPPPPPPPPP",
568
+ "PDTHMS",
569
+ "P0DT999H999M999S",
570
+ "P1DT0H0M0.0000000000000S",
571
+ "P1DT0H0M0.S",
572
+ "P",
573
+ "-P",
574
+ ],
575
+ )
576
+ def test_iso_constructor_raises(fmt):
577
+ msg = f"Invalid ISO 8601 Duration format - {fmt}"
578
+ with pytest.raises(ValueError, match=msg):
579
+ Timedelta(fmt)
580
+
581
+
582
+ @pytest.mark.parametrize(
583
+ "constructed_td, conversion",
584
+ [
585
+ (Timedelta(nanoseconds=100), "100ns"),
586
+ (
587
+ Timedelta(
588
+ days=1,
589
+ hours=1,
590
+ minutes=1,
591
+ weeks=1,
592
+ seconds=1,
593
+ milliseconds=1,
594
+ microseconds=1,
595
+ nanoseconds=1,
596
+ ),
597
+ 694861001001001,
598
+ ),
599
+ (Timedelta(microseconds=1) + Timedelta(nanoseconds=1), "1us1ns"),
600
+ (Timedelta(microseconds=1) - Timedelta(nanoseconds=1), "999ns"),
601
+ (Timedelta(microseconds=1) + 5 * Timedelta(nanoseconds=-2), "990ns"),
602
+ ],
603
+ )
604
+ def test_td_constructor_on_nanoseconds(constructed_td, conversion):
605
+ # GH#9273
606
+ assert constructed_td == Timedelta(conversion)
607
+
608
+
609
+ def test_td_constructor_value_error():
610
+ msg = "Invalid type <class 'str'>. Must be int or float."
611
+ with pytest.raises(TypeError, match=msg):
612
+ Timedelta(nanoseconds="abc")
613
+
614
+
615
+ def test_timedelta_constructor_identity():
616
+ # Test for #30543
617
+ expected = Timedelta(np.timedelta64(1, "s"))
618
+ result = Timedelta(expected)
619
+ assert result is expected
620
+
621
+
622
+ def test_timedelta_pass_td_and_kwargs_raises():
623
+ # don't silently ignore the kwargs GH#48898
624
+ td = Timedelta(days=1)
625
+ msg = (
626
+ "Cannot pass both a Timedelta input and timedelta keyword arguments, "
627
+ r"got \['days'\]"
628
+ )
629
+ with pytest.raises(ValueError, match=msg):
630
+ Timedelta(td, days=2)
631
+
632
+
633
+ @pytest.mark.parametrize(
634
+ "constructor, value, unit, expectation",
635
+ [
636
+ (Timedelta, "10s", "ms", (ValueError, "unit must not be specified")),
637
+ (to_timedelta, "10s", "ms", (ValueError, "unit must not be specified")),
638
+ (to_timedelta, ["1", 2, 3], "s", (ValueError, "unit must not be specified")),
639
+ ],
640
+ )
641
+ def test_string_with_unit(constructor, value, unit, expectation):
642
+ exp, match = expectation
643
+ with pytest.raises(exp, match=match):
644
+ _ = constructor(value, unit=unit)
645
+
646
+
647
+ @pytest.mark.parametrize(
648
+ "value",
649
+ [
650
+ "".join(elements)
651
+ for repetition in (1, 2)
652
+ for elements in product("+-, ", repeat=repetition)
653
+ ],
654
+ )
655
+ def test_string_without_numbers(value):
656
+ # GH39710 Timedelta input string with only symbols and no digits raises an error
657
+ msg = (
658
+ "symbols w/o a number"
659
+ if value != "--"
660
+ else "only leading negative signs are allowed"
661
+ )
662
+ with pytest.raises(ValueError, match=msg):
663
+ Timedelta(value)
664
+
665
+
666
+ def test_timedelta_new_npnat():
667
+ # GH#48898
668
+ nat = np.timedelta64("NaT", "h")
669
+ assert Timedelta(nat) is NaT
670
+
671
+
672
+ def test_subclass_respected():
673
+ # GH#49579
674
+ class MyCustomTimedelta(Timedelta):
675
+ pass
676
+
677
+ td = MyCustomTimedelta("1 minute")
678
+ assert isinstance(td, MyCustomTimedelta)
679
+
680
+
681
+ def test_non_nano_value():
682
+ # https://github.com/pandas-dev/pandas/issues/49076
683
+ result = Timedelta(10, unit="D").as_unit("s").value
684
+ # `.value` shows nanoseconds, even though unit is 's'
685
+ assert result == 864000000000000
686
+
687
+ # out-of-nanoseconds-bounds `.value` raises informative message
688
+ msg = (
689
+ r"Cannot convert Timedelta to nanoseconds without overflow. "
690
+ r"Use `.asm8.view\('i8'\)` to cast represent Timedelta in its "
691
+ r"own unit \(here, s\).$"
692
+ )
693
+ td = Timedelta(1_000, "D").as_unit("s") * 1_000
694
+ with pytest.raises(OverflowError, match=msg):
695
+ td.value
696
+ # check that the suggested workaround actually works
697
+ result = td.asm8.view("i8")
698
+ assert result == 86400000000
py311/lib/python3.11/site-packages/pandas/tests/scalar/timedelta/test_formats.py ADDED
@@ -0,0 +1,109 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import pytest
2
+
3
+ from pandas import Timedelta
4
+
5
+
6
+ @pytest.mark.parametrize(
7
+ "td, expected_repr",
8
+ [
9
+ (Timedelta(10, unit="d"), "Timedelta('10 days 00:00:00')"),
10
+ (Timedelta(10, unit="s"), "Timedelta('0 days 00:00:10')"),
11
+ (Timedelta(10, unit="ms"), "Timedelta('0 days 00:00:00.010000')"),
12
+ (Timedelta(-10, unit="ms"), "Timedelta('-1 days +23:59:59.990000')"),
13
+ ],
14
+ )
15
+ def test_repr(td, expected_repr):
16
+ assert repr(td) == expected_repr
17
+
18
+
19
+ @pytest.mark.parametrize(
20
+ "td, expected_iso",
21
+ [
22
+ (
23
+ Timedelta(
24
+ days=6,
25
+ minutes=50,
26
+ seconds=3,
27
+ milliseconds=10,
28
+ microseconds=10,
29
+ nanoseconds=12,
30
+ ),
31
+ "P6DT0H50M3.010010012S",
32
+ ),
33
+ (Timedelta(days=4, hours=12, minutes=30, seconds=5), "P4DT12H30M5S"),
34
+ (Timedelta(nanoseconds=123), "P0DT0H0M0.000000123S"),
35
+ # trim nano
36
+ (Timedelta(microseconds=10), "P0DT0H0M0.00001S"),
37
+ # trim micro
38
+ (Timedelta(milliseconds=1), "P0DT0H0M0.001S"),
39
+ # don't strip every 0
40
+ (Timedelta(minutes=1), "P0DT0H1M0S"),
41
+ ],
42
+ )
43
+ def test_isoformat(td, expected_iso):
44
+ assert td.isoformat() == expected_iso
45
+
46
+
47
+ class TestReprBase:
48
+ def test_none(self):
49
+ delta_1d = Timedelta(1, unit="D")
50
+ delta_0d = Timedelta(0, unit="D")
51
+ delta_1s = Timedelta(1, unit="s")
52
+ delta_500ms = Timedelta(500, unit="ms")
53
+
54
+ drepr = lambda x: x._repr_base()
55
+ assert drepr(delta_1d) == "1 days"
56
+ assert drepr(-delta_1d) == "-1 days"
57
+ assert drepr(delta_0d) == "0 days"
58
+ assert drepr(delta_1s) == "0 days 00:00:01"
59
+ assert drepr(delta_500ms) == "0 days 00:00:00.500000"
60
+ assert drepr(delta_1d + delta_1s) == "1 days 00:00:01"
61
+ assert drepr(-delta_1d + delta_1s) == "-1 days +00:00:01"
62
+ assert drepr(delta_1d + delta_500ms) == "1 days 00:00:00.500000"
63
+ assert drepr(-delta_1d + delta_500ms) == "-1 days +00:00:00.500000"
64
+
65
+ def test_sub_day(self):
66
+ delta_1d = Timedelta(1, unit="D")
67
+ delta_0d = Timedelta(0, unit="D")
68
+ delta_1s = Timedelta(1, unit="s")
69
+ delta_500ms = Timedelta(500, unit="ms")
70
+
71
+ drepr = lambda x: x._repr_base(format="sub_day")
72
+ assert drepr(delta_1d) == "1 days"
73
+ assert drepr(-delta_1d) == "-1 days"
74
+ assert drepr(delta_0d) == "00:00:00"
75
+ assert drepr(delta_1s) == "00:00:01"
76
+ assert drepr(delta_500ms) == "00:00:00.500000"
77
+ assert drepr(delta_1d + delta_1s) == "1 days 00:00:01"
78
+ assert drepr(-delta_1d + delta_1s) == "-1 days +00:00:01"
79
+ assert drepr(delta_1d + delta_500ms) == "1 days 00:00:00.500000"
80
+ assert drepr(-delta_1d + delta_500ms) == "-1 days +00:00:00.500000"
81
+
82
+ def test_long(self):
83
+ delta_1d = Timedelta(1, unit="D")
84
+ delta_0d = Timedelta(0, unit="D")
85
+ delta_1s = Timedelta(1, unit="s")
86
+ delta_500ms = Timedelta(500, unit="ms")
87
+
88
+ drepr = lambda x: x._repr_base(format="long")
89
+ assert drepr(delta_1d) == "1 days 00:00:00"
90
+ assert drepr(-delta_1d) == "-1 days +00:00:00"
91
+ assert drepr(delta_0d) == "0 days 00:00:00"
92
+ assert drepr(delta_1s) == "0 days 00:00:01"
93
+ assert drepr(delta_500ms) == "0 days 00:00:00.500000"
94
+ assert drepr(delta_1d + delta_1s) == "1 days 00:00:01"
95
+ assert drepr(-delta_1d + delta_1s) == "-1 days +00:00:01"
96
+ assert drepr(delta_1d + delta_500ms) == "1 days 00:00:00.500000"
97
+ assert drepr(-delta_1d + delta_500ms) == "-1 days +00:00:00.500000"
98
+
99
+ def test_all(self):
100
+ delta_1d = Timedelta(1, unit="D")
101
+ delta_0d = Timedelta(0, unit="D")
102
+ delta_1ns = Timedelta(1, unit="ns")
103
+
104
+ drepr = lambda x: x._repr_base(format="all")
105
+ assert drepr(delta_1d) == "1 days 00:00:00.000000000"
106
+ assert drepr(-delta_1d) == "-1 days +00:00:00.000000000"
107
+ assert drepr(delta_0d) == "0 days 00:00:00.000000000"
108
+ assert drepr(delta_1ns) == "0 days 00:00:00.000000001"
109
+ assert drepr(-delta_1d + delta_1ns) == "-1 days +00:00:00.000000001"
py311/lib/python3.11/site-packages/pandas/tests/scalar/timedelta/test_timedelta.py ADDED
@@ -0,0 +1,666 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """ test the scalar Timedelta """
2
+ from datetime import timedelta
3
+ import sys
4
+
5
+ from hypothesis import (
6
+ given,
7
+ strategies as st,
8
+ )
9
+ import numpy as np
10
+ import pytest
11
+
12
+ from pandas._libs import lib
13
+ from pandas._libs.tslibs import (
14
+ NaT,
15
+ iNaT,
16
+ )
17
+ from pandas._libs.tslibs.dtypes import NpyDatetimeUnit
18
+ from pandas.errors import OutOfBoundsTimedelta
19
+
20
+ from pandas import (
21
+ Timedelta,
22
+ to_timedelta,
23
+ )
24
+ import pandas._testing as tm
25
+
26
+
27
+ class TestNonNano:
28
+ @pytest.fixture(params=["s", "ms", "us"])
29
+ def unit_str(self, request):
30
+ return request.param
31
+
32
+ @pytest.fixture
33
+ def unit(self, unit_str):
34
+ # 7, 8, 9 correspond to second, millisecond, and microsecond, respectively
35
+ attr = f"NPY_FR_{unit_str}"
36
+ return getattr(NpyDatetimeUnit, attr).value
37
+
38
+ @pytest.fixture
39
+ def val(self, unit):
40
+ # microsecond that would be just out of bounds for nano
41
+ us = 9223372800000000
42
+ if unit == NpyDatetimeUnit.NPY_FR_us.value:
43
+ value = us
44
+ elif unit == NpyDatetimeUnit.NPY_FR_ms.value:
45
+ value = us // 1000
46
+ else:
47
+ value = us // 1_000_000
48
+ return value
49
+
50
+ @pytest.fixture
51
+ def td(self, unit, val):
52
+ return Timedelta._from_value_and_reso(val, unit)
53
+
54
+ def test_from_value_and_reso(self, unit, val):
55
+ # Just checking that the fixture is giving us what we asked for
56
+ td = Timedelta._from_value_and_reso(val, unit)
57
+ assert td._value == val
58
+ assert td._creso == unit
59
+ assert td.days == 106752
60
+
61
+ def test_unary_non_nano(self, td, unit):
62
+ assert abs(td)._creso == unit
63
+ assert (-td)._creso == unit
64
+ assert (+td)._creso == unit
65
+
66
+ def test_sub_preserves_reso(self, td, unit):
67
+ res = td - td
68
+ expected = Timedelta._from_value_and_reso(0, unit)
69
+ assert res == expected
70
+ assert res._creso == unit
71
+
72
+ def test_mul_preserves_reso(self, td, unit):
73
+ # The td fixture should always be far from the implementation
74
+ # bound, so doubling does not risk overflow.
75
+ res = td * 2
76
+ assert res._value == td._value * 2
77
+ assert res._creso == unit
78
+
79
+ def test_cmp_cross_reso(self, td):
80
+ # numpy gets this wrong because of silent overflow
81
+ other = Timedelta(days=106751, unit="ns")
82
+ assert other < td
83
+ assert td > other
84
+ assert not other == td
85
+ assert td != other
86
+
87
+ def test_to_pytimedelta(self, td):
88
+ res = td.to_pytimedelta()
89
+ expected = timedelta(days=106752)
90
+ assert type(res) is timedelta
91
+ assert res == expected
92
+
93
+ def test_to_timedelta64(self, td, unit):
94
+ for res in [td.to_timedelta64(), td.to_numpy(), td.asm8]:
95
+ assert isinstance(res, np.timedelta64)
96
+ assert res.view("i8") == td._value
97
+ if unit == NpyDatetimeUnit.NPY_FR_s.value:
98
+ assert res.dtype == "m8[s]"
99
+ elif unit == NpyDatetimeUnit.NPY_FR_ms.value:
100
+ assert res.dtype == "m8[ms]"
101
+ elif unit == NpyDatetimeUnit.NPY_FR_us.value:
102
+ assert res.dtype == "m8[us]"
103
+
104
+ def test_truediv_timedeltalike(self, td):
105
+ assert td / td == 1
106
+ assert (2.5 * td) / td == 2.5
107
+
108
+ other = Timedelta(td._value)
109
+ msg = "Cannot cast 106752 days 00:00:00 to unit='ns' without overflow."
110
+ with pytest.raises(OutOfBoundsTimedelta, match=msg):
111
+ td / other
112
+
113
+ # Timedelta(other.to_pytimedelta()) has microsecond resolution,
114
+ # so the division doesn't require casting all the way to nanos,
115
+ # so succeeds
116
+ res = other.to_pytimedelta() / td
117
+ expected = other.to_pytimedelta() / td.to_pytimedelta()
118
+ assert res == expected
119
+
120
+ # if there's no overflow, we cast to the higher reso
121
+ left = Timedelta._from_value_and_reso(50, NpyDatetimeUnit.NPY_FR_us.value)
122
+ right = Timedelta._from_value_and_reso(50, NpyDatetimeUnit.NPY_FR_ms.value)
123
+ result = left / right
124
+ assert result == 0.001
125
+
126
+ result = right / left
127
+ assert result == 1000
128
+
129
+ def test_truediv_numeric(self, td):
130
+ assert td / np.nan is NaT
131
+
132
+ res = td / 2
133
+ assert res._value == td._value / 2
134
+ assert res._creso == td._creso
135
+
136
+ res = td / 2.0
137
+ assert res._value == td._value / 2
138
+ assert res._creso == td._creso
139
+
140
+ def test_floordiv_timedeltalike(self, td):
141
+ assert td // td == 1
142
+ assert (2.5 * td) // td == 2
143
+
144
+ other = Timedelta(td._value)
145
+ msg = "Cannot cast 106752 days 00:00:00 to unit='ns' without overflow"
146
+ with pytest.raises(OutOfBoundsTimedelta, match=msg):
147
+ td // other
148
+
149
+ # Timedelta(other.to_pytimedelta()) has microsecond resolution,
150
+ # so the floordiv doesn't require casting all the way to nanos,
151
+ # so succeeds
152
+ res = other.to_pytimedelta() // td
153
+ assert res == 0
154
+
155
+ # if there's no overflow, we cast to the higher reso
156
+ left = Timedelta._from_value_and_reso(50050, NpyDatetimeUnit.NPY_FR_us.value)
157
+ right = Timedelta._from_value_and_reso(50, NpyDatetimeUnit.NPY_FR_ms.value)
158
+ result = left // right
159
+ assert result == 1
160
+ result = right // left
161
+ assert result == 0
162
+
163
+ def test_floordiv_numeric(self, td):
164
+ assert td // np.nan is NaT
165
+
166
+ res = td // 2
167
+ assert res._value == td._value // 2
168
+ assert res._creso == td._creso
169
+
170
+ res = td // 2.0
171
+ assert res._value == td._value // 2
172
+ assert res._creso == td._creso
173
+
174
+ assert td // np.array(np.nan) is NaT
175
+
176
+ res = td // np.array(2)
177
+ assert res._value == td._value // 2
178
+ assert res._creso == td._creso
179
+
180
+ res = td // np.array(2.0)
181
+ assert res._value == td._value // 2
182
+ assert res._creso == td._creso
183
+
184
+ def test_addsub_mismatched_reso(self, td):
185
+ # need to cast to since td is out of bounds for ns, so
186
+ # so we would raise OverflowError without casting
187
+ other = Timedelta(days=1).as_unit("us")
188
+
189
+ # td is out of bounds for ns
190
+ result = td + other
191
+ assert result._creso == other._creso
192
+ assert result.days == td.days + 1
193
+
194
+ result = other + td
195
+ assert result._creso == other._creso
196
+ assert result.days == td.days + 1
197
+
198
+ result = td - other
199
+ assert result._creso == other._creso
200
+ assert result.days == td.days - 1
201
+
202
+ result = other - td
203
+ assert result._creso == other._creso
204
+ assert result.days == 1 - td.days
205
+
206
+ other2 = Timedelta(500)
207
+ msg = "Cannot cast 106752 days 00:00:00 to unit='ns' without overflow"
208
+ with pytest.raises(OutOfBoundsTimedelta, match=msg):
209
+ td + other2
210
+ with pytest.raises(OutOfBoundsTimedelta, match=msg):
211
+ other2 + td
212
+ with pytest.raises(OutOfBoundsTimedelta, match=msg):
213
+ td - other2
214
+ with pytest.raises(OutOfBoundsTimedelta, match=msg):
215
+ other2 - td
216
+
217
+ def test_min(self, td):
218
+ assert td.min <= td
219
+ assert td.min._creso == td._creso
220
+ assert td.min._value == NaT._value + 1
221
+
222
+ def test_max(self, td):
223
+ assert td.max >= td
224
+ assert td.max._creso == td._creso
225
+ assert td.max._value == np.iinfo(np.int64).max
226
+
227
+ def test_resolution(self, td):
228
+ expected = Timedelta._from_value_and_reso(1, td._creso)
229
+ result = td.resolution
230
+ assert result == expected
231
+ assert result._creso == expected._creso
232
+
233
+ def test_hash(self) -> None:
234
+ # GH#54037
235
+ second_resolution_max = Timedelta(0).as_unit("s").max
236
+
237
+ assert hash(second_resolution_max)
238
+
239
+
240
+ def test_timedelta_class_min_max_resolution():
241
+ # when accessed on the class (as opposed to an instance), we default
242
+ # to nanoseconds
243
+ assert Timedelta.min == Timedelta(NaT._value + 1)
244
+ assert Timedelta.min._creso == NpyDatetimeUnit.NPY_FR_ns.value
245
+
246
+ assert Timedelta.max == Timedelta(np.iinfo(np.int64).max)
247
+ assert Timedelta.max._creso == NpyDatetimeUnit.NPY_FR_ns.value
248
+
249
+ assert Timedelta.resolution == Timedelta(1)
250
+ assert Timedelta.resolution._creso == NpyDatetimeUnit.NPY_FR_ns.value
251
+
252
+
253
+ class TestTimedeltaUnaryOps:
254
+ def test_invert(self):
255
+ td = Timedelta(10, unit="d")
256
+
257
+ msg = "bad operand type for unary ~"
258
+ with pytest.raises(TypeError, match=msg):
259
+ ~td
260
+
261
+ # check this matches pytimedelta and timedelta64
262
+ with pytest.raises(TypeError, match=msg):
263
+ ~(td.to_pytimedelta())
264
+
265
+ umsg = "ufunc 'invert' not supported for the input types"
266
+ with pytest.raises(TypeError, match=umsg):
267
+ ~(td.to_timedelta64())
268
+
269
+ def test_unary_ops(self):
270
+ td = Timedelta(10, unit="d")
271
+
272
+ # __neg__, __pos__
273
+ assert -td == Timedelta(-10, unit="d")
274
+ assert -td == Timedelta("-10d")
275
+ assert +td == Timedelta(10, unit="d")
276
+
277
+ # __abs__, __abs__(__neg__)
278
+ assert abs(td) == td
279
+ assert abs(-td) == td
280
+ assert abs(-td) == Timedelta("10d")
281
+
282
+
283
+ class TestTimedeltas:
284
+ @pytest.mark.parametrize(
285
+ "unit, value, expected",
286
+ [
287
+ ("us", 9.999, 9999),
288
+ ("ms", 9.999999, 9999999),
289
+ ("s", 9.999999999, 9999999999),
290
+ ],
291
+ )
292
+ def test_rounding_on_int_unit_construction(self, unit, value, expected):
293
+ # GH 12690
294
+ result = Timedelta(value, unit=unit)
295
+ assert result._value == expected
296
+ result = Timedelta(str(value) + unit)
297
+ assert result._value == expected
298
+
299
+ def test_total_seconds_scalar(self):
300
+ # see gh-10939
301
+ rng = Timedelta("1 days, 10:11:12.100123456")
302
+ expt = 1 * 86400 + 10 * 3600 + 11 * 60 + 12 + 100123456.0 / 1e9
303
+ tm.assert_almost_equal(rng.total_seconds(), expt)
304
+
305
+ rng = Timedelta(np.nan)
306
+ assert np.isnan(rng.total_seconds())
307
+
308
+ def test_conversion(self):
309
+ for td in [Timedelta(10, unit="d"), Timedelta("1 days, 10:11:12.012345")]:
310
+ pydt = td.to_pytimedelta()
311
+ assert td == Timedelta(pydt)
312
+ assert td == pydt
313
+ assert isinstance(pydt, timedelta) and not isinstance(pydt, Timedelta)
314
+
315
+ assert td == np.timedelta64(td._value, "ns")
316
+ td64 = td.to_timedelta64()
317
+
318
+ assert td64 == np.timedelta64(td._value, "ns")
319
+ assert td == td64
320
+
321
+ assert isinstance(td64, np.timedelta64)
322
+
323
+ # this is NOT equal and cannot be roundtripped (because of the nanos)
324
+ td = Timedelta("1 days, 10:11:12.012345678")
325
+ assert td != td.to_pytimedelta()
326
+
327
+ def test_fields(self):
328
+ def check(value):
329
+ # that we are int
330
+ assert isinstance(value, int)
331
+
332
+ # compat to datetime.timedelta
333
+ rng = to_timedelta("1 days, 10:11:12")
334
+ assert rng.days == 1
335
+ assert rng.seconds == 10 * 3600 + 11 * 60 + 12
336
+ assert rng.microseconds == 0
337
+ assert rng.nanoseconds == 0
338
+
339
+ msg = "'Timedelta' object has no attribute '{}'"
340
+ with pytest.raises(AttributeError, match=msg.format("hours")):
341
+ rng.hours
342
+ with pytest.raises(AttributeError, match=msg.format("minutes")):
343
+ rng.minutes
344
+ with pytest.raises(AttributeError, match=msg.format("milliseconds")):
345
+ rng.milliseconds
346
+
347
+ # GH 10050
348
+ check(rng.days)
349
+ check(rng.seconds)
350
+ check(rng.microseconds)
351
+ check(rng.nanoseconds)
352
+
353
+ td = Timedelta("-1 days, 10:11:12")
354
+ assert abs(td) == Timedelta("13:48:48")
355
+ assert str(td) == "-1 days +10:11:12"
356
+ assert -td == Timedelta("0 days 13:48:48")
357
+ assert -Timedelta("-1 days, 10:11:12")._value == 49728000000000
358
+ assert Timedelta("-1 days, 10:11:12")._value == -49728000000000
359
+
360
+ rng = to_timedelta("-1 days, 10:11:12.100123456")
361
+ assert rng.days == -1
362
+ assert rng.seconds == 10 * 3600 + 11 * 60 + 12
363
+ assert rng.microseconds == 100 * 1000 + 123
364
+ assert rng.nanoseconds == 456
365
+ msg = "'Timedelta' object has no attribute '{}'"
366
+ with pytest.raises(AttributeError, match=msg.format("hours")):
367
+ rng.hours
368
+ with pytest.raises(AttributeError, match=msg.format("minutes")):
369
+ rng.minutes
370
+ with pytest.raises(AttributeError, match=msg.format("milliseconds")):
371
+ rng.milliseconds
372
+
373
+ # components
374
+ tup = to_timedelta(-1, "us").components
375
+ assert tup.days == -1
376
+ assert tup.hours == 23
377
+ assert tup.minutes == 59
378
+ assert tup.seconds == 59
379
+ assert tup.milliseconds == 999
380
+ assert tup.microseconds == 999
381
+ assert tup.nanoseconds == 0
382
+
383
+ # GH 10050
384
+ check(tup.days)
385
+ check(tup.hours)
386
+ check(tup.minutes)
387
+ check(tup.seconds)
388
+ check(tup.milliseconds)
389
+ check(tup.microseconds)
390
+ check(tup.nanoseconds)
391
+
392
+ tup = Timedelta("-1 days 1 us").components
393
+ assert tup.days == -2
394
+ assert tup.hours == 23
395
+ assert tup.minutes == 59
396
+ assert tup.seconds == 59
397
+ assert tup.milliseconds == 999
398
+ assert tup.microseconds == 999
399
+ assert tup.nanoseconds == 0
400
+
401
+ # TODO: this is a test of to_timedelta string parsing
402
+ def test_iso_conversion(self):
403
+ # GH #21877
404
+ expected = Timedelta(1, unit="s")
405
+ assert to_timedelta("P0DT0H0M1S") == expected
406
+
407
+ # TODO: this is a test of to_timedelta returning NaT
408
+ def test_nat_converters(self):
409
+ result = to_timedelta("nat").to_numpy()
410
+ assert result.dtype.kind == "M"
411
+ assert result.astype("int64") == iNaT
412
+
413
+ result = to_timedelta("nan").to_numpy()
414
+ assert result.dtype.kind == "M"
415
+ assert result.astype("int64") == iNaT
416
+
417
+ def test_numeric_conversions(self):
418
+ assert Timedelta(0) == np.timedelta64(0, "ns")
419
+ assert Timedelta(10) == np.timedelta64(10, "ns")
420
+ assert Timedelta(10, unit="ns") == np.timedelta64(10, "ns")
421
+
422
+ assert Timedelta(10, unit="us") == np.timedelta64(10, "us")
423
+ assert Timedelta(10, unit="ms") == np.timedelta64(10, "ms")
424
+ assert Timedelta(10, unit="s") == np.timedelta64(10, "s")
425
+ assert Timedelta(10, unit="d") == np.timedelta64(10, "D")
426
+
427
+ def test_timedelta_conversions(self):
428
+ assert Timedelta(timedelta(seconds=1)) == np.timedelta64(1, "s").astype(
429
+ "m8[ns]"
430
+ )
431
+ assert Timedelta(timedelta(microseconds=1)) == np.timedelta64(1, "us").astype(
432
+ "m8[ns]"
433
+ )
434
+ assert Timedelta(timedelta(days=1)) == np.timedelta64(1, "D").astype("m8[ns]")
435
+
436
+ def test_to_numpy_alias(self):
437
+ # GH 24653: alias .to_numpy() for scalars
438
+ td = Timedelta("10m7s")
439
+ assert td.to_timedelta64() == td.to_numpy()
440
+
441
+ # GH#44460
442
+ msg = "dtype and copy arguments are ignored"
443
+ with pytest.raises(ValueError, match=msg):
444
+ td.to_numpy("m8[s]")
445
+ with pytest.raises(ValueError, match=msg):
446
+ td.to_numpy(copy=True)
447
+
448
+ def test_identity(self):
449
+ td = Timedelta(10, unit="d")
450
+ assert isinstance(td, Timedelta)
451
+ assert isinstance(td, timedelta)
452
+
453
+ def test_short_format_converters(self):
454
+ def conv(v):
455
+ return v.astype("m8[ns]")
456
+
457
+ assert Timedelta("10") == np.timedelta64(10, "ns")
458
+ assert Timedelta("10ns") == np.timedelta64(10, "ns")
459
+ assert Timedelta("100") == np.timedelta64(100, "ns")
460
+ assert Timedelta("100ns") == np.timedelta64(100, "ns")
461
+
462
+ assert Timedelta("1000") == np.timedelta64(1000, "ns")
463
+ assert Timedelta("1000ns") == np.timedelta64(1000, "ns")
464
+ assert Timedelta("1000NS") == np.timedelta64(1000, "ns")
465
+
466
+ assert Timedelta("10us") == np.timedelta64(10000, "ns")
467
+ assert Timedelta("100us") == np.timedelta64(100000, "ns")
468
+ assert Timedelta("1000us") == np.timedelta64(1000000, "ns")
469
+ assert Timedelta("1000Us") == np.timedelta64(1000000, "ns")
470
+ assert Timedelta("1000uS") == np.timedelta64(1000000, "ns")
471
+
472
+ assert Timedelta("1ms") == np.timedelta64(1000000, "ns")
473
+ assert Timedelta("10ms") == np.timedelta64(10000000, "ns")
474
+ assert Timedelta("100ms") == np.timedelta64(100000000, "ns")
475
+ assert Timedelta("1000ms") == np.timedelta64(1000000000, "ns")
476
+
477
+ assert Timedelta("-1s") == -np.timedelta64(1000000000, "ns")
478
+ assert Timedelta("1s") == np.timedelta64(1000000000, "ns")
479
+ assert Timedelta("10s") == np.timedelta64(10000000000, "ns")
480
+ assert Timedelta("100s") == np.timedelta64(100000000000, "ns")
481
+ assert Timedelta("1000s") == np.timedelta64(1000000000000, "ns")
482
+
483
+ assert Timedelta("1d") == conv(np.timedelta64(1, "D"))
484
+ assert Timedelta("-1d") == -conv(np.timedelta64(1, "D"))
485
+ assert Timedelta("1D") == conv(np.timedelta64(1, "D"))
486
+ assert Timedelta("10D") == conv(np.timedelta64(10, "D"))
487
+ assert Timedelta("100D") == conv(np.timedelta64(100, "D"))
488
+ assert Timedelta("1000D") == conv(np.timedelta64(1000, "D"))
489
+ assert Timedelta("10000D") == conv(np.timedelta64(10000, "D"))
490
+
491
+ # space
492
+ assert Timedelta(" 10000D ") == conv(np.timedelta64(10000, "D"))
493
+ assert Timedelta(" - 10000D ") == -conv(np.timedelta64(10000, "D"))
494
+
495
+ # invalid
496
+ msg = "invalid unit abbreviation"
497
+ with pytest.raises(ValueError, match=msg):
498
+ Timedelta("1foo")
499
+ msg = "unit abbreviation w/o a number"
500
+ with pytest.raises(ValueError, match=msg):
501
+ Timedelta("foo")
502
+
503
+ def test_full_format_converters(self):
504
+ def conv(v):
505
+ return v.astype("m8[ns]")
506
+
507
+ d1 = np.timedelta64(1, "D")
508
+
509
+ assert Timedelta("1days") == conv(d1)
510
+ assert Timedelta("1days,") == conv(d1)
511
+ assert Timedelta("- 1days,") == -conv(d1)
512
+
513
+ assert Timedelta("00:00:01") == conv(np.timedelta64(1, "s"))
514
+ assert Timedelta("06:00:01") == conv(np.timedelta64(6 * 3600 + 1, "s"))
515
+ assert Timedelta("06:00:01.0") == conv(np.timedelta64(6 * 3600 + 1, "s"))
516
+ assert Timedelta("06:00:01.01") == conv(
517
+ np.timedelta64(1000 * (6 * 3600 + 1) + 10, "ms")
518
+ )
519
+
520
+ assert Timedelta("- 1days, 00:00:01") == conv(-d1 + np.timedelta64(1, "s"))
521
+ assert Timedelta("1days, 06:00:01") == conv(
522
+ d1 + np.timedelta64(6 * 3600 + 1, "s")
523
+ )
524
+ assert Timedelta("1days, 06:00:01.01") == conv(
525
+ d1 + np.timedelta64(1000 * (6 * 3600 + 1) + 10, "ms")
526
+ )
527
+
528
+ # invalid
529
+ msg = "have leftover units"
530
+ with pytest.raises(ValueError, match=msg):
531
+ Timedelta("- 1days, 00")
532
+
533
+ def test_pickle(self):
534
+ v = Timedelta("1 days 10:11:12.0123456")
535
+ v_p = tm.round_trip_pickle(v)
536
+ assert v == v_p
537
+
538
+ def test_timedelta_hash_equality(self):
539
+ # GH 11129
540
+ v = Timedelta(1, "D")
541
+ td = timedelta(days=1)
542
+ assert hash(v) == hash(td)
543
+
544
+ d = {td: 2}
545
+ assert d[v] == 2
546
+
547
+ tds = [Timedelta(seconds=1) + Timedelta(days=n) for n in range(20)]
548
+ assert all(hash(td) == hash(td.to_pytimedelta()) for td in tds)
549
+
550
+ # python timedeltas drop ns resolution
551
+ ns_td = Timedelta(1, "ns")
552
+ assert hash(ns_td) != hash(ns_td.to_pytimedelta())
553
+
554
+ @pytest.mark.skip_ubsan
555
+ @pytest.mark.xfail(
556
+ reason="pd.Timedelta violates the Python hash invariant (GH#44504).",
557
+ )
558
+ @given(
559
+ st.integers(
560
+ min_value=(-sys.maxsize - 1) // 500,
561
+ max_value=sys.maxsize // 500,
562
+ )
563
+ )
564
+ def test_hash_equality_invariance(self, half_microseconds: int) -> None:
565
+ # GH#44504
566
+
567
+ nanoseconds = half_microseconds * 500
568
+
569
+ pandas_timedelta = Timedelta(nanoseconds)
570
+ numpy_timedelta = np.timedelta64(nanoseconds)
571
+
572
+ # See: https://docs.python.org/3/glossary.html#term-hashable
573
+ # Hashable objects which compare equal must have the same hash value.
574
+ assert pandas_timedelta != numpy_timedelta or hash(pandas_timedelta) == hash(
575
+ numpy_timedelta
576
+ )
577
+
578
+ def test_implementation_limits(self):
579
+ min_td = Timedelta(Timedelta.min)
580
+ max_td = Timedelta(Timedelta.max)
581
+
582
+ # GH 12727
583
+ # timedelta limits correspond to int64 boundaries
584
+ assert min_td._value == iNaT + 1
585
+ assert max_td._value == lib.i8max
586
+
587
+ # Beyond lower limit, a NAT before the Overflow
588
+ assert (min_td - Timedelta(1, "ns")) is NaT
589
+
590
+ msg = "int too (large|big) to convert"
591
+ with pytest.raises(OverflowError, match=msg):
592
+ min_td - Timedelta(2, "ns")
593
+
594
+ with pytest.raises(OverflowError, match=msg):
595
+ max_td + Timedelta(1, "ns")
596
+
597
+ # Same tests using the internal nanosecond values
598
+ td = Timedelta(min_td._value - 1, "ns")
599
+ assert td is NaT
600
+
601
+ msg = "Cannot cast -9223372036854775809 from ns to 'ns' without overflow"
602
+ with pytest.raises(OutOfBoundsTimedelta, match=msg):
603
+ Timedelta(min_td._value - 2, "ns")
604
+
605
+ msg = "Cannot cast 9223372036854775808 from ns to 'ns' without overflow"
606
+ with pytest.raises(OutOfBoundsTimedelta, match=msg):
607
+ Timedelta(max_td._value + 1, "ns")
608
+
609
+ def test_total_seconds_precision(self):
610
+ # GH 19458
611
+ assert Timedelta("30s").total_seconds() == 30.0
612
+ assert Timedelta("0").total_seconds() == 0.0
613
+ assert Timedelta("-2s").total_seconds() == -2.0
614
+ assert Timedelta("5.324s").total_seconds() == 5.324
615
+ assert (Timedelta("30s").total_seconds() - 30.0) < 1e-20
616
+ assert (30.0 - Timedelta("30s").total_seconds()) < 1e-20
617
+
618
+ def test_resolution_string(self):
619
+ assert Timedelta(days=1).resolution_string == "D"
620
+ assert Timedelta(days=1, hours=6).resolution_string == "h"
621
+ assert Timedelta(days=1, minutes=6).resolution_string == "min"
622
+ assert Timedelta(days=1, seconds=6).resolution_string == "s"
623
+ assert Timedelta(days=1, milliseconds=6).resolution_string == "ms"
624
+ assert Timedelta(days=1, microseconds=6).resolution_string == "us"
625
+ assert Timedelta(days=1, nanoseconds=6).resolution_string == "ns"
626
+
627
+ def test_resolution_deprecated(self):
628
+ # GH#21344
629
+ td = Timedelta(days=4, hours=3)
630
+ result = td.resolution
631
+ assert result == Timedelta(nanoseconds=1)
632
+
633
+ # Check that the attribute is available on the class, mirroring
634
+ # the stdlib timedelta behavior
635
+ result = Timedelta.resolution
636
+ assert result == Timedelta(nanoseconds=1)
637
+
638
+
639
+ @pytest.mark.parametrize(
640
+ "value, expected",
641
+ [
642
+ (Timedelta("10s"), True),
643
+ (Timedelta("-10s"), True),
644
+ (Timedelta(10, unit="ns"), True),
645
+ (Timedelta(0, unit="ns"), False),
646
+ (Timedelta(-10, unit="ns"), True),
647
+ (Timedelta(None), True),
648
+ (NaT, True),
649
+ ],
650
+ )
651
+ def test_truthiness(value, expected):
652
+ # https://github.com/pandas-dev/pandas/issues/21484
653
+ assert bool(value) is expected
654
+
655
+
656
+ def test_timedelta_attribute_precision():
657
+ # GH 31354
658
+ td = Timedelta(1552211999999999872, unit="ns")
659
+ result = td.days * 86400
660
+ result += td.seconds
661
+ result *= 1000000
662
+ result += td.microseconds
663
+ result *= 1000
664
+ result += td.nanoseconds
665
+ expected = td._value
666
+ assert result == expected
py311/lib/python3.11/site-packages/pandas/tests/scalar/timestamp/__init__.py ADDED
File without changes
py311/lib/python3.11/site-packages/pandas/tests/scalar/timestamp/methods/__init__.py ADDED
File without changes
py311/lib/python3.11/site-packages/pandas/tests/scalar/timestamp/methods/test_as_unit.py ADDED
@@ -0,0 +1,86 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import pytest
2
+
3
+ from pandas._libs.tslibs.dtypes import NpyDatetimeUnit
4
+ from pandas.errors import OutOfBoundsDatetime
5
+
6
+ from pandas import Timestamp
7
+
8
+
9
+ class TestTimestampAsUnit:
10
+ def test_as_unit(self):
11
+ ts = Timestamp("1970-01-01").as_unit("ns")
12
+ assert ts.unit == "ns"
13
+
14
+ assert ts.as_unit("ns") is ts
15
+
16
+ res = ts.as_unit("us")
17
+ assert res._value == ts._value // 1000
18
+ assert res._creso == NpyDatetimeUnit.NPY_FR_us.value
19
+
20
+ rt = res.as_unit("ns")
21
+ assert rt._value == ts._value
22
+ assert rt._creso == ts._creso
23
+
24
+ res = ts.as_unit("ms")
25
+ assert res._value == ts._value // 1_000_000
26
+ assert res._creso == NpyDatetimeUnit.NPY_FR_ms.value
27
+
28
+ rt = res.as_unit("ns")
29
+ assert rt._value == ts._value
30
+ assert rt._creso == ts._creso
31
+
32
+ res = ts.as_unit("s")
33
+ assert res._value == ts._value // 1_000_000_000
34
+ assert res._creso == NpyDatetimeUnit.NPY_FR_s.value
35
+
36
+ rt = res.as_unit("ns")
37
+ assert rt._value == ts._value
38
+ assert rt._creso == ts._creso
39
+
40
+ def test_as_unit_overflows(self):
41
+ # microsecond that would be just out of bounds for nano
42
+ us = 9223372800000000
43
+ ts = Timestamp._from_value_and_reso(us, NpyDatetimeUnit.NPY_FR_us.value, None)
44
+
45
+ msg = "Cannot cast 2262-04-12 00:00:00 to unit='ns' without overflow"
46
+ with pytest.raises(OutOfBoundsDatetime, match=msg):
47
+ ts.as_unit("ns")
48
+
49
+ res = ts.as_unit("ms")
50
+ assert res._value == us // 1000
51
+ assert res._creso == NpyDatetimeUnit.NPY_FR_ms.value
52
+
53
+ def test_as_unit_rounding(self):
54
+ ts = Timestamp(1_500_000) # i.e. 1500 microseconds
55
+ res = ts.as_unit("ms")
56
+
57
+ expected = Timestamp(1_000_000) # i.e. 1 millisecond
58
+ assert res == expected
59
+
60
+ assert res._creso == NpyDatetimeUnit.NPY_FR_ms.value
61
+ assert res._value == 1
62
+
63
+ with pytest.raises(ValueError, match="Cannot losslessly convert units"):
64
+ ts.as_unit("ms", round_ok=False)
65
+
66
+ def test_as_unit_non_nano(self):
67
+ # case where we are going neither to nor from nano
68
+ ts = Timestamp("1970-01-02").as_unit("ms")
69
+ assert ts.year == 1970
70
+ assert ts.month == 1
71
+ assert ts.day == 2
72
+ assert ts.hour == ts.minute == ts.second == ts.microsecond == ts.nanosecond == 0
73
+
74
+ res = ts.as_unit("s")
75
+ assert res._value == 24 * 3600
76
+ assert res.year == 1970
77
+ assert res.month == 1
78
+ assert res.day == 2
79
+ assert (
80
+ res.hour
81
+ == res.minute
82
+ == res.second
83
+ == res.microsecond
84
+ == res.nanosecond
85
+ == 0
86
+ )
py311/lib/python3.11/site-packages/pandas/tests/scalar/timestamp/methods/test_normalize.py ADDED
@@ -0,0 +1,22 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import pytest
2
+
3
+ from pandas._libs.tslibs import Timestamp
4
+ from pandas._libs.tslibs.dtypes import NpyDatetimeUnit
5
+
6
+
7
+ class TestTimestampNormalize:
8
+ @pytest.mark.parametrize("arg", ["2013-11-30", "2013-11-30 12:00:00"])
9
+ @pytest.mark.parametrize("unit", ["ns", "us", "ms", "s"])
10
+ def test_normalize(self, tz_naive_fixture, arg, unit):
11
+ tz = tz_naive_fixture
12
+ ts = Timestamp(arg, tz=tz).as_unit(unit)
13
+ result = ts.normalize()
14
+ expected = Timestamp("2013-11-30", tz=tz)
15
+ assert result == expected
16
+ assert result._creso == getattr(NpyDatetimeUnit, f"NPY_FR_{unit}").value
17
+
18
+ def test_normalize_pre_epoch_dates(self):
19
+ # GH: 36294
20
+ result = Timestamp("1969-01-01 09:00:00").normalize()
21
+ expected = Timestamp("1969-01-01 00:00:00")
22
+ assert result == expected
py311/lib/python3.11/site-packages/pandas/tests/scalar/timestamp/methods/test_replace.py ADDED
@@ -0,0 +1,193 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from datetime import datetime
2
+
3
+ from dateutil.tz import gettz
4
+ import numpy as np
5
+ import pytest
6
+ import pytz
7
+
8
+ from pandas._libs.tslibs import (
9
+ OutOfBoundsDatetime,
10
+ Timestamp,
11
+ conversion,
12
+ )
13
+ from pandas._libs.tslibs.dtypes import NpyDatetimeUnit
14
+ import pandas.util._test_decorators as td
15
+
16
+ import pandas._testing as tm
17
+
18
+
19
+ class TestTimestampReplace:
20
+ def test_replace_out_of_pydatetime_bounds(self):
21
+ # GH#50348
22
+ ts = Timestamp("2016-01-01").as_unit("ns")
23
+
24
+ msg = "Out of bounds timestamp: 99999-01-01 00:00:00 with frequency 'ns'"
25
+ with pytest.raises(OutOfBoundsDatetime, match=msg):
26
+ ts.replace(year=99_999)
27
+
28
+ ts = ts.as_unit("ms")
29
+ result = ts.replace(year=99_999)
30
+ assert result.year == 99_999
31
+ assert result._value == Timestamp(np.datetime64("99999-01-01", "ms"))._value
32
+
33
+ def test_replace_non_nano(self):
34
+ ts = Timestamp._from_value_and_reso(
35
+ 91514880000000000, NpyDatetimeUnit.NPY_FR_us.value, None
36
+ )
37
+ assert ts.to_pydatetime() == datetime(4869, 12, 28)
38
+
39
+ result = ts.replace(year=4900)
40
+ assert result._creso == ts._creso
41
+ assert result.to_pydatetime() == datetime(4900, 12, 28)
42
+
43
+ def test_replace_naive(self):
44
+ # GH#14621, GH#7825
45
+ ts = Timestamp("2016-01-01 09:00:00")
46
+ result = ts.replace(hour=0)
47
+ expected = Timestamp("2016-01-01 00:00:00")
48
+ assert result == expected
49
+
50
+ def test_replace_aware(self, tz_aware_fixture):
51
+ tz = tz_aware_fixture
52
+ # GH#14621, GH#7825
53
+ # replacing datetime components with and w/o presence of a timezone
54
+ ts = Timestamp("2016-01-01 09:00:00", tz=tz)
55
+ result = ts.replace(hour=0)
56
+ expected = Timestamp("2016-01-01 00:00:00", tz=tz)
57
+ assert result == expected
58
+
59
+ def test_replace_preserves_nanos(self, tz_aware_fixture):
60
+ tz = tz_aware_fixture
61
+ # GH#14621, GH#7825
62
+ ts = Timestamp("2016-01-01 09:00:00.000000123", tz=tz)
63
+ result = ts.replace(hour=0)
64
+ expected = Timestamp("2016-01-01 00:00:00.000000123", tz=tz)
65
+ assert result == expected
66
+
67
+ def test_replace_multiple(self, tz_aware_fixture):
68
+ tz = tz_aware_fixture
69
+ # GH#14621, GH#7825
70
+ # replacing datetime components with and w/o presence of a timezone
71
+ # test all
72
+ ts = Timestamp("2016-01-01 09:00:00.000000123", tz=tz)
73
+ result = ts.replace(
74
+ year=2015,
75
+ month=2,
76
+ day=2,
77
+ hour=0,
78
+ minute=5,
79
+ second=5,
80
+ microsecond=5,
81
+ nanosecond=5,
82
+ )
83
+ expected = Timestamp("2015-02-02 00:05:05.000005005", tz=tz)
84
+ assert result == expected
85
+
86
+ def test_replace_invalid_kwarg(self, tz_aware_fixture):
87
+ tz = tz_aware_fixture
88
+ # GH#14621, GH#7825
89
+ ts = Timestamp("2016-01-01 09:00:00.000000123", tz=tz)
90
+ msg = r"replace\(\) got an unexpected keyword argument"
91
+ with pytest.raises(TypeError, match=msg):
92
+ ts.replace(foo=5)
93
+
94
+ def test_replace_integer_args(self, tz_aware_fixture):
95
+ tz = tz_aware_fixture
96
+ # GH#14621, GH#7825
97
+ ts = Timestamp("2016-01-01 09:00:00.000000123", tz=tz)
98
+ msg = "value must be an integer, received <class 'float'> for hour"
99
+ with pytest.raises(ValueError, match=msg):
100
+ ts.replace(hour=0.1)
101
+
102
+ def test_replace_tzinfo_equiv_tz_localize_none(self):
103
+ # GH#14621, GH#7825
104
+ # assert conversion to naive is the same as replacing tzinfo with None
105
+ ts = Timestamp("2013-11-03 01:59:59.999999-0400", tz="US/Eastern")
106
+ assert ts.tz_localize(None) == ts.replace(tzinfo=None)
107
+
108
+ @td.skip_if_windows
109
+ def test_replace_tzinfo(self):
110
+ # GH#15683
111
+ dt = datetime(2016, 3, 27, 1)
112
+ tzinfo = pytz.timezone("CET").localize(dt, is_dst=False).tzinfo
113
+
114
+ result_dt = dt.replace(tzinfo=tzinfo)
115
+ result_pd = Timestamp(dt).replace(tzinfo=tzinfo)
116
+
117
+ # datetime.timestamp() converts in the local timezone
118
+ with tm.set_timezone("UTC"):
119
+ assert result_dt.timestamp() == result_pd.timestamp()
120
+
121
+ assert result_dt == result_pd
122
+ assert result_dt == result_pd.to_pydatetime()
123
+
124
+ result_dt = dt.replace(tzinfo=tzinfo).replace(tzinfo=None)
125
+ result_pd = Timestamp(dt).replace(tzinfo=tzinfo).replace(tzinfo=None)
126
+
127
+ # datetime.timestamp() converts in the local timezone
128
+ with tm.set_timezone("UTC"):
129
+ assert result_dt.timestamp() == result_pd.timestamp()
130
+
131
+ assert result_dt == result_pd
132
+ assert result_dt == result_pd.to_pydatetime()
133
+
134
+ @pytest.mark.parametrize(
135
+ "tz, normalize",
136
+ [
137
+ (pytz.timezone("US/Eastern"), lambda x: x.tzinfo.normalize(x)),
138
+ (gettz("US/Eastern"), lambda x: x),
139
+ ],
140
+ )
141
+ def test_replace_across_dst(self, tz, normalize):
142
+ # GH#18319 check that 1) timezone is correctly normalized and
143
+ # 2) that hour is not incorrectly changed by this normalization
144
+ ts_naive = Timestamp("2017-12-03 16:03:30")
145
+ ts_aware = conversion.localize_pydatetime(ts_naive, tz)
146
+
147
+ # Preliminary sanity-check
148
+ assert ts_aware == normalize(ts_aware)
149
+
150
+ # Replace across DST boundary
151
+ ts2 = ts_aware.replace(month=6)
152
+
153
+ # Check that `replace` preserves hour literal
154
+ assert (ts2.hour, ts2.minute) == (ts_aware.hour, ts_aware.minute)
155
+
156
+ # Check that post-replace object is appropriately normalized
157
+ ts2b = normalize(ts2)
158
+ assert ts2 == ts2b
159
+
160
+ @pytest.mark.parametrize("unit", ["ns", "us", "ms", "s"])
161
+ def test_replace_dst_border(self, unit):
162
+ # Gh 7825
163
+ t = Timestamp("2013-11-3", tz="America/Chicago").as_unit(unit)
164
+ result = t.replace(hour=3)
165
+ expected = Timestamp("2013-11-3 03:00:00", tz="America/Chicago")
166
+ assert result == expected
167
+ assert result._creso == getattr(NpyDatetimeUnit, f"NPY_FR_{unit}").value
168
+
169
+ @pytest.mark.parametrize("fold", [0, 1])
170
+ @pytest.mark.parametrize("tz", ["dateutil/Europe/London", "Europe/London"])
171
+ @pytest.mark.parametrize("unit", ["ns", "us", "ms", "s"])
172
+ def test_replace_dst_fold(self, fold, tz, unit):
173
+ # GH 25017
174
+ d = datetime(2019, 10, 27, 2, 30)
175
+ ts = Timestamp(d, tz=tz).as_unit(unit)
176
+ result = ts.replace(hour=1, fold=fold)
177
+ expected = Timestamp(datetime(2019, 10, 27, 1, 30)).tz_localize(
178
+ tz, ambiguous=not fold
179
+ )
180
+ assert result == expected
181
+ assert result._creso == getattr(NpyDatetimeUnit, f"NPY_FR_{unit}").value
182
+
183
+ @pytest.mark.parametrize("fold", [0, 1])
184
+ def test_replace_preserves_fold(self, fold):
185
+ # GH#37610. Check that replace preserves Timestamp fold property
186
+ tz = gettz("Europe/Moscow")
187
+
188
+ ts = Timestamp(
189
+ year=2009, month=10, day=25, hour=2, minute=30, fold=fold, tzinfo=tz
190
+ )
191
+ ts_replaced = ts.replace(second=1)
192
+
193
+ assert ts_replaced.fold == fold
py311/lib/python3.11/site-packages/pandas/tests/scalar/timestamp/methods/test_round.py ADDED
@@ -0,0 +1,383 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from hypothesis import (
2
+ given,
3
+ strategies as st,
4
+ )
5
+ import numpy as np
6
+ import pytest
7
+ import pytz
8
+
9
+ from pandas._libs import lib
10
+ from pandas._libs.tslibs import (
11
+ NaT,
12
+ OutOfBoundsDatetime,
13
+ Timedelta,
14
+ Timestamp,
15
+ iNaT,
16
+ to_offset,
17
+ )
18
+ from pandas._libs.tslibs.dtypes import NpyDatetimeUnit
19
+ from pandas._libs.tslibs.period import INVALID_FREQ_ERR_MSG
20
+
21
+ import pandas._testing as tm
22
+
23
+
24
+ class TestTimestampRound:
25
+ def test_round_division_by_zero_raises(self):
26
+ ts = Timestamp("2016-01-01")
27
+
28
+ msg = "Division by zero in rounding"
29
+ with pytest.raises(ValueError, match=msg):
30
+ ts.round("0ns")
31
+
32
+ @pytest.mark.parametrize(
33
+ "timestamp, freq, expected",
34
+ [
35
+ ("20130101 09:10:11", "D", "20130101"),
36
+ ("20130101 19:10:11", "D", "20130102"),
37
+ ("20130201 12:00:00", "D", "20130202"),
38
+ ("20130104 12:00:00", "D", "20130105"),
39
+ ("2000-01-05 05:09:15.13", "D", "2000-01-05 00:00:00"),
40
+ ("2000-01-05 05:09:15.13", "h", "2000-01-05 05:00:00"),
41
+ ("2000-01-05 05:09:15.13", "s", "2000-01-05 05:09:15"),
42
+ ],
43
+ )
44
+ def test_round_frequencies(self, timestamp, freq, expected):
45
+ dt = Timestamp(timestamp)
46
+ result = dt.round(freq)
47
+ expected = Timestamp(expected)
48
+ assert result == expected
49
+
50
+ def test_round_tzaware(self):
51
+ dt = Timestamp("20130101 09:10:11", tz="US/Eastern")
52
+ result = dt.round("D")
53
+ expected = Timestamp("20130101", tz="US/Eastern")
54
+ assert result == expected
55
+
56
+ dt = Timestamp("20130101 09:10:11", tz="US/Eastern")
57
+ result = dt.round("s")
58
+ assert result == dt
59
+
60
+ def test_round_30min(self):
61
+ # round
62
+ dt = Timestamp("20130104 12:32:00")
63
+ result = dt.round("30Min")
64
+ expected = Timestamp("20130104 12:30:00")
65
+ assert result == expected
66
+
67
+ def test_round_subsecond(self):
68
+ # GH#14440 & GH#15578
69
+ result = Timestamp("2016-10-17 12:00:00.0015").round("ms")
70
+ expected = Timestamp("2016-10-17 12:00:00.002000")
71
+ assert result == expected
72
+
73
+ result = Timestamp("2016-10-17 12:00:00.00149").round("ms")
74
+ expected = Timestamp("2016-10-17 12:00:00.001000")
75
+ assert result == expected
76
+
77
+ ts = Timestamp("2016-10-17 12:00:00.0015")
78
+ for freq in ["us", "ns"]:
79
+ assert ts == ts.round(freq)
80
+
81
+ result = Timestamp("2016-10-17 12:00:00.001501031").round("10ns")
82
+ expected = Timestamp("2016-10-17 12:00:00.001501030")
83
+ assert result == expected
84
+
85
+ def test_round_nonstandard_freq(self):
86
+ with tm.assert_produces_warning(False):
87
+ Timestamp("2016-10-17 12:00:00.001501031").round("1010ns")
88
+
89
+ def test_round_invalid_arg(self):
90
+ stamp = Timestamp("2000-01-05 05:09:15.13")
91
+ with pytest.raises(ValueError, match=INVALID_FREQ_ERR_MSG):
92
+ stamp.round("foo")
93
+
94
+ @pytest.mark.parametrize(
95
+ "test_input, rounder, freq, expected",
96
+ [
97
+ ("2117-01-01 00:00:45", "floor", "15s", "2117-01-01 00:00:45"),
98
+ ("2117-01-01 00:00:45", "ceil", "15s", "2117-01-01 00:00:45"),
99
+ (
100
+ "2117-01-01 00:00:45.000000012",
101
+ "floor",
102
+ "10ns",
103
+ "2117-01-01 00:00:45.000000010",
104
+ ),
105
+ (
106
+ "1823-01-01 00:00:01.000000012",
107
+ "ceil",
108
+ "10ns",
109
+ "1823-01-01 00:00:01.000000020",
110
+ ),
111
+ ("1823-01-01 00:00:01", "floor", "1s", "1823-01-01 00:00:01"),
112
+ ("1823-01-01 00:00:01", "ceil", "1s", "1823-01-01 00:00:01"),
113
+ ("NaT", "floor", "1s", "NaT"),
114
+ ("NaT", "ceil", "1s", "NaT"),
115
+ ],
116
+ )
117
+ def test_ceil_floor_edge(self, test_input, rounder, freq, expected):
118
+ dt = Timestamp(test_input)
119
+ func = getattr(dt, rounder)
120
+ result = func(freq)
121
+
122
+ if dt is NaT:
123
+ assert result is NaT
124
+ else:
125
+ expected = Timestamp(expected)
126
+ assert result == expected
127
+
128
+ @pytest.mark.parametrize(
129
+ "test_input, freq, expected",
130
+ [
131
+ ("2018-01-01 00:02:06", "2s", "2018-01-01 00:02:06"),
132
+ ("2018-01-01 00:02:00", "2min", "2018-01-01 00:02:00"),
133
+ ("2018-01-01 00:04:00", "4min", "2018-01-01 00:04:00"),
134
+ ("2018-01-01 00:15:00", "15min", "2018-01-01 00:15:00"),
135
+ ("2018-01-01 00:20:00", "20min", "2018-01-01 00:20:00"),
136
+ ("2018-01-01 03:00:00", "3h", "2018-01-01 03:00:00"),
137
+ ],
138
+ )
139
+ @pytest.mark.parametrize("rounder", ["ceil", "floor", "round"])
140
+ def test_round_minute_freq(self, test_input, freq, expected, rounder):
141
+ # Ensure timestamps that shouldn't round dont!
142
+ # GH#21262
143
+
144
+ dt = Timestamp(test_input)
145
+ expected = Timestamp(expected)
146
+ func = getattr(dt, rounder)
147
+ result = func(freq)
148
+ assert result == expected
149
+
150
+ @pytest.mark.parametrize("unit", ["ns", "us", "ms", "s"])
151
+ def test_ceil(self, unit):
152
+ dt = Timestamp("20130101 09:10:11").as_unit(unit)
153
+ result = dt.ceil("D")
154
+ expected = Timestamp("20130102")
155
+ assert result == expected
156
+ assert result._creso == dt._creso
157
+
158
+ @pytest.mark.parametrize("unit", ["ns", "us", "ms", "s"])
159
+ def test_floor(self, unit):
160
+ dt = Timestamp("20130101 09:10:11").as_unit(unit)
161
+ result = dt.floor("D")
162
+ expected = Timestamp("20130101")
163
+ assert result == expected
164
+ assert result._creso == dt._creso
165
+
166
+ @pytest.mark.parametrize("method", ["ceil", "round", "floor"])
167
+ @pytest.mark.parametrize(
168
+ "unit",
169
+ ["ns", "us", "ms", "s"],
170
+ )
171
+ def test_round_dst_border_ambiguous(self, method, unit):
172
+ # GH 18946 round near "fall back" DST
173
+ ts = Timestamp("2017-10-29 00:00:00", tz="UTC").tz_convert("Europe/Madrid")
174
+ ts = ts.as_unit(unit)
175
+ #
176
+ result = getattr(ts, method)("h", ambiguous=True)
177
+ assert result == ts
178
+ assert result._creso == getattr(NpyDatetimeUnit, f"NPY_FR_{unit}").value
179
+
180
+ result = getattr(ts, method)("h", ambiguous=False)
181
+ expected = Timestamp("2017-10-29 01:00:00", tz="UTC").tz_convert(
182
+ "Europe/Madrid"
183
+ )
184
+ assert result == expected
185
+ assert result._creso == getattr(NpyDatetimeUnit, f"NPY_FR_{unit}").value
186
+
187
+ result = getattr(ts, method)("h", ambiguous="NaT")
188
+ assert result is NaT
189
+
190
+ msg = "Cannot infer dst time"
191
+ with pytest.raises(pytz.AmbiguousTimeError, match=msg):
192
+ getattr(ts, method)("h", ambiguous="raise")
193
+
194
+ @pytest.mark.parametrize(
195
+ "method, ts_str, freq",
196
+ [
197
+ ["ceil", "2018-03-11 01:59:00-0600", "5min"],
198
+ ["round", "2018-03-11 01:59:00-0600", "5min"],
199
+ ["floor", "2018-03-11 03:01:00-0500", "2h"],
200
+ ],
201
+ )
202
+ @pytest.mark.parametrize(
203
+ "unit",
204
+ ["ns", "us", "ms", "s"],
205
+ )
206
+ def test_round_dst_border_nonexistent(self, method, ts_str, freq, unit):
207
+ # GH 23324 round near "spring forward" DST
208
+ ts = Timestamp(ts_str, tz="America/Chicago").as_unit(unit)
209
+ result = getattr(ts, method)(freq, nonexistent="shift_forward")
210
+ expected = Timestamp("2018-03-11 03:00:00", tz="America/Chicago")
211
+ assert result == expected
212
+ assert result._creso == getattr(NpyDatetimeUnit, f"NPY_FR_{unit}").value
213
+
214
+ result = getattr(ts, method)(freq, nonexistent="NaT")
215
+ assert result is NaT
216
+
217
+ msg = "2018-03-11 02:00:00"
218
+ with pytest.raises(pytz.NonExistentTimeError, match=msg):
219
+ getattr(ts, method)(freq, nonexistent="raise")
220
+
221
+ @pytest.mark.parametrize(
222
+ "timestamp",
223
+ [
224
+ "2018-01-01 0:0:0.124999360",
225
+ "2018-01-01 0:0:0.125000367",
226
+ "2018-01-01 0:0:0.125500",
227
+ "2018-01-01 0:0:0.126500",
228
+ "2018-01-01 12:00:00",
229
+ "2019-01-01 12:00:00",
230
+ ],
231
+ )
232
+ @pytest.mark.parametrize(
233
+ "freq",
234
+ [
235
+ "2ns",
236
+ "3ns",
237
+ "4ns",
238
+ "5ns",
239
+ "6ns",
240
+ "7ns",
241
+ "250ns",
242
+ "500ns",
243
+ "750ns",
244
+ "1us",
245
+ "19us",
246
+ "250us",
247
+ "500us",
248
+ "750us",
249
+ "1s",
250
+ "2s",
251
+ "3s",
252
+ "1D",
253
+ ],
254
+ )
255
+ def test_round_int64(self, timestamp, freq):
256
+ # check that all rounding modes are accurate to int64 precision
257
+ # see GH#22591
258
+ dt = Timestamp(timestamp).as_unit("ns")
259
+ unit = to_offset(freq).nanos
260
+
261
+ # test floor
262
+ result = dt.floor(freq)
263
+ assert result._value % unit == 0, f"floor not a {freq} multiple"
264
+ assert 0 <= dt._value - result._value < unit, "floor error"
265
+
266
+ # test ceil
267
+ result = dt.ceil(freq)
268
+ assert result._value % unit == 0, f"ceil not a {freq} multiple"
269
+ assert 0 <= result._value - dt._value < unit, "ceil error"
270
+
271
+ # test round
272
+ result = dt.round(freq)
273
+ assert result._value % unit == 0, f"round not a {freq} multiple"
274
+ assert abs(result._value - dt._value) <= unit // 2, "round error"
275
+ if unit % 2 == 0 and abs(result._value - dt._value) == unit // 2:
276
+ # round half to even
277
+ assert result._value // unit % 2 == 0, "round half to even error"
278
+
279
+ def test_round_implementation_bounds(self):
280
+ # See also: analogous test for Timedelta
281
+ result = Timestamp.min.ceil("s")
282
+ expected = Timestamp(1677, 9, 21, 0, 12, 44)
283
+ assert result == expected
284
+
285
+ result = Timestamp.max.floor("s")
286
+ expected = Timestamp.max - Timedelta(854775807)
287
+ assert result == expected
288
+
289
+ msg = "Cannot round 1677-09-21 00:12:43.145224193 to freq=<Second>"
290
+ with pytest.raises(OutOfBoundsDatetime, match=msg):
291
+ Timestamp.min.floor("s")
292
+
293
+ with pytest.raises(OutOfBoundsDatetime, match=msg):
294
+ Timestamp.min.round("s")
295
+
296
+ msg = "Cannot round 2262-04-11 23:47:16.854775807 to freq=<Second>"
297
+ with pytest.raises(OutOfBoundsDatetime, match=msg):
298
+ Timestamp.max.ceil("s")
299
+
300
+ with pytest.raises(OutOfBoundsDatetime, match=msg):
301
+ Timestamp.max.round("s")
302
+
303
+ @given(val=st.integers(iNaT + 1, lib.i8max))
304
+ @pytest.mark.parametrize(
305
+ "method", [Timestamp.round, Timestamp.floor, Timestamp.ceil]
306
+ )
307
+ def test_round_sanity(self, val, method):
308
+ cls = Timestamp
309
+ err_cls = OutOfBoundsDatetime
310
+
311
+ val = np.int64(val)
312
+ ts = cls(val)
313
+
314
+ def checker(ts, nanos, unit):
315
+ # First check that we do raise in cases where we should
316
+ if nanos == 1:
317
+ pass
318
+ else:
319
+ div, mod = divmod(ts._value, nanos)
320
+ diff = int(nanos - mod)
321
+ lb = ts._value - mod
322
+ assert lb <= ts._value # i.e. no overflows with python ints
323
+ ub = ts._value + diff
324
+ assert ub > ts._value # i.e. no overflows with python ints
325
+
326
+ msg = "without overflow"
327
+ if mod == 0:
328
+ # We should never be raising in this
329
+ pass
330
+ elif method is cls.ceil:
331
+ if ub > cls.max._value:
332
+ with pytest.raises(err_cls, match=msg):
333
+ method(ts, unit)
334
+ return
335
+ elif method is cls.floor:
336
+ if lb < cls.min._value:
337
+ with pytest.raises(err_cls, match=msg):
338
+ method(ts, unit)
339
+ return
340
+ elif mod >= diff:
341
+ if ub > cls.max._value:
342
+ with pytest.raises(err_cls, match=msg):
343
+ method(ts, unit)
344
+ return
345
+ elif lb < cls.min._value:
346
+ with pytest.raises(err_cls, match=msg):
347
+ method(ts, unit)
348
+ return
349
+
350
+ res = method(ts, unit)
351
+
352
+ td = res - ts
353
+ diff = abs(td._value)
354
+ assert diff < nanos
355
+ assert res._value % nanos == 0
356
+
357
+ if method is cls.round:
358
+ assert diff <= nanos / 2
359
+ elif method is cls.floor:
360
+ assert res <= ts
361
+ elif method is cls.ceil:
362
+ assert res >= ts
363
+
364
+ nanos = 1
365
+ checker(ts, nanos, "ns")
366
+
367
+ nanos = 1000
368
+ checker(ts, nanos, "us")
369
+
370
+ nanos = 1_000_000
371
+ checker(ts, nanos, "ms")
372
+
373
+ nanos = 1_000_000_000
374
+ checker(ts, nanos, "s")
375
+
376
+ nanos = 60 * 1_000_000_000
377
+ checker(ts, nanos, "min")
378
+
379
+ nanos = 60 * 60 * 1_000_000_000
380
+ checker(ts, nanos, "h")
381
+
382
+ nanos = 24 * 60 * 60 * 1_000_000_000
383
+ checker(ts, nanos, "D")
py311/lib/python3.11/site-packages/pandas/tests/scalar/timestamp/methods/test_timestamp_method.py ADDED
@@ -0,0 +1,31 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # NB: This is for the Timestamp.timestamp *method* specifically, not
2
+ # the Timestamp class in general.
3
+
4
+ from pytz import utc
5
+
6
+ from pandas._libs.tslibs import Timestamp
7
+ import pandas.util._test_decorators as td
8
+
9
+ import pandas._testing as tm
10
+
11
+
12
+ class TestTimestampMethod:
13
+ @td.skip_if_windows
14
+ def test_timestamp(self, fixed_now_ts):
15
+ # GH#17329
16
+ # tz-naive --> treat it as if it were UTC for purposes of timestamp()
17
+ ts = fixed_now_ts
18
+ uts = ts.replace(tzinfo=utc)
19
+ assert ts.timestamp() == uts.timestamp()
20
+
21
+ tsc = Timestamp("2014-10-11 11:00:01.12345678", tz="US/Central")
22
+ utsc = tsc.tz_convert("UTC")
23
+
24
+ # utsc is a different representation of the same time
25
+ assert tsc.timestamp() == utsc.timestamp()
26
+
27
+ # datetime.timestamp() converts in the local timezone
28
+ with tm.set_timezone("UTC"):
29
+ # should agree with datetime.timestamp method
30
+ dt = ts.to_pydatetime()
31
+ assert dt.timestamp() == ts.timestamp()
py311/lib/python3.11/site-packages/pandas/tests/scalar/timestamp/methods/test_to_julian_date.py ADDED
@@ -0,0 +1,28 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from pandas import Timestamp
2
+
3
+
4
+ class TestTimestampToJulianDate:
5
+ def test_compare_1700(self):
6
+ ts = Timestamp("1700-06-23")
7
+ res = ts.to_julian_date()
8
+ assert res == 2_342_145.5
9
+
10
+ def test_compare_2000(self):
11
+ ts = Timestamp("2000-04-12")
12
+ res = ts.to_julian_date()
13
+ assert res == 2_451_646.5
14
+
15
+ def test_compare_2100(self):
16
+ ts = Timestamp("2100-08-12")
17
+ res = ts.to_julian_date()
18
+ assert res == 2_488_292.5
19
+
20
+ def test_compare_hour01(self):
21
+ ts = Timestamp("2000-08-12T01:00:00")
22
+ res = ts.to_julian_date()
23
+ assert res == 2_451_768.5416666666666666
24
+
25
+ def test_compare_hour13(self):
26
+ ts = Timestamp("2000-08-12T13:00:00")
27
+ res = ts.to_julian_date()
28
+ assert res == 2_451_769.0416666666666666
py311/lib/python3.11/site-packages/pandas/tests/scalar/timestamp/methods/test_to_pydatetime.py ADDED
@@ -0,0 +1,81 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from datetime import (
2
+ datetime,
3
+ timedelta,
4
+ )
5
+
6
+ import pytz
7
+
8
+ from pandas._libs.tslibs.timezones import dateutil_gettz as gettz
9
+ import pandas.util._test_decorators as td
10
+
11
+ from pandas import Timestamp
12
+ import pandas._testing as tm
13
+
14
+
15
+ class TestTimestampToPyDatetime:
16
+ def test_to_pydatetime_fold(self):
17
+ # GH#45087
18
+ tzstr = "dateutil/usr/share/zoneinfo/America/Chicago"
19
+ ts = Timestamp(year=2013, month=11, day=3, hour=1, minute=0, fold=1, tz=tzstr)
20
+ dt = ts.to_pydatetime()
21
+ assert dt.fold == 1
22
+
23
+ def test_to_pydatetime_nonzero_nano(self):
24
+ ts = Timestamp("2011-01-01 9:00:00.123456789")
25
+
26
+ # Warn the user of data loss (nanoseconds).
27
+ with tm.assert_produces_warning(UserWarning):
28
+ expected = datetime(2011, 1, 1, 9, 0, 0, 123456)
29
+ result = ts.to_pydatetime()
30
+ assert result == expected
31
+
32
+ def test_timestamp_to_datetime(self):
33
+ stamp = Timestamp("20090415", tz="US/Eastern")
34
+ dtval = stamp.to_pydatetime()
35
+ assert stamp == dtval
36
+ assert stamp.tzinfo == dtval.tzinfo
37
+
38
+ def test_timestamp_to_pydatetime_dateutil(self):
39
+ stamp = Timestamp("20090415", tz="dateutil/US/Eastern")
40
+ dtval = stamp.to_pydatetime()
41
+ assert stamp == dtval
42
+ assert stamp.tzinfo == dtval.tzinfo
43
+
44
+ def test_timestamp_to_pydatetime_explicit_pytz(self):
45
+ stamp = Timestamp("20090415", tz=pytz.timezone("US/Eastern"))
46
+ dtval = stamp.to_pydatetime()
47
+ assert stamp == dtval
48
+ assert stamp.tzinfo == dtval.tzinfo
49
+
50
+ @td.skip_if_windows
51
+ def test_timestamp_to_pydatetime_explicit_dateutil(self):
52
+ stamp = Timestamp("20090415", tz=gettz("US/Eastern"))
53
+ dtval = stamp.to_pydatetime()
54
+ assert stamp == dtval
55
+ assert stamp.tzinfo == dtval.tzinfo
56
+
57
+ def test_to_pydatetime_bijective(self):
58
+ # Ensure that converting to datetime and back only loses precision
59
+ # by going from nanoseconds to microseconds.
60
+ exp_warning = None if Timestamp.max.nanosecond == 0 else UserWarning
61
+ with tm.assert_produces_warning(exp_warning):
62
+ pydt_max = Timestamp.max.to_pydatetime()
63
+
64
+ assert (
65
+ Timestamp(pydt_max).as_unit("ns")._value / 1000
66
+ == Timestamp.max._value / 1000
67
+ )
68
+
69
+ exp_warning = None if Timestamp.min.nanosecond == 0 else UserWarning
70
+ with tm.assert_produces_warning(exp_warning):
71
+ pydt_min = Timestamp.min.to_pydatetime()
72
+
73
+ # The next assertion can be enabled once GH#39221 is merged
74
+ # assert pydt_min < Timestamp.min # this is bc nanos are dropped
75
+ tdus = timedelta(microseconds=1)
76
+ assert pydt_min + tdus > Timestamp.min
77
+
78
+ assert (
79
+ Timestamp(pydt_min + tdus).as_unit("ns")._value / 1000
80
+ == Timestamp.min._value / 1000
81
+ )
py311/lib/python3.11/site-packages/pandas/tests/scalar/timestamp/methods/test_tz_convert.py ADDED
@@ -0,0 +1,51 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import dateutil
2
+ import pytest
3
+
4
+ from pandas._libs.tslibs import timezones
5
+ import pandas.util._test_decorators as td
6
+
7
+ from pandas import Timestamp
8
+
9
+
10
+ class TestTimestampTZConvert:
11
+ @pytest.mark.parametrize("tzstr", ["US/Eastern", "dateutil/US/Eastern"])
12
+ def test_astimezone(self, tzstr):
13
+ # astimezone is an alias for tz_convert, so keep it with
14
+ # the tz_convert tests
15
+ utcdate = Timestamp("3/11/2012 22:00", tz="UTC")
16
+ expected = utcdate.tz_convert(tzstr)
17
+ result = utcdate.astimezone(tzstr)
18
+ assert expected == result
19
+ assert isinstance(result, Timestamp)
20
+
21
+ @pytest.mark.parametrize(
22
+ "stamp",
23
+ [
24
+ "2014-02-01 09:00",
25
+ "2014-07-08 09:00",
26
+ "2014-11-01 17:00",
27
+ "2014-11-05 00:00",
28
+ ],
29
+ )
30
+ def test_tz_convert_roundtrip(self, stamp, tz_aware_fixture):
31
+ tz = tz_aware_fixture
32
+
33
+ ts = Timestamp(stamp, tz="UTC")
34
+ converted = ts.tz_convert(tz)
35
+
36
+ reset = converted.tz_convert(None)
37
+ assert reset == Timestamp(stamp)
38
+ assert reset.tzinfo is None
39
+ assert reset == converted.tz_convert("UTC").tz_localize(None)
40
+
41
+ @td.skip_if_windows
42
+ def test_tz_convert_utc_with_system_utc(self):
43
+ # from system utc to real utc
44
+ ts = Timestamp("2001-01-05 11:56", tz=timezones.maybe_get_tz("dateutil/UTC"))
45
+ # check that the time hasn't changed.
46
+ assert ts == ts.tz_convert(dateutil.tz.tzutc())
47
+
48
+ # from system utc to real utc
49
+ ts = Timestamp("2001-01-05 11:56", tz=timezones.maybe_get_tz("dateutil/UTC"))
50
+ # check that the time hasn't changed.
51
+ assert ts == ts.tz_convert(dateutil.tz.tzutc())
py311/lib/python3.11/site-packages/pandas/tests/scalar/timestamp/methods/test_tz_localize.py ADDED
@@ -0,0 +1,351 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from datetime import timedelta
2
+ import re
3
+
4
+ from dateutil.tz import gettz
5
+ import pytest
6
+ import pytz
7
+ from pytz.exceptions import (
8
+ AmbiguousTimeError,
9
+ NonExistentTimeError,
10
+ )
11
+
12
+ from pandas._libs.tslibs.dtypes import NpyDatetimeUnit
13
+ from pandas.errors import OutOfBoundsDatetime
14
+
15
+ from pandas import (
16
+ NaT,
17
+ Timestamp,
18
+ )
19
+
20
+ try:
21
+ from zoneinfo import ZoneInfo
22
+ except ImportError:
23
+ # Cannot assign to a type
24
+ ZoneInfo = None # type: ignore[misc, assignment]
25
+
26
+
27
+ class TestTimestampTZLocalize:
28
+ @pytest.mark.skip_ubsan
29
+ def test_tz_localize_pushes_out_of_bounds(self):
30
+ # GH#12677
31
+ # tz_localize that pushes away from the boundary is OK
32
+ msg = (
33
+ f"Converting {Timestamp.min.strftime('%Y-%m-%d %H:%M:%S')} "
34
+ f"underflows past {Timestamp.min}"
35
+ )
36
+ pac = Timestamp.min.tz_localize("US/Pacific")
37
+ assert pac._value > Timestamp.min._value
38
+ pac.tz_convert("Asia/Tokyo") # tz_convert doesn't change value
39
+ with pytest.raises(OutOfBoundsDatetime, match=msg):
40
+ Timestamp.min.tz_localize("Asia/Tokyo")
41
+
42
+ # tz_localize that pushes away from the boundary is OK
43
+ msg = (
44
+ f"Converting {Timestamp.max.strftime('%Y-%m-%d %H:%M:%S')} "
45
+ f"overflows past {Timestamp.max}"
46
+ )
47
+ tokyo = Timestamp.max.tz_localize("Asia/Tokyo")
48
+ assert tokyo._value < Timestamp.max._value
49
+ tokyo.tz_convert("US/Pacific") # tz_convert doesn't change value
50
+ with pytest.raises(OutOfBoundsDatetime, match=msg):
51
+ Timestamp.max.tz_localize("US/Pacific")
52
+
53
+ @pytest.mark.parametrize("unit", ["ns", "us", "ms", "s"])
54
+ def test_tz_localize_ambiguous_bool(self, unit):
55
+ # make sure that we are correctly accepting bool values as ambiguous
56
+ # GH#14402
57
+ ts = Timestamp("2015-11-01 01:00:03").as_unit(unit)
58
+ expected0 = Timestamp("2015-11-01 01:00:03-0500", tz="US/Central")
59
+ expected1 = Timestamp("2015-11-01 01:00:03-0600", tz="US/Central")
60
+
61
+ msg = "Cannot infer dst time from 2015-11-01 01:00:03"
62
+ with pytest.raises(pytz.AmbiguousTimeError, match=msg):
63
+ ts.tz_localize("US/Central")
64
+
65
+ with pytest.raises(pytz.AmbiguousTimeError, match=msg):
66
+ ts.tz_localize("dateutil/US/Central")
67
+
68
+ if ZoneInfo is not None:
69
+ try:
70
+ tz = ZoneInfo("US/Central")
71
+ except KeyError:
72
+ # no tzdata
73
+ pass
74
+ else:
75
+ with pytest.raises(pytz.AmbiguousTimeError, match=msg):
76
+ ts.tz_localize(tz)
77
+
78
+ result = ts.tz_localize("US/Central", ambiguous=True)
79
+ assert result == expected0
80
+ assert result._creso == getattr(NpyDatetimeUnit, f"NPY_FR_{unit}").value
81
+
82
+ result = ts.tz_localize("US/Central", ambiguous=False)
83
+ assert result == expected1
84
+ assert result._creso == getattr(NpyDatetimeUnit, f"NPY_FR_{unit}").value
85
+
86
+ def test_tz_localize_ambiguous(self):
87
+ ts = Timestamp("2014-11-02 01:00")
88
+ ts_dst = ts.tz_localize("US/Eastern", ambiguous=True)
89
+ ts_no_dst = ts.tz_localize("US/Eastern", ambiguous=False)
90
+
91
+ assert ts_no_dst._value - ts_dst._value == 3600
92
+ msg = re.escape(
93
+ "'ambiguous' parameter must be one of: "
94
+ "True, False, 'NaT', 'raise' (default)"
95
+ )
96
+ with pytest.raises(ValueError, match=msg):
97
+ ts.tz_localize("US/Eastern", ambiguous="infer")
98
+
99
+ # GH#8025
100
+ msg = "Cannot localize tz-aware Timestamp, use tz_convert for conversions"
101
+ with pytest.raises(TypeError, match=msg):
102
+ Timestamp("2011-01-01", tz="US/Eastern").tz_localize("Asia/Tokyo")
103
+
104
+ msg = "Cannot convert tz-naive Timestamp, use tz_localize to localize"
105
+ with pytest.raises(TypeError, match=msg):
106
+ Timestamp("2011-01-01").tz_convert("Asia/Tokyo")
107
+
108
+ @pytest.mark.parametrize(
109
+ "stamp, tz",
110
+ [
111
+ ("2015-03-08 02:00", "US/Eastern"),
112
+ ("2015-03-08 02:30", "US/Pacific"),
113
+ ("2015-03-29 02:00", "Europe/Paris"),
114
+ ("2015-03-29 02:30", "Europe/Belgrade"),
115
+ ],
116
+ )
117
+ def test_tz_localize_nonexistent(self, stamp, tz):
118
+ # GH#13057
119
+ ts = Timestamp(stamp)
120
+ with pytest.raises(NonExistentTimeError, match=stamp):
121
+ ts.tz_localize(tz)
122
+ # GH 22644
123
+ with pytest.raises(NonExistentTimeError, match=stamp):
124
+ ts.tz_localize(tz, nonexistent="raise")
125
+ assert ts.tz_localize(tz, nonexistent="NaT") is NaT
126
+
127
+ @pytest.mark.parametrize(
128
+ "stamp, tz, forward_expected, backward_expected",
129
+ [
130
+ (
131
+ "2015-03-29 02:00:00",
132
+ "Europe/Warsaw",
133
+ "2015-03-29 03:00:00",
134
+ "2015-03-29 01:59:59",
135
+ ), # utc+1 -> utc+2
136
+ (
137
+ "2023-03-12 02:00:00",
138
+ "America/Los_Angeles",
139
+ "2023-03-12 03:00:00",
140
+ "2023-03-12 01:59:59",
141
+ ), # utc-8 -> utc-7
142
+ (
143
+ "2023-03-26 01:00:00",
144
+ "Europe/London",
145
+ "2023-03-26 02:00:00",
146
+ "2023-03-26 00:59:59",
147
+ ), # utc+0 -> utc+1
148
+ (
149
+ "2023-03-26 00:00:00",
150
+ "Atlantic/Azores",
151
+ "2023-03-26 01:00:00",
152
+ "2023-03-25 23:59:59",
153
+ ), # utc-1 -> utc+0
154
+ ],
155
+ )
156
+ def test_tz_localize_nonexistent_shift(
157
+ self, stamp, tz, forward_expected, backward_expected
158
+ ):
159
+ ts = Timestamp(stamp)
160
+ forward_ts = ts.tz_localize(tz, nonexistent="shift_forward")
161
+ assert forward_ts == Timestamp(forward_expected, tz=tz)
162
+ backward_ts = ts.tz_localize(tz, nonexistent="shift_backward")
163
+ assert backward_ts == Timestamp(backward_expected, tz=tz)
164
+
165
+ def test_tz_localize_ambiguous_raise(self):
166
+ # GH#13057
167
+ ts = Timestamp("2015-11-1 01:00")
168
+ msg = "Cannot infer dst time from 2015-11-01 01:00:00,"
169
+ with pytest.raises(AmbiguousTimeError, match=msg):
170
+ ts.tz_localize("US/Pacific", ambiguous="raise")
171
+
172
+ def test_tz_localize_nonexistent_invalid_arg(self, warsaw):
173
+ # GH 22644
174
+ tz = warsaw
175
+ ts = Timestamp("2015-03-29 02:00:00")
176
+ msg = (
177
+ "The nonexistent argument must be one of 'raise', 'NaT', "
178
+ "'shift_forward', 'shift_backward' or a timedelta object"
179
+ )
180
+ with pytest.raises(ValueError, match=msg):
181
+ ts.tz_localize(tz, nonexistent="foo")
182
+
183
+ @pytest.mark.parametrize(
184
+ "stamp",
185
+ [
186
+ "2014-02-01 09:00",
187
+ "2014-07-08 09:00",
188
+ "2014-11-01 17:00",
189
+ "2014-11-05 00:00",
190
+ ],
191
+ )
192
+ def test_tz_localize_roundtrip(self, stamp, tz_aware_fixture):
193
+ tz = tz_aware_fixture
194
+ ts = Timestamp(stamp)
195
+ localized = ts.tz_localize(tz)
196
+ assert localized == Timestamp(stamp, tz=tz)
197
+
198
+ msg = "Cannot localize tz-aware Timestamp"
199
+ with pytest.raises(TypeError, match=msg):
200
+ localized.tz_localize(tz)
201
+
202
+ reset = localized.tz_localize(None)
203
+ assert reset == ts
204
+ assert reset.tzinfo is None
205
+
206
+ def test_tz_localize_ambiguous_compat(self):
207
+ # validate that pytz and dateutil are compat for dst
208
+ # when the transition happens
209
+ naive = Timestamp("2013-10-27 01:00:00")
210
+
211
+ pytz_zone = "Europe/London"
212
+ dateutil_zone = "dateutil/Europe/London"
213
+ result_pytz = naive.tz_localize(pytz_zone, ambiguous=False)
214
+ result_dateutil = naive.tz_localize(dateutil_zone, ambiguous=False)
215
+ assert result_pytz._value == result_dateutil._value
216
+ assert result_pytz._value == 1382835600
217
+
218
+ # fixed ambiguous behavior
219
+ # see gh-14621, GH#45087
220
+ assert result_pytz.to_pydatetime().tzname() == "GMT"
221
+ assert result_dateutil.to_pydatetime().tzname() == "GMT"
222
+ assert str(result_pytz) == str(result_dateutil)
223
+
224
+ # 1 hour difference
225
+ result_pytz = naive.tz_localize(pytz_zone, ambiguous=True)
226
+ result_dateutil = naive.tz_localize(dateutil_zone, ambiguous=True)
227
+ assert result_pytz._value == result_dateutil._value
228
+ assert result_pytz._value == 1382832000
229
+
230
+ # see gh-14621
231
+ assert str(result_pytz) == str(result_dateutil)
232
+ assert (
233
+ result_pytz.to_pydatetime().tzname()
234
+ == result_dateutil.to_pydatetime().tzname()
235
+ )
236
+
237
+ @pytest.mark.parametrize(
238
+ "tz",
239
+ [
240
+ pytz.timezone("US/Eastern"),
241
+ gettz("US/Eastern"),
242
+ "US/Eastern",
243
+ "dateutil/US/Eastern",
244
+ ],
245
+ )
246
+ def test_timestamp_tz_localize(self, tz):
247
+ stamp = Timestamp("3/11/2012 04:00")
248
+
249
+ result = stamp.tz_localize(tz)
250
+ expected = Timestamp("3/11/2012 04:00", tz=tz)
251
+ assert result.hour == expected.hour
252
+ assert result == expected
253
+
254
+ @pytest.mark.parametrize(
255
+ "start_ts, tz, end_ts, shift",
256
+ [
257
+ ["2015-03-29 02:20:00", "Europe/Warsaw", "2015-03-29 03:00:00", "forward"],
258
+ [
259
+ "2015-03-29 02:20:00",
260
+ "Europe/Warsaw",
261
+ "2015-03-29 01:59:59.999999999",
262
+ "backward",
263
+ ],
264
+ [
265
+ "2015-03-29 02:20:00",
266
+ "Europe/Warsaw",
267
+ "2015-03-29 03:20:00",
268
+ timedelta(hours=1),
269
+ ],
270
+ [
271
+ "2015-03-29 02:20:00",
272
+ "Europe/Warsaw",
273
+ "2015-03-29 01:20:00",
274
+ timedelta(hours=-1),
275
+ ],
276
+ ["2018-03-11 02:33:00", "US/Pacific", "2018-03-11 03:00:00", "forward"],
277
+ [
278
+ "2018-03-11 02:33:00",
279
+ "US/Pacific",
280
+ "2018-03-11 01:59:59.999999999",
281
+ "backward",
282
+ ],
283
+ [
284
+ "2018-03-11 02:33:00",
285
+ "US/Pacific",
286
+ "2018-03-11 03:33:00",
287
+ timedelta(hours=1),
288
+ ],
289
+ [
290
+ "2018-03-11 02:33:00",
291
+ "US/Pacific",
292
+ "2018-03-11 01:33:00",
293
+ timedelta(hours=-1),
294
+ ],
295
+ ],
296
+ )
297
+ @pytest.mark.parametrize("tz_type", ["", "dateutil/"])
298
+ @pytest.mark.parametrize("unit", ["ns", "us", "ms", "s"])
299
+ def test_timestamp_tz_localize_nonexistent_shift(
300
+ self, start_ts, tz, end_ts, shift, tz_type, unit
301
+ ):
302
+ # GH 8917, 24466
303
+ tz = tz_type + tz
304
+ if isinstance(shift, str):
305
+ shift = "shift_" + shift
306
+ ts = Timestamp(start_ts).as_unit(unit)
307
+ result = ts.tz_localize(tz, nonexistent=shift)
308
+ expected = Timestamp(end_ts).tz_localize(tz)
309
+
310
+ if unit == "us":
311
+ assert result == expected.replace(nanosecond=0)
312
+ elif unit == "ms":
313
+ micros = expected.microsecond - expected.microsecond % 1000
314
+ assert result == expected.replace(microsecond=micros, nanosecond=0)
315
+ elif unit == "s":
316
+ assert result == expected.replace(microsecond=0, nanosecond=0)
317
+ else:
318
+ assert result == expected
319
+ assert result._creso == getattr(NpyDatetimeUnit, f"NPY_FR_{unit}").value
320
+
321
+ @pytest.mark.parametrize("offset", [-1, 1])
322
+ def test_timestamp_tz_localize_nonexistent_shift_invalid(self, offset, warsaw):
323
+ # GH 8917, 24466
324
+ tz = warsaw
325
+ ts = Timestamp("2015-03-29 02:20:00")
326
+ msg = "The provided timedelta will relocalize on a nonexistent time"
327
+ with pytest.raises(ValueError, match=msg):
328
+ ts.tz_localize(tz, nonexistent=timedelta(seconds=offset))
329
+
330
+ @pytest.mark.parametrize("unit", ["ns", "us", "ms", "s"])
331
+ def test_timestamp_tz_localize_nonexistent_NaT(self, warsaw, unit):
332
+ # GH 8917
333
+ tz = warsaw
334
+ ts = Timestamp("2015-03-29 02:20:00").as_unit(unit)
335
+ result = ts.tz_localize(tz, nonexistent="NaT")
336
+ assert result is NaT
337
+
338
+ @pytest.mark.parametrize("unit", ["ns", "us", "ms", "s"])
339
+ def test_timestamp_tz_localize_nonexistent_raise(self, warsaw, unit):
340
+ # GH 8917
341
+ tz = warsaw
342
+ ts = Timestamp("2015-03-29 02:20:00").as_unit(unit)
343
+ msg = "2015-03-29 02:20:00"
344
+ with pytest.raises(pytz.NonExistentTimeError, match=msg):
345
+ ts.tz_localize(tz, nonexistent="raise")
346
+ msg = (
347
+ "The nonexistent argument must be one of 'raise', 'NaT', "
348
+ "'shift_forward', 'shift_backward' or a timedelta object"
349
+ )
350
+ with pytest.raises(ValueError, match=msg):
351
+ ts.tz_localize(tz, nonexistent="foo")
py311/lib/python3.11/site-packages/pandas/tests/scalar/timestamp/test_arithmetic.py ADDED
@@ -0,0 +1,334 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from datetime import (
2
+ datetime,
3
+ timedelta,
4
+ timezone,
5
+ )
6
+
7
+ from dateutil.tz import gettz
8
+ import numpy as np
9
+ import pytest
10
+ import pytz
11
+
12
+ from pandas._libs.tslibs import (
13
+ OutOfBoundsDatetime,
14
+ OutOfBoundsTimedelta,
15
+ Timedelta,
16
+ Timestamp,
17
+ offsets,
18
+ to_offset,
19
+ )
20
+
21
+ import pandas._testing as tm
22
+
23
+
24
+ class TestTimestampArithmetic:
25
+ def test_overflow_offset(self):
26
+ # no overflow expected
27
+
28
+ stamp = Timestamp("2000/1/1")
29
+ offset_no_overflow = to_offset("D") * 100
30
+
31
+ expected = Timestamp("2000/04/10")
32
+ assert stamp + offset_no_overflow == expected
33
+
34
+ assert offset_no_overflow + stamp == expected
35
+
36
+ expected = Timestamp("1999/09/23")
37
+ assert stamp - offset_no_overflow == expected
38
+
39
+ def test_overflow_offset_raises(self):
40
+ # xref https://github.com/statsmodels/statsmodels/issues/3374
41
+ # ends up multiplying really large numbers which overflow
42
+
43
+ stamp = Timestamp("2017-01-13 00:00:00").as_unit("ns")
44
+ offset_overflow = 20169940 * offsets.Day(1)
45
+ lmsg2 = r"Cannot cast -?20169940 days \+?00:00:00 to unit='ns' without overflow"
46
+
47
+ with pytest.raises(OutOfBoundsTimedelta, match=lmsg2):
48
+ stamp + offset_overflow
49
+
50
+ with pytest.raises(OutOfBoundsTimedelta, match=lmsg2):
51
+ offset_overflow + stamp
52
+
53
+ with pytest.raises(OutOfBoundsTimedelta, match=lmsg2):
54
+ stamp - offset_overflow
55
+
56
+ # xref https://github.com/pandas-dev/pandas/issues/14080
57
+ # used to crash, so check for proper overflow exception
58
+
59
+ stamp = Timestamp("2000/1/1").as_unit("ns")
60
+ offset_overflow = to_offset("D") * 100**5
61
+
62
+ lmsg3 = (
63
+ r"Cannot cast -?10000000000 days \+?00:00:00 to unit='ns' without overflow"
64
+ )
65
+ with pytest.raises(OutOfBoundsTimedelta, match=lmsg3):
66
+ stamp + offset_overflow
67
+
68
+ with pytest.raises(OutOfBoundsTimedelta, match=lmsg3):
69
+ offset_overflow + stamp
70
+
71
+ with pytest.raises(OutOfBoundsTimedelta, match=lmsg3):
72
+ stamp - offset_overflow
73
+
74
+ def test_overflow_timestamp_raises(self):
75
+ # https://github.com/pandas-dev/pandas/issues/31774
76
+ msg = "Result is too large"
77
+ a = Timestamp("2101-01-01 00:00:00").as_unit("ns")
78
+ b = Timestamp("1688-01-01 00:00:00").as_unit("ns")
79
+
80
+ with pytest.raises(OutOfBoundsDatetime, match=msg):
81
+ a - b
82
+
83
+ # but we're OK for timestamp and datetime.datetime
84
+ assert (a - b.to_pydatetime()) == (a.to_pydatetime() - b)
85
+
86
+ def test_delta_preserve_nanos(self):
87
+ val = Timestamp(1337299200000000123)
88
+ result = val + timedelta(1)
89
+ assert result.nanosecond == val.nanosecond
90
+
91
+ def test_rsub_dtscalars(self, tz_naive_fixture):
92
+ # In particular, check that datetime64 - Timestamp works GH#28286
93
+ td = Timedelta(1235345642000)
94
+ ts = Timestamp("2021-01-01", tz=tz_naive_fixture)
95
+ other = ts + td
96
+
97
+ assert other - ts == td
98
+ assert other.to_pydatetime() - ts == td
99
+ if tz_naive_fixture is None:
100
+ assert other.to_datetime64() - ts == td
101
+ else:
102
+ msg = "Cannot subtract tz-naive and tz-aware datetime-like objects"
103
+ with pytest.raises(TypeError, match=msg):
104
+ other.to_datetime64() - ts
105
+
106
+ def test_timestamp_sub_datetime(self):
107
+ dt = datetime(2013, 10, 12)
108
+ ts = Timestamp(datetime(2013, 10, 13))
109
+ assert (ts - dt).days == 1
110
+ assert (dt - ts).days == -1
111
+
112
+ def test_subtract_tzaware_datetime(self):
113
+ t1 = Timestamp("2020-10-22T22:00:00+00:00")
114
+ t2 = datetime(2020, 10, 22, 22, tzinfo=timezone.utc)
115
+
116
+ result = t1 - t2
117
+
118
+ assert isinstance(result, Timedelta)
119
+ assert result == Timedelta("0 days")
120
+
121
+ def test_subtract_timestamp_from_different_timezone(self):
122
+ t1 = Timestamp("20130101").tz_localize("US/Eastern")
123
+ t2 = Timestamp("20130101").tz_localize("CET")
124
+
125
+ result = t1 - t2
126
+
127
+ assert isinstance(result, Timedelta)
128
+ assert result == Timedelta("0 days 06:00:00")
129
+
130
+ def test_subtracting_involving_datetime_with_different_tz(self):
131
+ t1 = datetime(2013, 1, 1, tzinfo=timezone(timedelta(hours=-5)))
132
+ t2 = Timestamp("20130101").tz_localize("CET")
133
+
134
+ result = t1 - t2
135
+
136
+ assert isinstance(result, Timedelta)
137
+ assert result == Timedelta("0 days 06:00:00")
138
+
139
+ result = t2 - t1
140
+ assert isinstance(result, Timedelta)
141
+ assert result == Timedelta("-1 days +18:00:00")
142
+
143
+ def test_subtracting_different_timezones(self, tz_aware_fixture):
144
+ t_raw = Timestamp("20130101")
145
+ t_UTC = t_raw.tz_localize("UTC")
146
+ t_diff = t_UTC.tz_convert(tz_aware_fixture) + Timedelta("0 days 05:00:00")
147
+
148
+ result = t_diff - t_UTC
149
+
150
+ assert isinstance(result, Timedelta)
151
+ assert result == Timedelta("0 days 05:00:00")
152
+
153
+ def test_addition_subtraction_types(self):
154
+ # Assert on the types resulting from Timestamp +/- various date/time
155
+ # objects
156
+ dt = datetime(2014, 3, 4)
157
+ td = timedelta(seconds=1)
158
+ ts = Timestamp(dt)
159
+
160
+ msg = "Addition/subtraction of integers"
161
+ with pytest.raises(TypeError, match=msg):
162
+ # GH#22535 add/sub with integers is deprecated
163
+ ts + 1
164
+ with pytest.raises(TypeError, match=msg):
165
+ ts - 1
166
+
167
+ # Timestamp + datetime not supported, though subtraction is supported
168
+ # and yields timedelta more tests in tseries/base/tests/test_base.py
169
+ assert type(ts - dt) == Timedelta
170
+ assert type(ts + td) == Timestamp
171
+ assert type(ts - td) == Timestamp
172
+
173
+ # Timestamp +/- datetime64 not supported, so not tested (could possibly
174
+ # assert error raised?)
175
+ td64 = np.timedelta64(1, "D")
176
+ assert type(ts + td64) == Timestamp
177
+ assert type(ts - td64) == Timestamp
178
+
179
+ @pytest.mark.parametrize(
180
+ "td", [Timedelta(hours=3), np.timedelta64(3, "h"), timedelta(hours=3)]
181
+ )
182
+ def test_radd_tdscalar(self, td, fixed_now_ts):
183
+ # GH#24775 timedelta64+Timestamp should not raise
184
+ ts = fixed_now_ts
185
+ assert td + ts == ts + td
186
+
187
+ @pytest.mark.parametrize(
188
+ "other,expected_difference",
189
+ [
190
+ (np.timedelta64(-123, "ns"), -123),
191
+ (np.timedelta64(1234567898, "ns"), 1234567898),
192
+ (np.timedelta64(-123, "us"), -123000),
193
+ (np.timedelta64(-123, "ms"), -123000000),
194
+ ],
195
+ )
196
+ def test_timestamp_add_timedelta64_unit(self, other, expected_difference):
197
+ now = datetime.now(timezone.utc)
198
+ ts = Timestamp(now).as_unit("ns")
199
+ result = ts + other
200
+ valdiff = result._value - ts._value
201
+ assert valdiff == expected_difference
202
+
203
+ ts2 = Timestamp(now)
204
+ assert ts2 + other == result
205
+
206
+ @pytest.mark.parametrize(
207
+ "ts",
208
+ [
209
+ Timestamp("1776-07-04"),
210
+ Timestamp("1776-07-04", tz="UTC"),
211
+ ],
212
+ )
213
+ @pytest.mark.parametrize(
214
+ "other",
215
+ [
216
+ 1,
217
+ np.int64(1),
218
+ np.array([1, 2], dtype=np.int32),
219
+ np.array([3, 4], dtype=np.uint64),
220
+ ],
221
+ )
222
+ def test_add_int_with_freq(self, ts, other):
223
+ msg = "Addition/subtraction of integers and integer-arrays"
224
+ with pytest.raises(TypeError, match=msg):
225
+ ts + other
226
+ with pytest.raises(TypeError, match=msg):
227
+ other + ts
228
+
229
+ with pytest.raises(TypeError, match=msg):
230
+ ts - other
231
+
232
+ msg = "unsupported operand type"
233
+ with pytest.raises(TypeError, match=msg):
234
+ other - ts
235
+
236
+ @pytest.mark.parametrize("shape", [(6,), (2, 3)])
237
+ def test_addsub_m8ndarray(self, shape):
238
+ # GH#33296
239
+ ts = Timestamp("2020-04-04 15:45").as_unit("ns")
240
+ other = np.arange(6).astype("m8[h]").reshape(shape)
241
+
242
+ result = ts + other
243
+
244
+ ex_stamps = [ts + Timedelta(hours=n) for n in range(6)]
245
+ expected = np.array([x.asm8 for x in ex_stamps], dtype="M8[ns]").reshape(shape)
246
+ tm.assert_numpy_array_equal(result, expected)
247
+
248
+ result = other + ts
249
+ tm.assert_numpy_array_equal(result, expected)
250
+
251
+ result = ts - other
252
+ ex_stamps = [ts - Timedelta(hours=n) for n in range(6)]
253
+ expected = np.array([x.asm8 for x in ex_stamps], dtype="M8[ns]").reshape(shape)
254
+ tm.assert_numpy_array_equal(result, expected)
255
+
256
+ msg = r"unsupported operand type\(s\) for -: 'numpy.ndarray' and 'Timestamp'"
257
+ with pytest.raises(TypeError, match=msg):
258
+ other - ts
259
+
260
+ @pytest.mark.parametrize("shape", [(6,), (2, 3)])
261
+ def test_addsub_m8ndarray_tzaware(self, shape):
262
+ # GH#33296
263
+ ts = Timestamp("2020-04-04 15:45", tz="US/Pacific")
264
+
265
+ other = np.arange(6).astype("m8[h]").reshape(shape)
266
+
267
+ result = ts + other
268
+
269
+ ex_stamps = [ts + Timedelta(hours=n) for n in range(6)]
270
+ expected = np.array(ex_stamps).reshape(shape)
271
+ tm.assert_numpy_array_equal(result, expected)
272
+
273
+ result = other + ts
274
+ tm.assert_numpy_array_equal(result, expected)
275
+
276
+ result = ts - other
277
+ ex_stamps = [ts - Timedelta(hours=n) for n in range(6)]
278
+ expected = np.array(ex_stamps).reshape(shape)
279
+ tm.assert_numpy_array_equal(result, expected)
280
+
281
+ msg = r"unsupported operand type\(s\) for -: 'numpy.ndarray' and 'Timestamp'"
282
+ with pytest.raises(TypeError, match=msg):
283
+ other - ts
284
+
285
+ def test_subtract_different_utc_objects(self, utc_fixture, utc_fixture2):
286
+ # GH 32619
287
+ dt = datetime(2021, 1, 1)
288
+ ts1 = Timestamp(dt, tz=utc_fixture)
289
+ ts2 = Timestamp(dt, tz=utc_fixture2)
290
+ result = ts1 - ts2
291
+ expected = Timedelta(0)
292
+ assert result == expected
293
+
294
+ @pytest.mark.parametrize(
295
+ "tz",
296
+ [
297
+ pytz.timezone("US/Eastern"),
298
+ gettz("US/Eastern"),
299
+ "US/Eastern",
300
+ "dateutil/US/Eastern",
301
+ ],
302
+ )
303
+ def test_timestamp_add_timedelta_push_over_dst_boundary(self, tz):
304
+ # GH#1389
305
+
306
+ # 4 hours before DST transition
307
+ stamp = Timestamp("3/10/2012 22:00", tz=tz)
308
+
309
+ result = stamp + timedelta(hours=6)
310
+
311
+ # spring forward, + "7" hours
312
+ expected = Timestamp("3/11/2012 05:00", tz=tz)
313
+
314
+ assert result == expected
315
+
316
+
317
+ class SubDatetime(datetime):
318
+ pass
319
+
320
+
321
+ @pytest.mark.parametrize(
322
+ "lh,rh",
323
+ [
324
+ (SubDatetime(2000, 1, 1), Timedelta(hours=1)),
325
+ (Timedelta(hours=1), SubDatetime(2000, 1, 1)),
326
+ ],
327
+ )
328
+ def test_dt_subclass_add_timedelta(lh, rh):
329
+ # GH#25851
330
+ # ensure that subclassed datetime works for
331
+ # Timedelta operations
332
+ result = lh + rh
333
+ expected = SubDatetime(2000, 1, 1, 1)
334
+ assert result == expected
py311/lib/python3.11/site-packages/pandas/tests/scalar/timestamp/test_comparisons.py ADDED
@@ -0,0 +1,313 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from datetime import (
2
+ datetime,
3
+ timedelta,
4
+ )
5
+ import operator
6
+
7
+ import numpy as np
8
+ import pytest
9
+
10
+ from pandas import Timestamp
11
+ import pandas._testing as tm
12
+
13
+
14
+ class TestTimestampComparison:
15
+ def test_compare_non_nano_dt64(self):
16
+ # don't raise when converting dt64 to Timestamp in __richcmp__
17
+ dt = np.datetime64("1066-10-14")
18
+ ts = Timestamp(dt)
19
+
20
+ assert dt == ts
21
+
22
+ def test_comparison_dt64_ndarray(self):
23
+ ts = Timestamp("2021-01-01")
24
+ ts2 = Timestamp("2019-04-05")
25
+ arr = np.array([[ts.asm8, ts2.asm8]], dtype="M8[ns]")
26
+
27
+ result = ts == arr
28
+ expected = np.array([[True, False]], dtype=bool)
29
+ tm.assert_numpy_array_equal(result, expected)
30
+
31
+ result = arr == ts
32
+ tm.assert_numpy_array_equal(result, expected)
33
+
34
+ result = ts != arr
35
+ tm.assert_numpy_array_equal(result, ~expected)
36
+
37
+ result = arr != ts
38
+ tm.assert_numpy_array_equal(result, ~expected)
39
+
40
+ result = ts2 < arr
41
+ tm.assert_numpy_array_equal(result, expected)
42
+
43
+ result = arr < ts2
44
+ tm.assert_numpy_array_equal(result, np.array([[False, False]], dtype=bool))
45
+
46
+ result = ts2 <= arr
47
+ tm.assert_numpy_array_equal(result, np.array([[True, True]], dtype=bool))
48
+
49
+ result = arr <= ts2
50
+ tm.assert_numpy_array_equal(result, ~expected)
51
+
52
+ result = ts >= arr
53
+ tm.assert_numpy_array_equal(result, np.array([[True, True]], dtype=bool))
54
+
55
+ result = arr >= ts
56
+ tm.assert_numpy_array_equal(result, np.array([[True, False]], dtype=bool))
57
+
58
+ @pytest.mark.parametrize("reverse", [True, False])
59
+ def test_comparison_dt64_ndarray_tzaware(self, reverse, comparison_op):
60
+ ts = Timestamp("2021-01-01 00:00:00.00000", tz="UTC")
61
+ arr = np.array([ts.asm8, ts.asm8], dtype="M8[ns]")
62
+
63
+ left, right = ts, arr
64
+ if reverse:
65
+ left, right = arr, ts
66
+
67
+ if comparison_op is operator.eq:
68
+ expected = np.array([False, False], dtype=bool)
69
+ result = comparison_op(left, right)
70
+ tm.assert_numpy_array_equal(result, expected)
71
+ elif comparison_op is operator.ne:
72
+ expected = np.array([True, True], dtype=bool)
73
+ result = comparison_op(left, right)
74
+ tm.assert_numpy_array_equal(result, expected)
75
+ else:
76
+ msg = "Cannot compare tz-naive and tz-aware timestamps"
77
+ with pytest.raises(TypeError, match=msg):
78
+ comparison_op(left, right)
79
+
80
+ def test_comparison_object_array(self):
81
+ # GH#15183
82
+ ts = Timestamp("2011-01-03 00:00:00-0500", tz="US/Eastern")
83
+ other = Timestamp("2011-01-01 00:00:00-0500", tz="US/Eastern")
84
+ naive = Timestamp("2011-01-01 00:00:00")
85
+
86
+ arr = np.array([other, ts], dtype=object)
87
+ res = arr == ts
88
+ expected = np.array([False, True], dtype=bool)
89
+ assert (res == expected).all()
90
+
91
+ # 2D case
92
+ arr = np.array([[other, ts], [ts, other]], dtype=object)
93
+ res = arr != ts
94
+ expected = np.array([[True, False], [False, True]], dtype=bool)
95
+ assert res.shape == expected.shape
96
+ assert (res == expected).all()
97
+
98
+ # tzaware mismatch
99
+ arr = np.array([naive], dtype=object)
100
+ msg = "Cannot compare tz-naive and tz-aware timestamps"
101
+ with pytest.raises(TypeError, match=msg):
102
+ arr < ts
103
+
104
+ def test_comparison(self):
105
+ # 5-18-2012 00:00:00.000
106
+ stamp = 1337299200000000000
107
+
108
+ val = Timestamp(stamp)
109
+
110
+ assert val == val
111
+ assert not val != val
112
+ assert not val < val
113
+ assert val <= val
114
+ assert not val > val
115
+ assert val >= val
116
+
117
+ other = datetime(2012, 5, 18)
118
+ assert val == other
119
+ assert not val != other
120
+ assert not val < other
121
+ assert val <= other
122
+ assert not val > other
123
+ assert val >= other
124
+
125
+ other = Timestamp(stamp + 100)
126
+
127
+ assert val != other
128
+ assert val != other
129
+ assert val < other
130
+ assert val <= other
131
+ assert other > val
132
+ assert other >= val
133
+
134
+ def test_compare_invalid(self):
135
+ # GH#8058
136
+ val = Timestamp("20130101 12:01:02")
137
+ assert not val == "foo"
138
+ assert not val == 10.0
139
+ assert not val == 1
140
+ assert not val == []
141
+ assert not val == {"foo": 1}
142
+ assert not val == np.float64(1)
143
+ assert not val == np.int64(1)
144
+
145
+ assert val != "foo"
146
+ assert val != 10.0
147
+ assert val != 1
148
+ assert val != []
149
+ assert val != {"foo": 1}
150
+ assert val != np.float64(1)
151
+ assert val != np.int64(1)
152
+
153
+ @pytest.mark.parametrize("tz", [None, "US/Pacific"])
154
+ def test_compare_date(self, tz):
155
+ # GH#36131 comparing Timestamp with date object is deprecated
156
+ ts = Timestamp("2021-01-01 00:00:00.00000", tz=tz)
157
+ dt = ts.to_pydatetime().date()
158
+ # in 2.0 we disallow comparing pydate objects with Timestamps,
159
+ # following the stdlib datetime behavior.
160
+
161
+ msg = "Cannot compare Timestamp with datetime.date"
162
+ for left, right in [(ts, dt), (dt, ts)]:
163
+ assert not left == right
164
+ assert left != right
165
+
166
+ with pytest.raises(TypeError, match=msg):
167
+ left < right
168
+ with pytest.raises(TypeError, match=msg):
169
+ left <= right
170
+ with pytest.raises(TypeError, match=msg):
171
+ left > right
172
+ with pytest.raises(TypeError, match=msg):
173
+ left >= right
174
+
175
+ def test_cant_compare_tz_naive_w_aware(self, utc_fixture):
176
+ # see GH#1404
177
+ a = Timestamp("3/12/2012")
178
+ b = Timestamp("3/12/2012", tz=utc_fixture)
179
+
180
+ msg = "Cannot compare tz-naive and tz-aware timestamps"
181
+ assert not a == b
182
+ assert a != b
183
+ with pytest.raises(TypeError, match=msg):
184
+ a < b
185
+ with pytest.raises(TypeError, match=msg):
186
+ a <= b
187
+ with pytest.raises(TypeError, match=msg):
188
+ a > b
189
+ with pytest.raises(TypeError, match=msg):
190
+ a >= b
191
+
192
+ assert not b == a
193
+ assert b != a
194
+ with pytest.raises(TypeError, match=msg):
195
+ b < a
196
+ with pytest.raises(TypeError, match=msg):
197
+ b <= a
198
+ with pytest.raises(TypeError, match=msg):
199
+ b > a
200
+ with pytest.raises(TypeError, match=msg):
201
+ b >= a
202
+
203
+ assert not a == b.to_pydatetime()
204
+ assert not a.to_pydatetime() == b
205
+
206
+ def test_timestamp_compare_scalars(self):
207
+ # case where ndim == 0
208
+ lhs = np.datetime64(datetime(2013, 12, 6))
209
+ rhs = Timestamp("now")
210
+ nat = Timestamp("nat")
211
+
212
+ ops = {"gt": "lt", "lt": "gt", "ge": "le", "le": "ge", "eq": "eq", "ne": "ne"}
213
+
214
+ for left, right in ops.items():
215
+ left_f = getattr(operator, left)
216
+ right_f = getattr(operator, right)
217
+ expected = left_f(lhs, rhs)
218
+
219
+ result = right_f(rhs, lhs)
220
+ assert result == expected
221
+
222
+ expected = left_f(rhs, nat)
223
+ result = right_f(nat, rhs)
224
+ assert result == expected
225
+
226
+ def test_timestamp_compare_with_early_datetime(self):
227
+ # e.g. datetime.min
228
+ stamp = Timestamp("2012-01-01")
229
+
230
+ assert not stamp == datetime.min
231
+ assert not stamp == datetime(1600, 1, 1)
232
+ assert not stamp == datetime(2700, 1, 1)
233
+ assert stamp != datetime.min
234
+ assert stamp != datetime(1600, 1, 1)
235
+ assert stamp != datetime(2700, 1, 1)
236
+ assert stamp > datetime(1600, 1, 1)
237
+ assert stamp >= datetime(1600, 1, 1)
238
+ assert stamp < datetime(2700, 1, 1)
239
+ assert stamp <= datetime(2700, 1, 1)
240
+
241
+ other = Timestamp.min.to_pydatetime(warn=False)
242
+ assert other - timedelta(microseconds=1) < Timestamp.min
243
+
244
+ def test_timestamp_compare_oob_dt64(self):
245
+ us = np.timedelta64(1, "us")
246
+ other = np.datetime64(Timestamp.min).astype("M8[us]")
247
+
248
+ # This may change if the implementation bound is dropped to match
249
+ # DatetimeArray/DatetimeIndex GH#24124
250
+ assert Timestamp.min > other
251
+ # Note: numpy gets the reversed comparison wrong
252
+
253
+ other = np.datetime64(Timestamp.max).astype("M8[us]")
254
+ assert Timestamp.max > other # not actually OOB
255
+ assert other < Timestamp.max
256
+
257
+ assert Timestamp.max < other + us
258
+ # Note: numpy gets the reversed comparison wrong
259
+
260
+ # GH-42794
261
+ other = datetime(9999, 9, 9)
262
+ assert Timestamp.min < other
263
+ assert other > Timestamp.min
264
+ assert Timestamp.max < other
265
+ assert other > Timestamp.max
266
+
267
+ other = datetime(1, 1, 1)
268
+ assert Timestamp.max > other
269
+ assert other < Timestamp.max
270
+ assert Timestamp.min > other
271
+ assert other < Timestamp.min
272
+
273
+ def test_compare_zerodim_array(self, fixed_now_ts):
274
+ # GH#26916
275
+ ts = fixed_now_ts
276
+ dt64 = np.datetime64("2016-01-01", "ns")
277
+ arr = np.array(dt64)
278
+ assert arr.ndim == 0
279
+
280
+ result = arr < ts
281
+ assert result is np.bool_(True)
282
+ result = arr > ts
283
+ assert result is np.bool_(False)
284
+
285
+
286
+ def test_rich_comparison_with_unsupported_type():
287
+ # Comparisons with unsupported objects should return NotImplemented
288
+ # (it previously raised TypeError, see #24011)
289
+
290
+ class Inf:
291
+ def __lt__(self, o):
292
+ return False
293
+
294
+ def __le__(self, o):
295
+ return isinstance(o, Inf)
296
+
297
+ def __gt__(self, o):
298
+ return not isinstance(o, Inf)
299
+
300
+ def __ge__(self, o):
301
+ return True
302
+
303
+ def __eq__(self, other) -> bool:
304
+ return isinstance(other, Inf)
305
+
306
+ inf = Inf()
307
+ timestamp = Timestamp("2018-11-30")
308
+
309
+ for left, right in [(inf, timestamp), (timestamp, inf)]:
310
+ assert left > right or left < right
311
+ assert left >= right or left <= right
312
+ assert not left == right # pylint: disable=unneeded-not
313
+ assert left != right
py311/lib/python3.11/site-packages/pandas/tests/scalar/timestamp/test_constructors.py ADDED
@@ -0,0 +1,1077 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import calendar
2
+ from datetime import (
3
+ date,
4
+ datetime,
5
+ timedelta,
6
+ timezone,
7
+ )
8
+ import zoneinfo
9
+
10
+ import dateutil.tz
11
+ from dateutil.tz import (
12
+ gettz,
13
+ tzoffset,
14
+ tzutc,
15
+ )
16
+ import numpy as np
17
+ import pytest
18
+ import pytz
19
+
20
+ from pandas._libs.tslibs.dtypes import NpyDatetimeUnit
21
+ from pandas.compat import (
22
+ PY310,
23
+ PY314,
24
+ )
25
+ from pandas.errors import OutOfBoundsDatetime
26
+
27
+ from pandas import (
28
+ NA,
29
+ NaT,
30
+ Period,
31
+ Timedelta,
32
+ Timestamp,
33
+ )
34
+
35
+
36
+ class TestTimestampConstructorUnitKeyword:
37
+ @pytest.mark.parametrize("typ", [int, float])
38
+ def test_constructor_int_float_with_YM_unit(self, typ):
39
+ # GH#47266 avoid the conversions in cast_from_unit
40
+ val = typ(150)
41
+
42
+ ts = Timestamp(val, unit="Y")
43
+ expected = Timestamp("2120-01-01")
44
+ assert ts == expected
45
+
46
+ ts = Timestamp(val, unit="M")
47
+ expected = Timestamp("1982-07-01")
48
+ assert ts == expected
49
+
50
+ @pytest.mark.parametrize("typ", [int, float])
51
+ def test_construct_from_int_float_with_unit_out_of_bound_raises(self, typ):
52
+ # GH#50870 make sure we get a OutOfBoundsDatetime instead of OverflowError
53
+ val = typ(150000000000000)
54
+
55
+ msg = f"cannot convert input {val} with the unit 'D'"
56
+ with pytest.raises(OutOfBoundsDatetime, match=msg):
57
+ Timestamp(val, unit="D")
58
+
59
+ def test_constructor_float_not_round_with_YM_unit_raises(self):
60
+ # GH#47267 avoid the conversions in cast_from-unit
61
+
62
+ msg = "Conversion of non-round float with unit=[MY] is ambiguous"
63
+ with pytest.raises(ValueError, match=msg):
64
+ Timestamp(150.5, unit="Y")
65
+
66
+ with pytest.raises(ValueError, match=msg):
67
+ Timestamp(150.5, unit="M")
68
+
69
+ @pytest.mark.parametrize(
70
+ "value, check_kwargs",
71
+ [
72
+ [946688461000000000, {}],
73
+ [946688461000000000 / 1000, {"unit": "us"}],
74
+ [946688461000000000 / 1_000_000, {"unit": "ms"}],
75
+ [946688461000000000 / 1_000_000_000, {"unit": "s"}],
76
+ [10957, {"unit": "D", "h": 0}],
77
+ [
78
+ (946688461000000000 + 500000) / 1000000000,
79
+ {"unit": "s", "us": 499, "ns": 964},
80
+ ],
81
+ [
82
+ (946688461000000000 + 500000000) / 1000000000,
83
+ {"unit": "s", "us": 500000},
84
+ ],
85
+ [(946688461000000000 + 500000) / 1000000, {"unit": "ms", "us": 500}],
86
+ [(946688461000000000 + 500000) / 1000, {"unit": "us", "us": 500}],
87
+ [(946688461000000000 + 500000000) / 1000000, {"unit": "ms", "us": 500000}],
88
+ [946688461000000000 / 1000.0 + 5, {"unit": "us", "us": 5}],
89
+ [946688461000000000 / 1000.0 + 5000, {"unit": "us", "us": 5000}],
90
+ [946688461000000000 / 1000000.0 + 0.5, {"unit": "ms", "us": 500}],
91
+ [946688461000000000 / 1000000.0 + 0.005, {"unit": "ms", "us": 5, "ns": 5}],
92
+ [946688461000000000 / 1000000000.0 + 0.5, {"unit": "s", "us": 500000}],
93
+ [10957 + 0.5, {"unit": "D", "h": 12}],
94
+ ],
95
+ )
96
+ def test_construct_with_unit(self, value, check_kwargs):
97
+ def check(value, unit=None, h=1, s=1, us=0, ns=0):
98
+ stamp = Timestamp(value, unit=unit)
99
+ assert stamp.year == 2000
100
+ assert stamp.month == 1
101
+ assert stamp.day == 1
102
+ assert stamp.hour == h
103
+ if unit != "D":
104
+ assert stamp.minute == 1
105
+ assert stamp.second == s
106
+ assert stamp.microsecond == us
107
+ else:
108
+ assert stamp.minute == 0
109
+ assert stamp.second == 0
110
+ assert stamp.microsecond == 0
111
+ assert stamp.nanosecond == ns
112
+
113
+ check(value, **check_kwargs)
114
+
115
+
116
+ class TestTimestampConstructorFoldKeyword:
117
+ def test_timestamp_constructor_invalid_fold_raise(self):
118
+ # Test for GH#25057
119
+ # Valid fold values are only [None, 0, 1]
120
+ msg = "Valid values for the fold argument are None, 0, or 1."
121
+ with pytest.raises(ValueError, match=msg):
122
+ Timestamp(123, fold=2)
123
+
124
+ def test_timestamp_constructor_pytz_fold_raise(self):
125
+ # Test for GH#25057
126
+ # pytz doesn't support fold. Check that we raise
127
+ # if fold is passed with pytz
128
+ msg = "pytz timezones do not support fold. Please use dateutil timezones."
129
+ tz = pytz.timezone("Europe/London")
130
+ with pytest.raises(ValueError, match=msg):
131
+ Timestamp(datetime(2019, 10, 27, 0, 30, 0, 0), tz=tz, fold=0)
132
+
133
+ @pytest.mark.parametrize("fold", [0, 1])
134
+ @pytest.mark.parametrize(
135
+ "ts_input",
136
+ [
137
+ 1572136200000000000,
138
+ 1572136200000000000.0,
139
+ np.datetime64(1572136200000000000, "ns"),
140
+ "2019-10-27 01:30:00+01:00",
141
+ datetime(2019, 10, 27, 0, 30, 0, 0, tzinfo=timezone.utc),
142
+ ],
143
+ )
144
+ def test_timestamp_constructor_fold_conflict(self, ts_input, fold):
145
+ # Test for GH#25057
146
+ # Check that we raise on fold conflict
147
+ msg = (
148
+ "Cannot pass fold with possibly unambiguous input: int, float, "
149
+ "numpy.datetime64, str, or timezone-aware datetime-like. "
150
+ "Pass naive datetime-like or build Timestamp from components."
151
+ )
152
+ with pytest.raises(ValueError, match=msg):
153
+ Timestamp(ts_input=ts_input, fold=fold)
154
+
155
+ @pytest.mark.parametrize("tz", ["dateutil/Europe/London", None])
156
+ @pytest.mark.parametrize("fold", [0, 1])
157
+ def test_timestamp_constructor_retain_fold(self, tz, fold):
158
+ # Test for GH#25057
159
+ # Check that we retain fold
160
+ ts = Timestamp(year=2019, month=10, day=27, hour=1, minute=30, tz=tz, fold=fold)
161
+ result = ts.fold
162
+ expected = fold
163
+ assert result == expected
164
+
165
+ try:
166
+ _tzs = [
167
+ "dateutil/Europe/London",
168
+ zoneinfo.ZoneInfo("Europe/London"),
169
+ ]
170
+ except zoneinfo.ZoneInfoNotFoundError:
171
+ _tzs = ["dateutil/Europe/London"]
172
+
173
+ @pytest.mark.parametrize("tz", _tzs)
174
+ @pytest.mark.parametrize(
175
+ "ts_input,fold_out",
176
+ [
177
+ (1572136200000000000, 0),
178
+ (1572139800000000000, 1),
179
+ ("2019-10-27 01:30:00+01:00", 0),
180
+ ("2019-10-27 01:30:00+00:00", 1),
181
+ (datetime(2019, 10, 27, 1, 30, 0, 0, fold=0), 0),
182
+ (datetime(2019, 10, 27, 1, 30, 0, 0, fold=1), 1),
183
+ ],
184
+ )
185
+ def test_timestamp_constructor_infer_fold_from_value(self, tz, ts_input, fold_out):
186
+ # Test for GH#25057
187
+ # Check that we infer fold correctly based on timestamps since utc
188
+ # or strings
189
+ ts = Timestamp(ts_input, tz=tz)
190
+ result = ts.fold
191
+ expected = fold_out
192
+ assert result == expected
193
+
194
+ @pytest.mark.parametrize("tz", ["dateutil/Europe/London"])
195
+ @pytest.mark.parametrize(
196
+ "ts_input,fold,value_out",
197
+ [
198
+ (datetime(2019, 10, 27, 1, 30, 0, 0), 0, 1572136200000000),
199
+ (datetime(2019, 10, 27, 1, 30, 0, 0), 1, 1572139800000000),
200
+ ],
201
+ )
202
+ def test_timestamp_constructor_adjust_value_for_fold(
203
+ self, tz, ts_input, fold, value_out
204
+ ):
205
+ # Test for GH#25057
206
+ # Check that we adjust value for fold correctly
207
+ # based on timestamps since utc
208
+ ts = Timestamp(ts_input, tz=tz, fold=fold)
209
+ result = ts._value
210
+ expected = value_out
211
+ assert result == expected
212
+
213
+
214
+ class TestTimestampConstructorPositionalAndKeywordSupport:
215
+ def test_constructor_positional(self):
216
+ # see GH#10758
217
+ msg = (
218
+ "'NoneType' object cannot be interpreted as an integer"
219
+ if PY310
220
+ else "an integer is required"
221
+ )
222
+ with pytest.raises(TypeError, match=msg):
223
+ Timestamp(2000, 1)
224
+
225
+ msg = "month must be in 1..12"
226
+ with pytest.raises(ValueError, match=msg):
227
+ Timestamp(2000, 0, 1)
228
+ with pytest.raises(ValueError, match=msg):
229
+ Timestamp(2000, 13, 1)
230
+
231
+ if PY314:
232
+ msg = "must be in range 1..31 for month 1 in year 2000"
233
+ else:
234
+ msg = "day is out of range for month"
235
+ with pytest.raises(ValueError, match=msg):
236
+ Timestamp(2000, 1, 0)
237
+ with pytest.raises(ValueError, match=msg):
238
+ Timestamp(2000, 1, 32)
239
+
240
+ # see gh-11630
241
+ assert repr(Timestamp(2015, 11, 12)) == repr(Timestamp("20151112"))
242
+ assert repr(Timestamp(2015, 11, 12, 1, 2, 3, 999999)) == repr(
243
+ Timestamp("2015-11-12 01:02:03.999999")
244
+ )
245
+
246
+ def test_constructor_keyword(self):
247
+ # GH#10758
248
+ msg = "function missing required argument 'day'|Required argument 'day'"
249
+ with pytest.raises(TypeError, match=msg):
250
+ Timestamp(year=2000, month=1)
251
+
252
+ msg = "month must be in 1..12"
253
+ with pytest.raises(ValueError, match=msg):
254
+ Timestamp(year=2000, month=0, day=1)
255
+ with pytest.raises(ValueError, match=msg):
256
+ Timestamp(year=2000, month=13, day=1)
257
+
258
+ if PY314:
259
+ msg = "must be in range 1..31 for month 1 in year 2000"
260
+ else:
261
+ msg = "day is out of range for month"
262
+ with pytest.raises(ValueError, match=msg):
263
+ Timestamp(year=2000, month=1, day=0)
264
+ with pytest.raises(ValueError, match=msg):
265
+ Timestamp(year=2000, month=1, day=32)
266
+
267
+ assert repr(Timestamp(year=2015, month=11, day=12)) == repr(
268
+ Timestamp("20151112")
269
+ )
270
+
271
+ assert repr(
272
+ Timestamp(
273
+ year=2015,
274
+ month=11,
275
+ day=12,
276
+ hour=1,
277
+ minute=2,
278
+ second=3,
279
+ microsecond=999999,
280
+ )
281
+ ) == repr(Timestamp("2015-11-12 01:02:03.999999"))
282
+
283
+ @pytest.mark.parametrize(
284
+ "arg",
285
+ [
286
+ "year",
287
+ "month",
288
+ "day",
289
+ "hour",
290
+ "minute",
291
+ "second",
292
+ "microsecond",
293
+ "nanosecond",
294
+ ],
295
+ )
296
+ def test_invalid_date_kwarg_with_string_input(self, arg):
297
+ kwarg = {arg: 1}
298
+ msg = "Cannot pass a date attribute keyword argument"
299
+ with pytest.raises(ValueError, match=msg):
300
+ Timestamp("2010-10-10 12:59:59.999999999", **kwarg)
301
+
302
+ @pytest.mark.parametrize("kwargs", [{}, {"year": 2020}, {"year": 2020, "month": 1}])
303
+ def test_constructor_missing_keyword(self, kwargs):
304
+ # GH#31200
305
+
306
+ # The exact error message of datetime() depends on its version
307
+ msg1 = r"function missing required argument '(year|month|day)' \(pos [123]\)"
308
+ msg2 = r"Required argument '(year|month|day)' \(pos [123]\) not found"
309
+ msg = "|".join([msg1, msg2])
310
+
311
+ with pytest.raises(TypeError, match=msg):
312
+ Timestamp(**kwargs)
313
+
314
+ def test_constructor_positional_with_tzinfo(self):
315
+ # GH#31929
316
+ ts = Timestamp(2020, 12, 31, tzinfo=timezone.utc)
317
+ expected = Timestamp("2020-12-31", tzinfo=timezone.utc)
318
+ assert ts == expected
319
+
320
+ @pytest.mark.parametrize("kwd", ["nanosecond", "microsecond", "second", "minute"])
321
+ def test_constructor_positional_keyword_mixed_with_tzinfo(self, kwd, request):
322
+ # TODO: if we passed microsecond with a keyword we would mess up
323
+ # xref GH#45307
324
+ if kwd != "nanosecond":
325
+ # nanosecond is keyword-only as of 2.0, others are not
326
+ mark = pytest.mark.xfail(reason="GH#45307")
327
+ request.applymarker(mark)
328
+
329
+ kwargs = {kwd: 4}
330
+ ts = Timestamp(2020, 12, 31, tzinfo=timezone.utc, **kwargs)
331
+
332
+ td_kwargs = {kwd + "s": 4}
333
+ td = Timedelta(**td_kwargs)
334
+ expected = Timestamp("2020-12-31", tz=timezone.utc) + td
335
+ assert ts == expected
336
+
337
+
338
+ class TestTimestampClassMethodConstructors:
339
+ # Timestamp constructors other than __new__
340
+
341
+ def test_constructor_strptime(self):
342
+ # GH#25016
343
+ # Test support for Timestamp.strptime
344
+ fmt = "%Y%m%d-%H%M%S-%f%z"
345
+ ts = "20190129-235348-000001+0000"
346
+ msg = r"Timestamp.strptime\(\) is not implemented"
347
+ with pytest.raises(NotImplementedError, match=msg):
348
+ Timestamp.strptime(ts, fmt)
349
+
350
+ def test_constructor_fromisocalendar(self):
351
+ # GH#30395
352
+ expected_timestamp = Timestamp("2000-01-03 00:00:00")
353
+ expected_stdlib = datetime.fromisocalendar(2000, 1, 1)
354
+ result = Timestamp.fromisocalendar(2000, 1, 1)
355
+ assert result == expected_timestamp
356
+ assert result == expected_stdlib
357
+ assert isinstance(result, Timestamp)
358
+
359
+ def test_constructor_fromordinal(self):
360
+ base = datetime(2000, 1, 1)
361
+
362
+ ts = Timestamp.fromordinal(base.toordinal())
363
+ assert base == ts
364
+ assert base.toordinal() == ts.toordinal()
365
+
366
+ ts = Timestamp.fromordinal(base.toordinal(), tz="US/Eastern")
367
+ assert Timestamp("2000-01-01", tz="US/Eastern") == ts
368
+ assert base.toordinal() == ts.toordinal()
369
+
370
+ # GH#3042
371
+ dt = datetime(2011, 4, 16, 0, 0)
372
+ ts = Timestamp.fromordinal(dt.toordinal())
373
+ assert ts.to_pydatetime() == dt
374
+
375
+ # with a tzinfo
376
+ stamp = Timestamp("2011-4-16", tz="US/Eastern")
377
+ dt_tz = stamp.to_pydatetime()
378
+ ts = Timestamp.fromordinal(dt_tz.toordinal(), tz="US/Eastern")
379
+ assert ts.to_pydatetime() == dt_tz
380
+
381
+ def test_now(self):
382
+ # GH#9000
383
+ ts_from_string = Timestamp("now")
384
+ ts_from_method = Timestamp.now()
385
+ ts_datetime = datetime.now()
386
+
387
+ ts_from_string_tz = Timestamp("now", tz="US/Eastern")
388
+ ts_from_method_tz = Timestamp.now(tz="US/Eastern")
389
+
390
+ # Check that the delta between the times is less than 1s (arbitrarily
391
+ # small)
392
+ delta = Timedelta(seconds=1)
393
+ assert abs(ts_from_method - ts_from_string) < delta
394
+ assert abs(ts_datetime - ts_from_method) < delta
395
+ assert abs(ts_from_method_tz - ts_from_string_tz) < delta
396
+ assert (
397
+ abs(
398
+ ts_from_string_tz.tz_localize(None)
399
+ - ts_from_method_tz.tz_localize(None)
400
+ )
401
+ < delta
402
+ )
403
+
404
+ def test_today(self):
405
+ ts_from_string = Timestamp("today")
406
+ ts_from_method = Timestamp.today()
407
+ ts_datetime = datetime.today()
408
+
409
+ ts_from_string_tz = Timestamp("today", tz="US/Eastern")
410
+ ts_from_method_tz = Timestamp.today(tz="US/Eastern")
411
+
412
+ # Check that the delta between the times is less than 1s (arbitrarily
413
+ # small)
414
+ delta = Timedelta(seconds=1)
415
+ assert abs(ts_from_method - ts_from_string) < delta
416
+ assert abs(ts_datetime - ts_from_method) < delta
417
+ assert abs(ts_from_method_tz - ts_from_string_tz) < delta
418
+ assert (
419
+ abs(
420
+ ts_from_string_tz.tz_localize(None)
421
+ - ts_from_method_tz.tz_localize(None)
422
+ )
423
+ < delta
424
+ )
425
+
426
+
427
+ class TestTimestampResolutionInference:
428
+ def test_construct_from_time_unit(self):
429
+ # GH#54097 only passing a time component, no date
430
+ ts = Timestamp("01:01:01.111")
431
+ assert ts.unit == "ms"
432
+
433
+ def test_constructor_str_infer_reso(self):
434
+ # non-iso8601 path
435
+
436
+ # _parse_delimited_date path
437
+ ts = Timestamp("01/30/2023")
438
+ assert ts.unit == "s"
439
+
440
+ # _parse_dateabbr_string path
441
+ ts = Timestamp("2015Q1")
442
+ assert ts.unit == "s"
443
+
444
+ # dateutil_parse path
445
+ ts = Timestamp("2016-01-01 1:30:01 PM")
446
+ assert ts.unit == "s"
447
+
448
+ ts = Timestamp("2016 June 3 15:25:01.345")
449
+ assert ts.unit == "ms"
450
+
451
+ ts = Timestamp("300-01-01")
452
+ assert ts.unit == "s"
453
+
454
+ ts = Timestamp("300 June 1:30:01.300")
455
+ assert ts.unit == "ms"
456
+
457
+ # dateutil path -> don't drop trailing zeros
458
+ ts = Timestamp("01-01-2013T00:00:00.000000000+0000")
459
+ assert ts.unit == "ns"
460
+
461
+ ts = Timestamp("2016/01/02 03:04:05.001000 UTC")
462
+ assert ts.unit == "us"
463
+
464
+ # higher-than-nanosecond -> we drop the trailing bits
465
+ ts = Timestamp("01-01-2013T00:00:00.000000002100+0000")
466
+ assert ts == Timestamp("01-01-2013T00:00:00.000000002+0000")
467
+ assert ts.unit == "ns"
468
+
469
+ # GH#56208 minute reso through the ISO8601 path with tz offset
470
+ ts = Timestamp("2020-01-01 00:00+00:00")
471
+ assert ts.unit == "s"
472
+
473
+ ts = Timestamp("2020-01-01 00+00:00")
474
+ assert ts.unit == "s"
475
+
476
+ @pytest.mark.parametrize("method", ["now", "today"])
477
+ def test_now_today_unit(self, method):
478
+ # GH#55879
479
+ ts_from_method = getattr(Timestamp, method)()
480
+ ts_from_string = Timestamp(method)
481
+ assert ts_from_method.unit == ts_from_string.unit == "us"
482
+
483
+
484
+ class TestTimestampConstructors:
485
+ def test_weekday_but_no_day_raises(self):
486
+ # GH#52659
487
+ msg = "Parsing datetimes with weekday but no day information is not supported"
488
+ with pytest.raises(ValueError, match=msg):
489
+ Timestamp("2023 Sept Thu")
490
+
491
+ def test_construct_from_string_invalid_raises(self):
492
+ # dateutil (weirdly) parses "200622-12-31" as
493
+ # datetime(2022, 6, 20, 12, 0, tzinfo=tzoffset(None, -111600)
494
+ # which besides being mis-parsed, is a tzoffset that will cause
495
+ # str(ts) to raise ValueError. Ensure we raise in the constructor
496
+ # instead.
497
+ # see test_to_datetime_malformed_raise for analogous to_datetime test
498
+ with pytest.raises(ValueError, match="gives an invalid tzoffset"):
499
+ Timestamp("200622-12-31")
500
+
501
+ def test_constructor_from_iso8601_str_with_offset_reso(self):
502
+ # GH#49737
503
+ ts = Timestamp("2016-01-01 04:05:06-01:00")
504
+ assert ts.unit == "s"
505
+
506
+ ts = Timestamp("2016-01-01 04:05:06.000-01:00")
507
+ assert ts.unit == "ms"
508
+
509
+ ts = Timestamp("2016-01-01 04:05:06.000000-01:00")
510
+ assert ts.unit == "us"
511
+
512
+ ts = Timestamp("2016-01-01 04:05:06.000000001-01:00")
513
+ assert ts.unit == "ns"
514
+
515
+ def test_constructor_from_date_second_reso(self):
516
+ # GH#49034 constructing from a pydate object gets lowest supported
517
+ # reso, i.e. seconds
518
+ obj = date(2012, 9, 1)
519
+ ts = Timestamp(obj)
520
+ assert ts.unit == "s"
521
+
522
+ def test_constructor_datetime64_with_tz(self):
523
+ # GH#42288, GH#24559
524
+ dt = np.datetime64("1970-01-01 05:00:00")
525
+ tzstr = "UTC+05:00"
526
+
527
+ # pre-2.0 this interpreted dt as a UTC time. in 2.0 this is treated
528
+ # as a wall-time, consistent with DatetimeIndex behavior
529
+ ts = Timestamp(dt, tz=tzstr)
530
+
531
+ alt = Timestamp(dt).tz_localize(tzstr)
532
+ assert ts == alt
533
+ assert ts.hour == 5
534
+
535
+ def test_constructor(self):
536
+ base_str = "2014-07-01 09:00"
537
+ base_dt = datetime(2014, 7, 1, 9)
538
+ base_expected = 1_404_205_200_000_000_000
539
+
540
+ # confirm base representation is correct
541
+ assert calendar.timegm(base_dt.timetuple()) * 1_000_000_000 == base_expected
542
+
543
+ tests = [
544
+ (base_str, base_dt, base_expected),
545
+ (
546
+ "2014-07-01 10:00",
547
+ datetime(2014, 7, 1, 10),
548
+ base_expected + 3600 * 1_000_000_000,
549
+ ),
550
+ (
551
+ "2014-07-01 09:00:00.000008000",
552
+ datetime(2014, 7, 1, 9, 0, 0, 8),
553
+ base_expected + 8000,
554
+ ),
555
+ (
556
+ "2014-07-01 09:00:00.000000005",
557
+ Timestamp("2014-07-01 09:00:00.000000005"),
558
+ base_expected + 5,
559
+ ),
560
+ ]
561
+
562
+ timezones = [
563
+ (None, 0),
564
+ ("UTC", 0),
565
+ (pytz.utc, 0),
566
+ ("Asia/Tokyo", 9),
567
+ ("US/Eastern", -4),
568
+ ("dateutil/US/Pacific", -7),
569
+ (pytz.FixedOffset(-180), -3),
570
+ (dateutil.tz.tzoffset(None, 18000), 5),
571
+ ]
572
+
573
+ for date_str, date_obj, expected in tests:
574
+ for result in [Timestamp(date_str), Timestamp(date_obj)]:
575
+ result = result.as_unit("ns") # test originally written before non-nano
576
+ # only with timestring
577
+ assert result.as_unit("ns")._value == expected
578
+
579
+ # re-creation shouldn't affect to internal value
580
+ result = Timestamp(result)
581
+ assert result.as_unit("ns")._value == expected
582
+
583
+ # with timezone
584
+ for tz, offset in timezones:
585
+ for result in [Timestamp(date_str, tz=tz), Timestamp(date_obj, tz=tz)]:
586
+ result = result.as_unit(
587
+ "ns"
588
+ ) # test originally written before non-nano
589
+ expected_tz = expected - offset * 3600 * 1_000_000_000
590
+ assert result.as_unit("ns")._value == expected_tz
591
+
592
+ # should preserve tz
593
+ result = Timestamp(result)
594
+ assert result.as_unit("ns")._value == expected_tz
595
+
596
+ # should convert to UTC
597
+ if tz is not None:
598
+ result = Timestamp(result).tz_convert("UTC")
599
+ else:
600
+ result = Timestamp(result, tz="UTC")
601
+ expected_utc = expected - offset * 3600 * 1_000_000_000
602
+ assert result.as_unit("ns")._value == expected_utc
603
+
604
+ def test_constructor_with_stringoffset(self):
605
+ # GH 7833
606
+ base_str = "2014-07-01 11:00:00+02:00"
607
+ base_dt = datetime(2014, 7, 1, 9)
608
+ base_expected = 1_404_205_200_000_000_000
609
+
610
+ # confirm base representation is correct
611
+ assert calendar.timegm(base_dt.timetuple()) * 1_000_000_000 == base_expected
612
+
613
+ tests = [
614
+ (base_str, base_expected),
615
+ ("2014-07-01 12:00:00+02:00", base_expected + 3600 * 1_000_000_000),
616
+ ("2014-07-01 11:00:00.000008000+02:00", base_expected + 8000),
617
+ ("2014-07-01 11:00:00.000000005+02:00", base_expected + 5),
618
+ ]
619
+
620
+ timezones = [
621
+ (None, 0),
622
+ ("UTC", 0),
623
+ (pytz.utc, 0),
624
+ ("Asia/Tokyo", 9),
625
+ ("US/Eastern", -4),
626
+ ("dateutil/US/Pacific", -7),
627
+ (pytz.FixedOffset(-180), -3),
628
+ (dateutil.tz.tzoffset(None, 18000), 5),
629
+ ]
630
+
631
+ for date_str, expected in tests:
632
+ for result in [Timestamp(date_str)]:
633
+ # only with timestring
634
+ assert result.as_unit("ns")._value == expected
635
+
636
+ # re-creation shouldn't affect to internal value
637
+ result = Timestamp(result)
638
+ assert result.as_unit("ns")._value == expected
639
+
640
+ # with timezone
641
+ for tz, offset in timezones:
642
+ result = Timestamp(date_str, tz=tz)
643
+ expected_tz = expected
644
+ assert result.as_unit("ns")._value == expected_tz
645
+
646
+ # should preserve tz
647
+ result = Timestamp(result)
648
+ assert result.as_unit("ns")._value == expected_tz
649
+
650
+ # should convert to UTC
651
+ result = Timestamp(result).tz_convert("UTC")
652
+ expected_utc = expected
653
+ assert result.as_unit("ns")._value == expected_utc
654
+
655
+ # This should be 2013-11-01 05:00 in UTC
656
+ # converted to Chicago tz
657
+ result = Timestamp("2013-11-01 00:00:00-0500", tz="America/Chicago")
658
+ assert result._value == Timestamp("2013-11-01 05:00")._value
659
+ expected = "Timestamp('2013-11-01 00:00:00-0500', tz='America/Chicago')"
660
+ assert repr(result) == expected
661
+ assert result == eval(repr(result))
662
+
663
+ # This should be 2013-11-01 05:00 in UTC
664
+ # converted to Tokyo tz (+09:00)
665
+ result = Timestamp("2013-11-01 00:00:00-0500", tz="Asia/Tokyo")
666
+ assert result._value == Timestamp("2013-11-01 05:00")._value
667
+ expected = "Timestamp('2013-11-01 14:00:00+0900', tz='Asia/Tokyo')"
668
+ assert repr(result) == expected
669
+ assert result == eval(repr(result))
670
+
671
+ # GH11708
672
+ # This should be 2015-11-18 10:00 in UTC
673
+ # converted to Asia/Katmandu
674
+ result = Timestamp("2015-11-18 15:45:00+05:45", tz="Asia/Katmandu")
675
+ assert result._value == Timestamp("2015-11-18 10:00")._value
676
+ expected = "Timestamp('2015-11-18 15:45:00+0545', tz='Asia/Katmandu')"
677
+ assert repr(result) == expected
678
+ assert result == eval(repr(result))
679
+
680
+ # This should be 2015-11-18 10:00 in UTC
681
+ # converted to Asia/Kolkata
682
+ result = Timestamp("2015-11-18 15:30:00+05:30", tz="Asia/Kolkata")
683
+ assert result._value == Timestamp("2015-11-18 10:00")._value
684
+ expected = "Timestamp('2015-11-18 15:30:00+0530', tz='Asia/Kolkata')"
685
+ assert repr(result) == expected
686
+ assert result == eval(repr(result))
687
+
688
+ def test_constructor_invalid(self):
689
+ msg = "Cannot convert input"
690
+ with pytest.raises(TypeError, match=msg):
691
+ Timestamp(slice(2))
692
+ msg = "Cannot convert Period"
693
+ with pytest.raises(ValueError, match=msg):
694
+ Timestamp(Period("1000-01-01"))
695
+
696
+ def test_constructor_invalid_tz(self):
697
+ # GH#17690
698
+ msg = (
699
+ "Argument 'tzinfo' has incorrect type "
700
+ r"\(expected datetime.tzinfo, got str\)"
701
+ )
702
+ with pytest.raises(TypeError, match=msg):
703
+ Timestamp("2017-10-22", tzinfo="US/Eastern")
704
+
705
+ msg = "at most one of"
706
+ with pytest.raises(ValueError, match=msg):
707
+ Timestamp("2017-10-22", tzinfo=pytz.utc, tz="UTC")
708
+
709
+ msg = "Cannot pass a date attribute keyword argument when passing a date string"
710
+ with pytest.raises(ValueError, match=msg):
711
+ # GH#5168
712
+ # case where user tries to pass tz as an arg, not kwarg, gets
713
+ # interpreted as `year`
714
+ Timestamp("2012-01-01", "US/Pacific")
715
+
716
+ def test_constructor_tz_or_tzinfo(self):
717
+ # GH#17943, GH#17690, GH#5168
718
+ stamps = [
719
+ Timestamp(year=2017, month=10, day=22, tz="UTC"),
720
+ Timestamp(year=2017, month=10, day=22, tzinfo=pytz.utc),
721
+ Timestamp(year=2017, month=10, day=22, tz=pytz.utc),
722
+ Timestamp(datetime(2017, 10, 22), tzinfo=pytz.utc),
723
+ Timestamp(datetime(2017, 10, 22), tz="UTC"),
724
+ Timestamp(datetime(2017, 10, 22), tz=pytz.utc),
725
+ ]
726
+ assert all(ts == stamps[0] for ts in stamps)
727
+
728
+ @pytest.mark.parametrize(
729
+ "result",
730
+ [
731
+ Timestamp(datetime(2000, 1, 2, 3, 4, 5, 6), nanosecond=1),
732
+ Timestamp(
733
+ year=2000,
734
+ month=1,
735
+ day=2,
736
+ hour=3,
737
+ minute=4,
738
+ second=5,
739
+ microsecond=6,
740
+ nanosecond=1,
741
+ ),
742
+ Timestamp(
743
+ year=2000,
744
+ month=1,
745
+ day=2,
746
+ hour=3,
747
+ minute=4,
748
+ second=5,
749
+ microsecond=6,
750
+ nanosecond=1,
751
+ tz="UTC",
752
+ ),
753
+ Timestamp(2000, 1, 2, 3, 4, 5, 6, None, nanosecond=1),
754
+ Timestamp(2000, 1, 2, 3, 4, 5, 6, tz=pytz.UTC, nanosecond=1),
755
+ ],
756
+ )
757
+ def test_constructor_nanosecond(self, result):
758
+ # GH 18898
759
+ # As of 2.0 (GH 49416), nanosecond should not be accepted positionally
760
+ expected = Timestamp(datetime(2000, 1, 2, 3, 4, 5, 6), tz=result.tz)
761
+ expected = expected + Timedelta(nanoseconds=1)
762
+ assert result == expected
763
+
764
+ @pytest.mark.parametrize("z", ["Z0", "Z00"])
765
+ def test_constructor_invalid_Z0_isostring(self, z):
766
+ # GH 8910
767
+ msg = f"Unknown datetime string format, unable to parse: 2014-11-02 01:00{z}"
768
+ with pytest.raises(ValueError, match=msg):
769
+ Timestamp(f"2014-11-02 01:00{z}")
770
+
771
+ def test_out_of_bounds_integer_value(self):
772
+ # GH#26651 check that we raise OutOfBoundsDatetime, not OverflowError
773
+ msg = str(Timestamp.max._value * 2)
774
+ with pytest.raises(OutOfBoundsDatetime, match=msg):
775
+ Timestamp(Timestamp.max._value * 2)
776
+ msg = str(Timestamp.min._value * 2)
777
+ with pytest.raises(OutOfBoundsDatetime, match=msg):
778
+ Timestamp(Timestamp.min._value * 2)
779
+
780
+ def test_out_of_bounds_value(self):
781
+ one_us = np.timedelta64(1).astype("timedelta64[us]")
782
+
783
+ # By definition we can't go out of bounds in [ns], so we
784
+ # convert the datetime64s to [us] so we can go out of bounds
785
+ min_ts_us = np.datetime64(Timestamp.min).astype("M8[us]") + one_us
786
+ max_ts_us = np.datetime64(Timestamp.max).astype("M8[us]")
787
+
788
+ # No error for the min/max datetimes
789
+ Timestamp(min_ts_us)
790
+ Timestamp(max_ts_us)
791
+
792
+ # We used to raise on these before supporting non-nano
793
+ us_val = NpyDatetimeUnit.NPY_FR_us.value
794
+ assert Timestamp(min_ts_us - one_us)._creso == us_val
795
+ assert Timestamp(max_ts_us + one_us)._creso == us_val
796
+
797
+ # https://github.com/numpy/numpy/issues/22346 for why
798
+ # we can't use the same construction as above with minute resolution
799
+
800
+ # too_low, too_high are the _just_ outside the range of M8[s]
801
+ too_low = np.datetime64("-292277022657-01-27T08:29", "m")
802
+ too_high = np.datetime64("292277026596-12-04T15:31", "m")
803
+
804
+ msg = "Out of bounds"
805
+ # One us less than the minimum is an error
806
+ with pytest.raises(ValueError, match=msg):
807
+ Timestamp(too_low)
808
+
809
+ # One us more than the maximum is an error
810
+ with pytest.raises(ValueError, match=msg):
811
+ Timestamp(too_high)
812
+
813
+ def test_out_of_bounds_string(self):
814
+ msg = "Cannot cast .* to unit='ns' without overflow"
815
+ with pytest.raises(ValueError, match=msg):
816
+ Timestamp("1676-01-01").as_unit("ns")
817
+ with pytest.raises(ValueError, match=msg):
818
+ Timestamp("2263-01-01").as_unit("ns")
819
+
820
+ ts = Timestamp("2263-01-01")
821
+ assert ts.unit == "s"
822
+
823
+ ts = Timestamp("1676-01-01")
824
+ assert ts.unit == "s"
825
+
826
+ def test_barely_out_of_bounds(self):
827
+ # GH#19529
828
+ # GH#19382 close enough to bounds that dropping nanos would result
829
+ # in an in-bounds datetime
830
+ msg = "Out of bounds nanosecond timestamp: 2262-04-11 23:47:16"
831
+ with pytest.raises(OutOfBoundsDatetime, match=msg):
832
+ Timestamp("2262-04-11 23:47:16.854775808")
833
+
834
+ @pytest.mark.skip_ubsan
835
+ def test_bounds_with_different_units(self):
836
+ out_of_bounds_dates = ("1677-09-21", "2262-04-12")
837
+
838
+ time_units = ("D", "h", "m", "s", "ms", "us")
839
+
840
+ for date_string in out_of_bounds_dates:
841
+ for unit in time_units:
842
+ dt64 = np.datetime64(date_string, unit)
843
+ ts = Timestamp(dt64)
844
+ if unit in ["s", "ms", "us"]:
845
+ # We can preserve the input unit
846
+ assert ts._value == dt64.view("i8")
847
+ else:
848
+ # we chose the closest unit that we _do_ support
849
+ assert ts._creso == NpyDatetimeUnit.NPY_FR_s.value
850
+
851
+ # With more extreme cases, we can't even fit inside second resolution
852
+ info = np.iinfo(np.int64)
853
+ msg = "Out of bounds second timestamp:"
854
+ for value in [info.min + 1, info.max]:
855
+ for unit in ["D", "h", "m"]:
856
+ dt64 = np.datetime64(value, unit)
857
+ with pytest.raises(OutOfBoundsDatetime, match=msg):
858
+ Timestamp(dt64)
859
+
860
+ in_bounds_dates = ("1677-09-23", "2262-04-11")
861
+
862
+ for date_string in in_bounds_dates:
863
+ for unit in time_units:
864
+ dt64 = np.datetime64(date_string, unit)
865
+ Timestamp(dt64)
866
+
867
+ @pytest.mark.parametrize("arg", ["001-01-01", "0001-01-01"])
868
+ def test_out_of_bounds_string_consistency(self, arg):
869
+ # GH 15829
870
+ msg = "Cannot cast 0001-01-01 00:00:00 to unit='ns' without overflow"
871
+ with pytest.raises(OutOfBoundsDatetime, match=msg):
872
+ Timestamp(arg).as_unit("ns")
873
+
874
+ ts = Timestamp(arg)
875
+ assert ts.unit == "s"
876
+ assert ts.year == ts.month == ts.day == 1
877
+
878
+ def test_min_valid(self):
879
+ # Ensure that Timestamp.min is a valid Timestamp
880
+ Timestamp(Timestamp.min)
881
+
882
+ def test_max_valid(self):
883
+ # Ensure that Timestamp.max is a valid Timestamp
884
+ Timestamp(Timestamp.max)
885
+
886
+ @pytest.mark.parametrize("offset", ["+0300", "+0200"])
887
+ def test_construct_timestamp_near_dst(self, offset):
888
+ # GH 20854
889
+ expected = Timestamp(f"2016-10-30 03:00:00{offset}", tz="Europe/Helsinki")
890
+ result = Timestamp(expected).tz_convert("Europe/Helsinki")
891
+ assert result == expected
892
+
893
+ @pytest.mark.parametrize(
894
+ "arg", ["2013/01/01 00:00:00+09:00", "2013-01-01 00:00:00+09:00"]
895
+ )
896
+ def test_construct_with_different_string_format(self, arg):
897
+ # GH 12064
898
+ result = Timestamp(arg)
899
+ expected = Timestamp(datetime(2013, 1, 1), tz=pytz.FixedOffset(540))
900
+ assert result == expected
901
+
902
+ @pytest.mark.parametrize("box", [datetime, Timestamp])
903
+ def test_raise_tz_and_tzinfo_in_datetime_input(self, box):
904
+ # GH 23579
905
+ kwargs = {"year": 2018, "month": 1, "day": 1, "tzinfo": pytz.utc}
906
+ msg = "Cannot pass a datetime or Timestamp"
907
+ with pytest.raises(ValueError, match=msg):
908
+ Timestamp(box(**kwargs), tz="US/Pacific")
909
+ msg = "Cannot pass a datetime or Timestamp"
910
+ with pytest.raises(ValueError, match=msg):
911
+ Timestamp(box(**kwargs), tzinfo=pytz.timezone("US/Pacific"))
912
+
913
+ def test_dont_convert_dateutil_utc_to_pytz_utc(self):
914
+ result = Timestamp(datetime(2018, 1, 1), tz=tzutc())
915
+ expected = Timestamp(datetime(2018, 1, 1)).tz_localize(tzutc())
916
+ assert result == expected
917
+
918
+ def test_constructor_subclassed_datetime(self):
919
+ # GH 25851
920
+ # ensure that subclassed datetime works for
921
+ # Timestamp creation
922
+ class SubDatetime(datetime):
923
+ pass
924
+
925
+ data = SubDatetime(2000, 1, 1)
926
+ result = Timestamp(data)
927
+ expected = Timestamp(2000, 1, 1)
928
+ assert result == expected
929
+
930
+ def test_timestamp_constructor_tz_utc(self):
931
+ utc_stamp = Timestamp("3/11/2012 05:00", tz="utc")
932
+ assert utc_stamp.tzinfo is timezone.utc
933
+ assert utc_stamp.hour == 5
934
+
935
+ utc_stamp = Timestamp("3/11/2012 05:00").tz_localize("utc")
936
+ assert utc_stamp.hour == 5
937
+
938
+ def test_timestamp_to_datetime_tzoffset(self):
939
+ tzinfo = tzoffset(None, 7200)
940
+ expected = Timestamp("3/11/2012 04:00", tz=tzinfo)
941
+ result = Timestamp(expected.to_pydatetime())
942
+ assert expected == result
943
+
944
+ def test_timestamp_constructor_near_dst_boundary(self):
945
+ # GH#11481 & GH#15777
946
+ # Naive string timestamps were being localized incorrectly
947
+ # with tz_convert_from_utc_single instead of tz_localize_to_utc
948
+
949
+ for tz in ["Europe/Brussels", "Europe/Prague"]:
950
+ result = Timestamp("2015-10-25 01:00", tz=tz)
951
+ expected = Timestamp("2015-10-25 01:00").tz_localize(tz)
952
+ assert result == expected
953
+
954
+ msg = "Cannot infer dst time from 2015-10-25 02:00:00"
955
+ with pytest.raises(pytz.AmbiguousTimeError, match=msg):
956
+ Timestamp("2015-10-25 02:00", tz=tz)
957
+
958
+ result = Timestamp("2017-03-26 01:00", tz="Europe/Paris")
959
+ expected = Timestamp("2017-03-26 01:00").tz_localize("Europe/Paris")
960
+ assert result == expected
961
+
962
+ msg = "2017-03-26 02:00"
963
+ with pytest.raises(pytz.NonExistentTimeError, match=msg):
964
+ Timestamp("2017-03-26 02:00", tz="Europe/Paris")
965
+
966
+ # GH#11708
967
+ naive = Timestamp("2015-11-18 10:00:00")
968
+ result = naive.tz_localize("UTC").tz_convert("Asia/Kolkata")
969
+ expected = Timestamp("2015-11-18 15:30:00+0530", tz="Asia/Kolkata")
970
+ assert result == expected
971
+
972
+ # GH#15823
973
+ result = Timestamp("2017-03-26 00:00", tz="Europe/Paris")
974
+ expected = Timestamp("2017-03-26 00:00:00+0100", tz="Europe/Paris")
975
+ assert result == expected
976
+
977
+ result = Timestamp("2017-03-26 01:00", tz="Europe/Paris")
978
+ expected = Timestamp("2017-03-26 01:00:00+0100", tz="Europe/Paris")
979
+ assert result == expected
980
+
981
+ msg = "2017-03-26 02:00"
982
+ with pytest.raises(pytz.NonExistentTimeError, match=msg):
983
+ Timestamp("2017-03-26 02:00", tz="Europe/Paris")
984
+
985
+ result = Timestamp("2017-03-26 02:00:00+0100", tz="Europe/Paris")
986
+ naive = Timestamp(result.as_unit("ns")._value)
987
+ expected = naive.tz_localize("UTC").tz_convert("Europe/Paris")
988
+ assert result == expected
989
+
990
+ result = Timestamp("2017-03-26 03:00", tz="Europe/Paris")
991
+ expected = Timestamp("2017-03-26 03:00:00+0200", tz="Europe/Paris")
992
+ assert result == expected
993
+
994
+ @pytest.mark.parametrize(
995
+ "tz",
996
+ [
997
+ pytz.timezone("US/Eastern"),
998
+ gettz("US/Eastern"),
999
+ "US/Eastern",
1000
+ "dateutil/US/Eastern",
1001
+ ],
1002
+ )
1003
+ def test_timestamp_constructed_by_date_and_tz(self, tz):
1004
+ # GH#2993, Timestamp cannot be constructed by datetime.date
1005
+ # and tz correctly
1006
+
1007
+ result = Timestamp(date(2012, 3, 11), tz=tz)
1008
+
1009
+ expected = Timestamp("3/11/2012", tz=tz)
1010
+ assert result.hour == expected.hour
1011
+ assert result == expected
1012
+
1013
+
1014
+ def test_constructor_ambiguous_dst():
1015
+ # GH 24329
1016
+ # Make sure that calling Timestamp constructor
1017
+ # on Timestamp created from ambiguous time
1018
+ # doesn't change Timestamp.value
1019
+ ts = Timestamp(1382835600000000000, tz="dateutil/Europe/London")
1020
+ expected = ts._value
1021
+ result = Timestamp(ts)._value
1022
+ assert result == expected
1023
+
1024
+
1025
+ @pytest.mark.parametrize("epoch", [1552211999999999872, 1552211999999999999])
1026
+ def test_constructor_before_dst_switch(epoch):
1027
+ # GH 31043
1028
+ # Make sure that calling Timestamp constructor
1029
+ # on time just before DST switch doesn't lead to
1030
+ # nonexistent time or value change
1031
+ ts = Timestamp(epoch, tz="dateutil/America/Los_Angeles")
1032
+ result = ts.tz.dst(ts)
1033
+ expected = timedelta(seconds=0)
1034
+ assert Timestamp(ts)._value == epoch
1035
+ assert result == expected
1036
+
1037
+
1038
+ def test_timestamp_constructor_identity():
1039
+ # Test for #30543
1040
+ expected = Timestamp("2017-01-01T12")
1041
+ result = Timestamp(expected)
1042
+ assert result is expected
1043
+
1044
+
1045
+ @pytest.mark.parametrize("nano", [-1, 1000])
1046
+ def test_timestamp_nano_range(nano):
1047
+ # GH 48255
1048
+ with pytest.raises(ValueError, match="nanosecond must be in 0..999"):
1049
+ Timestamp(year=2022, month=1, day=1, nanosecond=nano)
1050
+
1051
+
1052
+ def test_non_nano_value():
1053
+ # https://github.com/pandas-dev/pandas/issues/49076
1054
+ result = Timestamp("1800-01-01", unit="s").value
1055
+ # `.value` shows nanoseconds, even though unit is 's'
1056
+ assert result == -5364662400000000000
1057
+
1058
+ # out-of-nanoseconds-bounds `.value` raises informative message
1059
+ msg = (
1060
+ r"Cannot convert Timestamp to nanoseconds without overflow. "
1061
+ r"Use `.asm8.view\('i8'\)` to cast represent Timestamp in its "
1062
+ r"own unit \(here, s\).$"
1063
+ )
1064
+ ts = Timestamp("0300-01-01")
1065
+ with pytest.raises(OverflowError, match=msg):
1066
+ ts.value
1067
+ # check that the suggested workaround actually works
1068
+ result = ts.asm8.view("i8")
1069
+ assert result == -52700112000
1070
+
1071
+
1072
+ @pytest.mark.parametrize("na_value", [None, np.nan, np.datetime64("NaT"), NaT, NA])
1073
+ def test_timestamp_constructor_na_value(na_value):
1074
+ # GH45481
1075
+ result = Timestamp(na_value)
1076
+ expected = NaT
1077
+ assert result is expected
py311/lib/python3.11/site-packages/pandas/tests/scalar/timestamp/test_timestamp.py ADDED
@@ -0,0 +1,928 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """ test the scalar Timestamp """
2
+
3
+ import calendar
4
+ from datetime import (
5
+ datetime,
6
+ timedelta,
7
+ timezone,
8
+ )
9
+ import locale
10
+ import time
11
+ import unicodedata
12
+
13
+ from dateutil.tz import (
14
+ tzlocal,
15
+ tzutc,
16
+ )
17
+ from hypothesis import (
18
+ given,
19
+ strategies as st,
20
+ )
21
+ import numpy as np
22
+ import pytest
23
+ import pytz
24
+ from pytz import utc
25
+
26
+ from pandas._libs.tslibs.dtypes import NpyDatetimeUnit
27
+ from pandas._libs.tslibs.timezones import (
28
+ dateutil_gettz as gettz,
29
+ get_timezone,
30
+ maybe_get_tz,
31
+ tz_compare,
32
+ )
33
+ from pandas.compat import IS64
34
+
35
+ from pandas import (
36
+ NaT,
37
+ Timedelta,
38
+ Timestamp,
39
+ )
40
+ import pandas._testing as tm
41
+
42
+ from pandas.tseries import offsets
43
+ from pandas.tseries.frequencies import to_offset
44
+
45
+
46
+ class TestTimestampProperties:
47
+ def test_properties_business(self):
48
+ freq = to_offset("B")
49
+
50
+ ts = Timestamp("2017-10-01")
51
+ assert ts.dayofweek == 6
52
+ assert ts.day_of_week == 6
53
+ assert ts.is_month_start # not a weekday
54
+ assert not freq.is_month_start(ts)
55
+ assert freq.is_month_start(ts + Timedelta(days=1))
56
+ assert not freq.is_quarter_start(ts)
57
+ assert freq.is_quarter_start(ts + Timedelta(days=1))
58
+
59
+ ts = Timestamp("2017-09-30")
60
+ assert ts.dayofweek == 5
61
+ assert ts.day_of_week == 5
62
+ assert ts.is_month_end
63
+ assert not freq.is_month_end(ts)
64
+ assert freq.is_month_end(ts - Timedelta(days=1))
65
+ assert ts.is_quarter_end
66
+ assert not freq.is_quarter_end(ts)
67
+ assert freq.is_quarter_end(ts - Timedelta(days=1))
68
+
69
+ @pytest.mark.parametrize(
70
+ "attr, expected",
71
+ [
72
+ ["year", 2014],
73
+ ["month", 12],
74
+ ["day", 31],
75
+ ["hour", 23],
76
+ ["minute", 59],
77
+ ["second", 0],
78
+ ["microsecond", 0],
79
+ ["nanosecond", 0],
80
+ ["dayofweek", 2],
81
+ ["day_of_week", 2],
82
+ ["quarter", 4],
83
+ ["dayofyear", 365],
84
+ ["day_of_year", 365],
85
+ ["week", 1],
86
+ ["daysinmonth", 31],
87
+ ],
88
+ )
89
+ @pytest.mark.parametrize("tz", [None, "US/Eastern"])
90
+ def test_fields(self, attr, expected, tz):
91
+ # GH 10050
92
+ # GH 13303
93
+ ts = Timestamp("2014-12-31 23:59:00", tz=tz)
94
+ result = getattr(ts, attr)
95
+ # that we are int like
96
+ assert isinstance(result, int)
97
+ assert result == expected
98
+
99
+ @pytest.mark.parametrize("tz", [None, "US/Eastern"])
100
+ def test_millisecond_raises(self, tz):
101
+ ts = Timestamp("2014-12-31 23:59:00", tz=tz)
102
+ msg = "'Timestamp' object has no attribute 'millisecond'"
103
+ with pytest.raises(AttributeError, match=msg):
104
+ ts.millisecond
105
+
106
+ @pytest.mark.parametrize(
107
+ "start", ["is_month_start", "is_quarter_start", "is_year_start"]
108
+ )
109
+ @pytest.mark.parametrize("tz", [None, "US/Eastern"])
110
+ def test_is_start(self, start, tz):
111
+ ts = Timestamp("2014-01-01 00:00:00", tz=tz)
112
+ assert getattr(ts, start)
113
+
114
+ @pytest.mark.parametrize("end", ["is_month_end", "is_year_end", "is_quarter_end"])
115
+ @pytest.mark.parametrize("tz", [None, "US/Eastern"])
116
+ def test_is_end(self, end, tz):
117
+ ts = Timestamp("2014-12-31 23:59:59", tz=tz)
118
+ assert getattr(ts, end)
119
+
120
+ # GH 12806
121
+ @pytest.mark.parametrize(
122
+ "data",
123
+ [Timestamp("2017-08-28 23:00:00"), Timestamp("2017-08-28 23:00:00", tz="EST")],
124
+ )
125
+ # error: Unsupported operand types for + ("List[None]" and "List[str]")
126
+ @pytest.mark.parametrize(
127
+ "time_locale", [None] + tm.get_locales() # type: ignore[operator]
128
+ )
129
+ def test_names(self, data, time_locale):
130
+ # GH 17354
131
+ # Test .day_name(), .month_name
132
+ if time_locale is None:
133
+ expected_day = "Monday"
134
+ expected_month = "August"
135
+ else:
136
+ with tm.set_locale(time_locale, locale.LC_TIME):
137
+ expected_day = calendar.day_name[0].capitalize()
138
+ expected_month = calendar.month_name[8].capitalize()
139
+
140
+ result_day = data.day_name(time_locale)
141
+ result_month = data.month_name(time_locale)
142
+
143
+ # Work around https://github.com/pandas-dev/pandas/issues/22342
144
+ # different normalizations
145
+ expected_day = unicodedata.normalize("NFD", expected_day)
146
+ expected_month = unicodedata.normalize("NFD", expected_month)
147
+
148
+ result_day = unicodedata.normalize("NFD", result_day)
149
+ result_month = unicodedata.normalize("NFD", result_month)
150
+
151
+ assert result_day == expected_day
152
+ assert result_month == expected_month
153
+
154
+ # Test NaT
155
+ nan_ts = Timestamp(NaT)
156
+ assert np.isnan(nan_ts.day_name(time_locale))
157
+ assert np.isnan(nan_ts.month_name(time_locale))
158
+
159
+ def test_is_leap_year(self, tz_naive_fixture):
160
+ tz = tz_naive_fixture
161
+ if not IS64 and tz == tzlocal():
162
+ # https://github.com/dateutil/dateutil/issues/197
163
+ pytest.skip(
164
+ "tzlocal() on a 32 bit platform causes internal overflow errors"
165
+ )
166
+ # GH 13727
167
+ dt = Timestamp("2000-01-01 00:00:00", tz=tz)
168
+ assert dt.is_leap_year
169
+ assert isinstance(dt.is_leap_year, bool)
170
+
171
+ dt = Timestamp("1999-01-01 00:00:00", tz=tz)
172
+ assert not dt.is_leap_year
173
+
174
+ dt = Timestamp("2004-01-01 00:00:00", tz=tz)
175
+ assert dt.is_leap_year
176
+
177
+ dt = Timestamp("2100-01-01 00:00:00", tz=tz)
178
+ assert not dt.is_leap_year
179
+
180
+ def test_woy_boundary(self):
181
+ # make sure weeks at year boundaries are correct
182
+ d = datetime(2013, 12, 31)
183
+ result = Timestamp(d).week
184
+ expected = 1 # ISO standard
185
+ assert result == expected
186
+
187
+ d = datetime(2008, 12, 28)
188
+ result = Timestamp(d).week
189
+ expected = 52 # ISO standard
190
+ assert result == expected
191
+
192
+ d = datetime(2009, 12, 31)
193
+ result = Timestamp(d).week
194
+ expected = 53 # ISO standard
195
+ assert result == expected
196
+
197
+ d = datetime(2010, 1, 1)
198
+ result = Timestamp(d).week
199
+ expected = 53 # ISO standard
200
+ assert result == expected
201
+
202
+ d = datetime(2010, 1, 3)
203
+ result = Timestamp(d).week
204
+ expected = 53 # ISO standard
205
+ assert result == expected
206
+
207
+ result = np.array(
208
+ [
209
+ Timestamp(datetime(*args)).week
210
+ for args in [(2000, 1, 1), (2000, 1, 2), (2005, 1, 1), (2005, 1, 2)]
211
+ ]
212
+ )
213
+ assert (result == [52, 52, 53, 53]).all()
214
+
215
+ def test_resolution(self):
216
+ # GH#21336, GH#21365
217
+ dt = Timestamp("2100-01-01 00:00:00.000000000")
218
+ assert dt.resolution == Timedelta(nanoseconds=1)
219
+
220
+ # Check that the attribute is available on the class, mirroring
221
+ # the stdlib datetime behavior
222
+ assert Timestamp.resolution == Timedelta(nanoseconds=1)
223
+
224
+ assert dt.as_unit("us").resolution == Timedelta(microseconds=1)
225
+ assert dt.as_unit("ms").resolution == Timedelta(milliseconds=1)
226
+ assert dt.as_unit("s").resolution == Timedelta(seconds=1)
227
+
228
+ @pytest.mark.parametrize(
229
+ "date_string, expected",
230
+ [
231
+ ("0000-2-29", 1),
232
+ ("0000-3-1", 2),
233
+ ("1582-10-14", 3),
234
+ ("-0040-1-1", 4),
235
+ ("2023-06-18", 6),
236
+ ],
237
+ )
238
+ def test_dow_historic(self, date_string, expected):
239
+ # GH 53738
240
+ ts = Timestamp(date_string)
241
+ dow = ts.weekday()
242
+ assert dow == expected
243
+
244
+ @given(
245
+ ts=st.datetimes(),
246
+ sign=st.sampled_from(["-", ""]),
247
+ )
248
+ def test_dow_parametric(self, ts, sign):
249
+ # GH 53738
250
+ ts = (
251
+ f"{sign}{str(ts.year).zfill(4)}"
252
+ f"-{str(ts.month).zfill(2)}"
253
+ f"-{str(ts.day).zfill(2)}"
254
+ )
255
+ result = Timestamp(ts).weekday()
256
+ expected = (
257
+ (np.datetime64(ts) - np.datetime64("1970-01-01")).astype("int64") - 4
258
+ ) % 7
259
+ assert result == expected
260
+
261
+
262
+ class TestTimestamp:
263
+ @pytest.mark.parametrize("tz", [None, pytz.timezone("US/Pacific")])
264
+ def test_disallow_setting_tz(self, tz):
265
+ # GH#3746
266
+ ts = Timestamp("2010")
267
+ msg = "Cannot directly set timezone"
268
+ with pytest.raises(AttributeError, match=msg):
269
+ ts.tz = tz
270
+
271
+ def test_default_to_stdlib_utc(self):
272
+ assert Timestamp.utcnow().tz is timezone.utc
273
+ assert Timestamp.now("UTC").tz is timezone.utc
274
+ assert Timestamp("2016-01-01", tz="UTC").tz is timezone.utc
275
+
276
+ def test_tz(self):
277
+ tstr = "2014-02-01 09:00"
278
+ ts = Timestamp(tstr)
279
+ local = ts.tz_localize("Asia/Tokyo")
280
+ assert local.hour == 9
281
+ assert local == Timestamp(tstr, tz="Asia/Tokyo")
282
+ conv = local.tz_convert("US/Eastern")
283
+ assert conv == Timestamp("2014-01-31 19:00", tz="US/Eastern")
284
+ assert conv.hour == 19
285
+
286
+ # preserves nanosecond
287
+ ts = Timestamp(tstr) + offsets.Nano(5)
288
+ local = ts.tz_localize("Asia/Tokyo")
289
+ assert local.hour == 9
290
+ assert local.nanosecond == 5
291
+ conv = local.tz_convert("US/Eastern")
292
+ assert conv.nanosecond == 5
293
+ assert conv.hour == 19
294
+
295
+ def test_utc_z_designator(self):
296
+ assert get_timezone(Timestamp("2014-11-02 01:00Z").tzinfo) is timezone.utc
297
+
298
+ def test_asm8(self):
299
+ ns = [Timestamp.min._value, Timestamp.max._value, 1000]
300
+
301
+ for n in ns:
302
+ assert (
303
+ Timestamp(n).asm8.view("i8") == np.datetime64(n, "ns").view("i8") == n
304
+ )
305
+
306
+ assert Timestamp("nat").asm8.view("i8") == np.datetime64("nat", "ns").view("i8")
307
+
308
+ def test_class_ops(self):
309
+ def compare(x, y):
310
+ assert int((Timestamp(x)._value - Timestamp(y)._value) / 1e9) == 0
311
+
312
+ compare(Timestamp.now(), datetime.now())
313
+ compare(Timestamp.now("UTC"), datetime.now(pytz.timezone("UTC")))
314
+ compare(Timestamp.now("UTC"), datetime.now(tzutc()))
315
+ compare(Timestamp.utcnow(), datetime.now(timezone.utc))
316
+ compare(Timestamp.today(), datetime.today())
317
+ current_time = calendar.timegm(datetime.now().utctimetuple())
318
+
319
+ ts_utc = Timestamp.utcfromtimestamp(current_time)
320
+ assert ts_utc.timestamp() == current_time
321
+ compare(
322
+ Timestamp.fromtimestamp(current_time), datetime.fromtimestamp(current_time)
323
+ )
324
+ compare(
325
+ # Support tz kwarg in Timestamp.fromtimestamp
326
+ Timestamp.fromtimestamp(current_time, "UTC"),
327
+ datetime.fromtimestamp(current_time, utc),
328
+ )
329
+ compare(
330
+ # Support tz kwarg in Timestamp.fromtimestamp
331
+ Timestamp.fromtimestamp(current_time, tz="UTC"),
332
+ datetime.fromtimestamp(current_time, utc),
333
+ )
334
+
335
+ date_component = datetime.now(timezone.utc)
336
+ time_component = (date_component + timedelta(minutes=10)).time()
337
+ compare(
338
+ Timestamp.combine(date_component, time_component),
339
+ datetime.combine(date_component, time_component),
340
+ )
341
+
342
+ def test_basics_nanos(self):
343
+ val = np.int64(946_684_800_000_000_000).view("M8[ns]")
344
+ stamp = Timestamp(val.view("i8") + 500)
345
+ assert stamp.year == 2000
346
+ assert stamp.month == 1
347
+ assert stamp.microsecond == 0
348
+ assert stamp.nanosecond == 500
349
+
350
+ # GH 14415
351
+ val = np.iinfo(np.int64).min + 80_000_000_000_000
352
+ stamp = Timestamp(val)
353
+ assert stamp.year == 1677
354
+ assert stamp.month == 9
355
+ assert stamp.day == 21
356
+ assert stamp.microsecond == 145224
357
+ assert stamp.nanosecond == 192
358
+
359
+ def test_roundtrip(self):
360
+ # test value to string and back conversions
361
+ # further test accessors
362
+ base = Timestamp("20140101 00:00:00").as_unit("ns")
363
+
364
+ result = Timestamp(base._value + Timedelta("5ms")._value)
365
+ assert result == Timestamp(f"{base}.005000")
366
+ assert result.microsecond == 5000
367
+
368
+ result = Timestamp(base._value + Timedelta("5us")._value)
369
+ assert result == Timestamp(f"{base}.000005")
370
+ assert result.microsecond == 5
371
+
372
+ result = Timestamp(base._value + Timedelta("5ns")._value)
373
+ assert result == Timestamp(f"{base}.000000005")
374
+ assert result.nanosecond == 5
375
+ assert result.microsecond == 0
376
+
377
+ result = Timestamp(base._value + Timedelta("6ms 5us")._value)
378
+ assert result == Timestamp(f"{base}.006005")
379
+ assert result.microsecond == 5 + 6 * 1000
380
+
381
+ result = Timestamp(base._value + Timedelta("200ms 5us")._value)
382
+ assert result == Timestamp(f"{base}.200005")
383
+ assert result.microsecond == 5 + 200 * 1000
384
+
385
+ def test_hash_equivalent(self):
386
+ d = {datetime(2011, 1, 1): 5}
387
+ stamp = Timestamp(datetime(2011, 1, 1))
388
+ assert d[stamp] == 5
389
+
390
+ @pytest.mark.parametrize(
391
+ "timezone, year, month, day, hour",
392
+ [["America/Chicago", 2013, 11, 3, 1], ["America/Santiago", 2021, 4, 3, 23]],
393
+ )
394
+ def test_hash_timestamp_with_fold(self, timezone, year, month, day, hour):
395
+ # see gh-33931
396
+ test_timezone = gettz(timezone)
397
+ transition_1 = Timestamp(
398
+ year=year,
399
+ month=month,
400
+ day=day,
401
+ hour=hour,
402
+ minute=0,
403
+ fold=0,
404
+ tzinfo=test_timezone,
405
+ )
406
+ transition_2 = Timestamp(
407
+ year=year,
408
+ month=month,
409
+ day=day,
410
+ hour=hour,
411
+ minute=0,
412
+ fold=1,
413
+ tzinfo=test_timezone,
414
+ )
415
+ assert hash(transition_1) == hash(transition_2)
416
+
417
+
418
+ class TestTimestampNsOperations:
419
+ def test_nanosecond_string_parsing(self):
420
+ ts = Timestamp("2013-05-01 07:15:45.123456789")
421
+ # GH 7878
422
+ expected_repr = "2013-05-01 07:15:45.123456789"
423
+ expected_value = 1_367_392_545_123_456_789
424
+ assert ts._value == expected_value
425
+ assert expected_repr in repr(ts)
426
+
427
+ ts = Timestamp("2013-05-01 07:15:45.123456789+09:00", tz="Asia/Tokyo")
428
+ assert ts._value == expected_value - 9 * 3600 * 1_000_000_000
429
+ assert expected_repr in repr(ts)
430
+
431
+ ts = Timestamp("2013-05-01 07:15:45.123456789", tz="UTC")
432
+ assert ts._value == expected_value
433
+ assert expected_repr in repr(ts)
434
+
435
+ ts = Timestamp("2013-05-01 07:15:45.123456789", tz="US/Eastern")
436
+ assert ts._value == expected_value + 4 * 3600 * 1_000_000_000
437
+ assert expected_repr in repr(ts)
438
+
439
+ # GH 10041
440
+ ts = Timestamp("20130501T071545.123456789")
441
+ assert ts._value == expected_value
442
+ assert expected_repr in repr(ts)
443
+
444
+ def test_nanosecond_timestamp(self):
445
+ # GH 7610
446
+ expected = 1_293_840_000_000_000_005
447
+ t = Timestamp("2011-01-01") + offsets.Nano(5)
448
+ assert repr(t) == "Timestamp('2011-01-01 00:00:00.000000005')"
449
+ assert t._value == expected
450
+ assert t.nanosecond == 5
451
+
452
+ t = Timestamp(t)
453
+ assert repr(t) == "Timestamp('2011-01-01 00:00:00.000000005')"
454
+ assert t._value == expected
455
+ assert t.nanosecond == 5
456
+
457
+ t = Timestamp("2011-01-01 00:00:00.000000005")
458
+ assert repr(t) == "Timestamp('2011-01-01 00:00:00.000000005')"
459
+ assert t._value == expected
460
+ assert t.nanosecond == 5
461
+
462
+ expected = 1_293_840_000_000_000_010
463
+ t = t + offsets.Nano(5)
464
+ assert repr(t) == "Timestamp('2011-01-01 00:00:00.000000010')"
465
+ assert t._value == expected
466
+ assert t.nanosecond == 10
467
+
468
+ t = Timestamp(t)
469
+ assert repr(t) == "Timestamp('2011-01-01 00:00:00.000000010')"
470
+ assert t._value == expected
471
+ assert t.nanosecond == 10
472
+
473
+ t = Timestamp("2011-01-01 00:00:00.000000010")
474
+ assert repr(t) == "Timestamp('2011-01-01 00:00:00.000000010')"
475
+ assert t._value == expected
476
+ assert t.nanosecond == 10
477
+
478
+
479
+ class TestTimestampConversion:
480
+ def test_conversion(self):
481
+ # GH#9255
482
+ ts = Timestamp("2000-01-01").as_unit("ns")
483
+
484
+ result = ts.to_pydatetime()
485
+ expected = datetime(2000, 1, 1)
486
+ assert result == expected
487
+ assert type(result) == type(expected)
488
+
489
+ result = ts.to_datetime64()
490
+ expected = np.datetime64(ts._value, "ns")
491
+ assert result == expected
492
+ assert type(result) == type(expected)
493
+ assert result.dtype == expected.dtype
494
+
495
+ def test_to_period_tz_warning(self):
496
+ # GH#21333 make sure a warning is issued when timezone
497
+ # info is lost
498
+ ts = Timestamp("2009-04-15 16:17:18", tz="US/Eastern")
499
+ with tm.assert_produces_warning(UserWarning):
500
+ # warning that timezone info will be lost
501
+ ts.to_period("D")
502
+
503
+ def test_to_numpy_alias(self):
504
+ # GH 24653: alias .to_numpy() for scalars
505
+ ts = Timestamp(datetime.now())
506
+ assert ts.to_datetime64() == ts.to_numpy()
507
+
508
+ # GH#44460
509
+ msg = "dtype and copy arguments are ignored"
510
+ with pytest.raises(ValueError, match=msg):
511
+ ts.to_numpy("M8[s]")
512
+ with pytest.raises(ValueError, match=msg):
513
+ ts.to_numpy(copy=True)
514
+
515
+
516
+ class TestNonNano:
517
+ @pytest.fixture(params=["s", "ms", "us"])
518
+ def reso(self, request):
519
+ return request.param
520
+
521
+ @pytest.fixture
522
+ def dt64(self, reso):
523
+ # cases that are in-bounds for nanosecond, so we can compare against
524
+ # the existing implementation.
525
+ return np.datetime64("2016-01-01", reso)
526
+
527
+ @pytest.fixture
528
+ def ts(self, dt64):
529
+ return Timestamp._from_dt64(dt64)
530
+
531
+ @pytest.fixture
532
+ def ts_tz(self, ts, tz_aware_fixture):
533
+ tz = maybe_get_tz(tz_aware_fixture)
534
+ return Timestamp._from_value_and_reso(ts._value, ts._creso, tz)
535
+
536
+ def test_non_nano_construction(self, dt64, ts, reso):
537
+ assert ts._value == dt64.view("i8")
538
+
539
+ if reso == "s":
540
+ assert ts._creso == NpyDatetimeUnit.NPY_FR_s.value
541
+ elif reso == "ms":
542
+ assert ts._creso == NpyDatetimeUnit.NPY_FR_ms.value
543
+ elif reso == "us":
544
+ assert ts._creso == NpyDatetimeUnit.NPY_FR_us.value
545
+
546
+ def test_non_nano_fields(self, dt64, ts):
547
+ alt = Timestamp(dt64)
548
+
549
+ assert ts.year == alt.year
550
+ assert ts.month == alt.month
551
+ assert ts.day == alt.day
552
+ assert ts.hour == ts.minute == ts.second == ts.microsecond == 0
553
+ assert ts.nanosecond == 0
554
+
555
+ assert ts.to_julian_date() == alt.to_julian_date()
556
+ assert ts.weekday() == alt.weekday()
557
+ assert ts.isoweekday() == alt.isoweekday()
558
+
559
+ def test_start_end_fields(self, ts):
560
+ assert ts.is_year_start
561
+ assert ts.is_quarter_start
562
+ assert ts.is_month_start
563
+ assert not ts.is_year_end
564
+ assert not ts.is_month_end
565
+ assert not ts.is_month_end
566
+
567
+ # 2016-01-01 is a Friday, so is year/quarter/month start with this freq
568
+ assert ts.is_year_start
569
+ assert ts.is_quarter_start
570
+ assert ts.is_month_start
571
+ assert not ts.is_year_end
572
+ assert not ts.is_month_end
573
+ assert not ts.is_month_end
574
+
575
+ def test_day_name(self, dt64, ts):
576
+ alt = Timestamp(dt64)
577
+ assert ts.day_name() == alt.day_name()
578
+
579
+ def test_month_name(self, dt64, ts):
580
+ alt = Timestamp(dt64)
581
+ assert ts.month_name() == alt.month_name()
582
+
583
+ def test_tz_convert(self, ts):
584
+ ts = Timestamp._from_value_and_reso(ts._value, ts._creso, utc)
585
+
586
+ tz = pytz.timezone("US/Pacific")
587
+ result = ts.tz_convert(tz)
588
+
589
+ assert isinstance(result, Timestamp)
590
+ assert result._creso == ts._creso
591
+ assert tz_compare(result.tz, tz)
592
+
593
+ def test_repr(self, dt64, ts):
594
+ alt = Timestamp(dt64)
595
+
596
+ assert str(ts) == str(alt)
597
+ assert repr(ts) == repr(alt)
598
+
599
+ def test_comparison(self, dt64, ts):
600
+ alt = Timestamp(dt64)
601
+
602
+ assert ts == dt64
603
+ assert dt64 == ts
604
+ assert ts == alt
605
+ assert alt == ts
606
+
607
+ assert not ts != dt64
608
+ assert not dt64 != ts
609
+ assert not ts != alt
610
+ assert not alt != ts
611
+
612
+ assert not ts < dt64
613
+ assert not dt64 < ts
614
+ assert not ts < alt
615
+ assert not alt < ts
616
+
617
+ assert not ts > dt64
618
+ assert not dt64 > ts
619
+ assert not ts > alt
620
+ assert not alt > ts
621
+
622
+ assert ts >= dt64
623
+ assert dt64 >= ts
624
+ assert ts >= alt
625
+ assert alt >= ts
626
+
627
+ assert ts <= dt64
628
+ assert dt64 <= ts
629
+ assert ts <= alt
630
+ assert alt <= ts
631
+
632
+ def test_cmp_cross_reso(self):
633
+ # numpy gets this wrong because of silent overflow
634
+ dt64 = np.datetime64(9223372800, "s") # won't fit in M8[ns]
635
+ ts = Timestamp._from_dt64(dt64)
636
+
637
+ # subtracting 3600*24 gives a datetime64 that _can_ fit inside the
638
+ # nanosecond implementation bounds.
639
+ other = Timestamp(dt64 - 3600 * 24).as_unit("ns")
640
+ assert other < ts
641
+ assert other.asm8 > ts.asm8 # <- numpy gets this wrong
642
+ assert ts > other
643
+ assert ts.asm8 < other.asm8 # <- numpy gets this wrong
644
+ assert not other == ts
645
+ assert ts != other
646
+
647
+ @pytest.mark.xfail(reason="Dispatches to np.datetime64 which is wrong")
648
+ def test_cmp_cross_reso_reversed_dt64(self):
649
+ dt64 = np.datetime64(106752, "D") # won't fit in M8[ns]
650
+ ts = Timestamp._from_dt64(dt64)
651
+ other = Timestamp(dt64 - 1)
652
+
653
+ assert other.asm8 < ts
654
+
655
+ def test_pickle(self, ts, tz_aware_fixture):
656
+ tz = tz_aware_fixture
657
+ tz = maybe_get_tz(tz)
658
+ ts = Timestamp._from_value_and_reso(ts._value, ts._creso, tz)
659
+ rt = tm.round_trip_pickle(ts)
660
+ assert rt._creso == ts._creso
661
+ assert rt == ts
662
+
663
+ def test_normalize(self, dt64, ts):
664
+ alt = Timestamp(dt64)
665
+ result = ts.normalize()
666
+ assert result._creso == ts._creso
667
+ assert result == alt.normalize()
668
+
669
+ def test_asm8(self, dt64, ts):
670
+ rt = ts.asm8
671
+ assert rt == dt64
672
+ assert rt.dtype == dt64.dtype
673
+
674
+ def test_to_numpy(self, dt64, ts):
675
+ res = ts.to_numpy()
676
+ assert res == dt64
677
+ assert res.dtype == dt64.dtype
678
+
679
+ def test_to_datetime64(self, dt64, ts):
680
+ res = ts.to_datetime64()
681
+ assert res == dt64
682
+ assert res.dtype == dt64.dtype
683
+
684
+ def test_timestamp(self, dt64, ts):
685
+ alt = Timestamp(dt64)
686
+ assert ts.timestamp() == alt.timestamp()
687
+
688
+ def test_to_period(self, dt64, ts):
689
+ alt = Timestamp(dt64)
690
+ assert ts.to_period("D") == alt.to_period("D")
691
+
692
+ @pytest.mark.parametrize(
693
+ "td", [timedelta(days=4), Timedelta(days=4), np.timedelta64(4, "D")]
694
+ )
695
+ def test_addsub_timedeltalike_non_nano(self, dt64, ts, td):
696
+ exp_reso = max(ts._creso, Timedelta(td)._creso)
697
+
698
+ result = ts - td
699
+ expected = Timestamp(dt64) - td
700
+ assert isinstance(result, Timestamp)
701
+ assert result._creso == exp_reso
702
+ assert result == expected
703
+
704
+ result = ts + td
705
+ expected = Timestamp(dt64) + td
706
+ assert isinstance(result, Timestamp)
707
+ assert result._creso == exp_reso
708
+ assert result == expected
709
+
710
+ result = td + ts
711
+ expected = td + Timestamp(dt64)
712
+ assert isinstance(result, Timestamp)
713
+ assert result._creso == exp_reso
714
+ assert result == expected
715
+
716
+ def test_addsub_offset(self, ts_tz):
717
+ # specifically non-Tick offset
718
+ off = offsets.YearEnd(1)
719
+ result = ts_tz + off
720
+
721
+ assert isinstance(result, Timestamp)
722
+ assert result._creso == ts_tz._creso
723
+ if ts_tz.month == 12 and ts_tz.day == 31:
724
+ assert result.year == ts_tz.year + 1
725
+ else:
726
+ assert result.year == ts_tz.year
727
+ assert result.day == 31
728
+ assert result.month == 12
729
+ assert tz_compare(result.tz, ts_tz.tz)
730
+
731
+ result = ts_tz - off
732
+
733
+ assert isinstance(result, Timestamp)
734
+ assert result._creso == ts_tz._creso
735
+ assert result.year == ts_tz.year - 1
736
+ assert result.day == 31
737
+ assert result.month == 12
738
+ assert tz_compare(result.tz, ts_tz.tz)
739
+
740
+ def test_sub_datetimelike_mismatched_reso(self, ts_tz):
741
+ # case with non-lossy rounding
742
+ ts = ts_tz
743
+
744
+ # choose a unit for `other` that doesn't match ts_tz's;
745
+ # this construction ensures we get cases with other._creso < ts._creso
746
+ # and cases with other._creso > ts._creso
747
+ unit = {
748
+ NpyDatetimeUnit.NPY_FR_us.value: "ms",
749
+ NpyDatetimeUnit.NPY_FR_ms.value: "s",
750
+ NpyDatetimeUnit.NPY_FR_s.value: "us",
751
+ }[ts._creso]
752
+ other = ts.as_unit(unit)
753
+ assert other._creso != ts._creso
754
+
755
+ result = ts - other
756
+ assert isinstance(result, Timedelta)
757
+ assert result._value == 0
758
+ assert result._creso == max(ts._creso, other._creso)
759
+
760
+ result = other - ts
761
+ assert isinstance(result, Timedelta)
762
+ assert result._value == 0
763
+ assert result._creso == max(ts._creso, other._creso)
764
+
765
+ if ts._creso < other._creso:
766
+ # Case where rounding is lossy
767
+ other2 = other + Timedelta._from_value_and_reso(1, other._creso)
768
+ exp = ts.as_unit(other.unit) - other2
769
+
770
+ res = ts - other2
771
+ assert res == exp
772
+ assert res._creso == max(ts._creso, other._creso)
773
+
774
+ res = other2 - ts
775
+ assert res == -exp
776
+ assert res._creso == max(ts._creso, other._creso)
777
+ else:
778
+ ts2 = ts + Timedelta._from_value_and_reso(1, ts._creso)
779
+ exp = ts2 - other.as_unit(ts2.unit)
780
+
781
+ res = ts2 - other
782
+ assert res == exp
783
+ assert res._creso == max(ts._creso, other._creso)
784
+ res = other - ts2
785
+ assert res == -exp
786
+ assert res._creso == max(ts._creso, other._creso)
787
+
788
+ def test_sub_timedeltalike_mismatched_reso(self, ts_tz):
789
+ # case with non-lossy rounding
790
+ ts = ts_tz
791
+
792
+ # choose a unit for `other` that doesn't match ts_tz's;
793
+ # this construction ensures we get cases with other._creso < ts._creso
794
+ # and cases with other._creso > ts._creso
795
+ unit = {
796
+ NpyDatetimeUnit.NPY_FR_us.value: "ms",
797
+ NpyDatetimeUnit.NPY_FR_ms.value: "s",
798
+ NpyDatetimeUnit.NPY_FR_s.value: "us",
799
+ }[ts._creso]
800
+ other = Timedelta(0).as_unit(unit)
801
+ assert other._creso != ts._creso
802
+
803
+ result = ts + other
804
+ assert isinstance(result, Timestamp)
805
+ assert result == ts
806
+ assert result._creso == max(ts._creso, other._creso)
807
+
808
+ result = other + ts
809
+ assert isinstance(result, Timestamp)
810
+ assert result == ts
811
+ assert result._creso == max(ts._creso, other._creso)
812
+
813
+ if ts._creso < other._creso:
814
+ # Case where rounding is lossy
815
+ other2 = other + Timedelta._from_value_and_reso(1, other._creso)
816
+ exp = ts.as_unit(other.unit) + other2
817
+ res = ts + other2
818
+ assert res == exp
819
+ assert res._creso == max(ts._creso, other._creso)
820
+ res = other2 + ts
821
+ assert res == exp
822
+ assert res._creso == max(ts._creso, other._creso)
823
+ else:
824
+ ts2 = ts + Timedelta._from_value_and_reso(1, ts._creso)
825
+ exp = ts2 + other.as_unit(ts2.unit)
826
+
827
+ res = ts2 + other
828
+ assert res == exp
829
+ assert res._creso == max(ts._creso, other._creso)
830
+ res = other + ts2
831
+ assert res == exp
832
+ assert res._creso == max(ts._creso, other._creso)
833
+
834
+ def test_addition_doesnt_downcast_reso(self):
835
+ # https://github.com/pandas-dev/pandas/pull/48748#pullrequestreview-1122635413
836
+ ts = Timestamp(year=2022, month=1, day=1, microsecond=999999).as_unit("us")
837
+ td = Timedelta(microseconds=1).as_unit("us")
838
+ res = ts + td
839
+ assert res._creso == ts._creso
840
+
841
+ def test_sub_timedelta64_mismatched_reso(self, ts_tz):
842
+ ts = ts_tz
843
+
844
+ res = ts + np.timedelta64(1, "ns")
845
+ exp = ts.as_unit("ns") + np.timedelta64(1, "ns")
846
+ assert exp == res
847
+ assert exp._creso == NpyDatetimeUnit.NPY_FR_ns.value
848
+
849
+ def test_min(self, ts):
850
+ assert ts.min <= ts
851
+ assert ts.min._creso == ts._creso
852
+ assert ts.min._value == NaT._value + 1
853
+
854
+ def test_max(self, ts):
855
+ assert ts.max >= ts
856
+ assert ts.max._creso == ts._creso
857
+ assert ts.max._value == np.iinfo(np.int64).max
858
+
859
+ def test_resolution(self, ts):
860
+ expected = Timedelta._from_value_and_reso(1, ts._creso)
861
+ result = ts.resolution
862
+ assert result == expected
863
+ assert result._creso == expected._creso
864
+
865
+ def test_out_of_ns_bounds(self):
866
+ # https://github.com/pandas-dev/pandas/issues/51060
867
+ result = Timestamp(-52700112000, unit="s")
868
+ assert result == Timestamp("0300-01-01")
869
+ assert result.to_numpy() == np.datetime64("0300-01-01T00:00:00", "s")
870
+
871
+
872
+ def test_timestamp_class_min_max_resolution():
873
+ # when accessed on the class (as opposed to an instance), we default
874
+ # to nanoseconds
875
+ assert Timestamp.min == Timestamp(NaT._value + 1)
876
+ assert Timestamp.min._creso == NpyDatetimeUnit.NPY_FR_ns.value
877
+
878
+ assert Timestamp.max == Timestamp(np.iinfo(np.int64).max)
879
+ assert Timestamp.max._creso == NpyDatetimeUnit.NPY_FR_ns.value
880
+
881
+ assert Timestamp.resolution == Timedelta(1)
882
+ assert Timestamp.resolution._creso == NpyDatetimeUnit.NPY_FR_ns.value
883
+
884
+
885
+ def test_delimited_date():
886
+ # https://github.com/pandas-dev/pandas/issues/50231
887
+ with tm.assert_produces_warning(None):
888
+ result = Timestamp("13-01-2000")
889
+ expected = Timestamp(2000, 1, 13)
890
+ assert result == expected
891
+
892
+
893
+ def test_utctimetuple():
894
+ # GH 32174
895
+ ts = Timestamp("2000-01-01", tz="UTC")
896
+ result = ts.utctimetuple()
897
+ expected = time.struct_time((2000, 1, 1, 0, 0, 0, 5, 1, 0))
898
+ assert result == expected
899
+
900
+
901
+ def test_negative_dates():
902
+ # https://github.com/pandas-dev/pandas/issues/50787
903
+ ts = Timestamp("-2000-01-01")
904
+ msg = (
905
+ " not yet supported on Timestamps which are outside the range of "
906
+ "Python's standard library. For now, please call the components you need "
907
+ r"\(such as `.year` and `.month`\) and construct your string from there.$"
908
+ )
909
+ func = "^strftime"
910
+ with pytest.raises(NotImplementedError, match=func + msg):
911
+ ts.strftime("%Y")
912
+
913
+ msg = (
914
+ " not yet supported on Timestamps which "
915
+ "are outside the range of Python's standard library. "
916
+ )
917
+ func = "^date"
918
+ with pytest.raises(NotImplementedError, match=func + msg):
919
+ ts.date()
920
+ func = "^isocalendar"
921
+ with pytest.raises(NotImplementedError, match=func + msg):
922
+ ts.isocalendar()
923
+ func = "^timetuple"
924
+ with pytest.raises(NotImplementedError, match=func + msg):
925
+ ts.timetuple()
926
+ func = "^toordinal"
927
+ with pytest.raises(NotImplementedError, match=func + msg):
928
+ ts.toordinal()