@@ -42,24 +42,37 @@ def create_index_with_nan(self, closed='right'):
42
42
np .where (mask , np .arange (10 ), np .nan ),
43
43
np .where (mask , np .arange (1 , 11 ), np .nan ), closed = closed )
44
44
45
- def test_constructors (self , closed , name ):
46
- left , right = Index ([0 , 1 , 2 , 3 ]), Index ([1 , 2 , 3 , 4 ])
45
+ @pytest .mark .parametrize ('data' , [
46
+ Index ([0 , 1 , 2 , 3 , 4 ]),
47
+ Index (list ('abcde' )),
48
+ date_range ('2017-01-01' , periods = 5 ),
49
+ date_range ('2017-01-01' , periods = 5 , tz = 'US/Eastern' ),
50
+ timedelta_range ('1 day' , periods = 5 )])
51
+ def test_constructors (self , data , closed , name ):
52
+ left , right = data [:- 1 ], data [1 :]
47
53
ivs = [Interval (l , r , closed = closed ) for l , r in lzip (left , right )]
48
54
expected = IntervalIndex ._simple_new (
49
55
left = left , right = right , closed = closed , name = name )
50
56
57
+ # validate expected
58
+ assert expected .closed == closed
59
+ assert expected .name == name
60
+ assert expected .dtype .subtype == data .dtype
61
+ tm .assert_index_equal (expected .left , data [:- 1 ])
62
+ tm .assert_index_equal (expected .right , data [1 :])
63
+
64
+ # validated constructors
51
65
result = IntervalIndex (ivs , name = name )
52
66
tm .assert_index_equal (result , expected )
53
67
54
68
result = IntervalIndex .from_intervals (ivs , name = name )
55
69
tm .assert_index_equal (result , expected )
56
70
57
- result = IntervalIndex .from_breaks (
58
- np .arange (5 ), closed = closed , name = name )
71
+ result = IntervalIndex .from_breaks (data , closed = closed , name = name )
59
72
tm .assert_index_equal (result , expected )
60
73
61
74
result = IntervalIndex .from_arrays (
62
- left . values , right . values , closed = closed , name = name )
75
+ left , right , closed = closed , name = name )
63
76
tm .assert_index_equal (result , expected )
64
77
65
78
result = IntervalIndex .from_tuples (
@@ -186,6 +199,9 @@ def test_constructors_errors(self):
186
199
IntervalIndex .from_intervals ([Interval (0 , 1 ),
187
200
Interval (1 , 2 , closed = 'left' )])
188
201
202
+ with tm .assert_raises_regex (ValueError , msg ):
203
+ IntervalIndex ([Interval (0 , 1 ), Interval (2 , 3 , closed = 'left' )])
204
+
189
205
with tm .assert_raises_regex (ValueError , msg ):
190
206
Index ([Interval (0 , 1 ), Interval (2 , 3 , closed = 'left' )])
191
207
@@ -209,26 +225,24 @@ def test_constructors_errors(self):
209
225
with tm .assert_raises_regex (ValueError , msg ):
210
226
IntervalIndex .from_arrays (range (10 , - 1 , - 1 ), range (9 , - 2 , - 1 ))
211
227
212
- def test_constructors_datetimelike (self , closed ):
228
+ @pytest .mark .parametrize ('tz_left, tz_right' , [
229
+ (None , 'UTC' ), ('UTC' , None ), ('UTC' , 'US/Eastern' )])
230
+ def test_constructors_errors_tz (self , tz_left , tz_right ):
231
+ # GH 18537
232
+ left = date_range ('2017-01-01' , periods = 4 , tz = tz_left )
233
+ right = date_range ('2017-01-02' , periods = 4 , tz = tz_right )
213
234
214
- # DTI / TDI
215
- for idx in [pd .date_range ('20130101' , periods = 5 ),
216
- pd .timedelta_range ('1 day' , periods = 5 )]:
217
- result = IntervalIndex .from_breaks (idx , closed = closed )
218
- expected = IntervalIndex .from_breaks (idx .values , closed = closed )
219
- tm .assert_index_equal (result , expected )
220
-
221
- expected_scalar_type = type (idx [0 ])
222
- i = result [0 ]
223
- assert isinstance (i .left , expected_scalar_type )
224
- assert isinstance (i .right , expected_scalar_type )
235
+ # don't need to check IntervalIndex(...) or from_intervals, since
236
+ # mixed tz are disallowed at the Interval level
237
+ with pytest .raises (ValueError ):
238
+ IntervalIndex .from_arrays (left , right )
225
239
226
- def test_constructors_error (self ):
240
+ with pytest .raises (ValueError ):
241
+ IntervalIndex .from_tuples (lzip (left , right ))
227
242
228
- # non-intervals
229
- def f ():
230
- IntervalIndex .from_intervals ([0.997 , 4.0 ])
231
- pytest .raises (TypeError , f )
243
+ with pytest .raises (ValueError ):
244
+ breaks = left .tolist () + [right [- 1 ]]
245
+ IntervalIndex .from_breaks (breaks )
232
246
233
247
def test_properties (self , closed ):
234
248
index = self .create_index (closed = closed )
@@ -964,23 +978,46 @@ def test_sort_values(self, closed):
964
978
expected = IntervalIndex ([np .nan , Interval (1 , 2 ), Interval (0 , 1 )])
965
979
tm .assert_index_equal (result , expected )
966
980
967
- def test_datetime (self ):
968
- dates = date_range ('2000' , periods = 3 )
969
- idx = IntervalIndex .from_breaks (dates )
970
-
971
- tm .assert_index_equal (idx .left , dates [:2 ])
972
- tm .assert_index_equal (idx .right , dates [- 2 :])
973
-
974
- expected = date_range ('2000-01-01T12:00' , periods = 2 )
975
- tm .assert_index_equal (idx .mid , expected )
976
-
977
- assert Timestamp ('2000-01-01T12' ) not in idx
978
- assert Timestamp ('2000-01-01T12' ) not in idx
979
-
980
- target = date_range ('1999-12-31T12:00' , periods = 7 , freq = '12H' )
981
- actual = idx .get_indexer (target )
981
+ @pytest .mark .parametrize ('tz' , [None , 'US/Eastern' ])
982
+ def test_datetime (self , tz ):
983
+ start = Timestamp ('2000-01-01' , tz = tz )
984
+ dates = date_range (start = start , periods = 10 )
985
+ index = IntervalIndex .from_breaks (dates )
986
+
987
+ # test mid
988
+ start = Timestamp ('2000-01-01T12:00' , tz = tz )
989
+ expected = date_range (start = start , periods = 9 )
990
+ tm .assert_index_equal (index .mid , expected )
991
+
992
+ # __contains__ doesn't check individual points
993
+ assert Timestamp ('2000-01-01' , tz = tz ) not in index
994
+ assert Timestamp ('2000-01-01T12' , tz = tz ) not in index
995
+ assert Timestamp ('2000-01-02' , tz = tz ) not in index
996
+ iv_true = Interval (Timestamp ('2000-01-01T08' , tz = tz ),
997
+ Timestamp ('2000-01-01T18' , tz = tz ))
998
+ iv_false = Interval (Timestamp ('1999-12-31' , tz = tz ),
999
+ Timestamp ('2000-01-01' , tz = tz ))
1000
+ assert iv_true in index
1001
+ assert iv_false not in index
1002
+
1003
+ # .contains does check individual points
1004
+ assert not index .contains (Timestamp ('2000-01-01' , tz = tz ))
1005
+ assert index .contains (Timestamp ('2000-01-01T12' , tz = tz ))
1006
+ assert index .contains (Timestamp ('2000-01-02' , tz = tz ))
1007
+ assert index .contains (iv_true )
1008
+ assert not index .contains (iv_false )
1009
+
1010
+ # test get_indexer
1011
+ start = Timestamp ('1999-12-31T12:00' , tz = tz )
1012
+ target = date_range (start = start , periods = 7 , freq = '12H' )
1013
+ actual = index .get_indexer (target )
1014
+ expected = np .array ([- 1 , - 1 , 0 , 0 , 1 , 1 , 2 ], dtype = 'intp' )
1015
+ tm .assert_numpy_array_equal (actual , expected )
982
1016
983
- expected = np .array ([- 1 , - 1 , 0 , 0 , 1 , 1 , - 1 ], dtype = 'intp' )
1017
+ start = Timestamp ('2000-01-08T18:00' , tz = tz )
1018
+ target = date_range (start = start , periods = 7 , freq = '6H' )
1019
+ actual = index .get_indexer (target )
1020
+ expected = np .array ([7 , 7 , 8 , 8 , 8 , 8 , - 1 ], dtype = 'intp' )
984
1021
tm .assert_numpy_array_equal (actual , expected )
985
1022
986
1023
def test_append (self , closed ):
@@ -1079,9 +1116,11 @@ def test_construction_from_numeric(self, closed, name):
1079
1116
closed = closed )
1080
1117
tm .assert_index_equal (result , expected )
1081
1118
1082
- def test_construction_from_timestamp (self , closed , name ):
1119
+ @pytest .mark .parametrize ('tz' , [None , 'US/Eastern' ])
1120
+ def test_construction_from_timestamp (self , closed , name , tz ):
1083
1121
# combinations of start/end/periods without freq
1084
- start , end = Timestamp ('2017-01-01' ), Timestamp ('2017-01-06' )
1122
+ start = Timestamp ('2017-01-01' , tz = tz )
1123
+ end = Timestamp ('2017-01-06' , tz = tz )
1085
1124
breaks = date_range (start = start , end = end )
1086
1125
expected = IntervalIndex .from_breaks (breaks , name = name , closed = closed )
1087
1126
@@ -1099,7 +1138,8 @@ def test_construction_from_timestamp(self, closed, name):
1099
1138
1100
1139
# combinations of start/end/periods with fixed freq
1101
1140
freq = '2D'
1102
- start , end = Timestamp ('2017-01-01' ), Timestamp ('2017-01-07' )
1141
+ start = Timestamp ('2017-01-01' , tz = tz )
1142
+ end = Timestamp ('2017-01-07' , tz = tz )
1103
1143
breaks = date_range (start = start , end = end , freq = freq )
1104
1144
expected = IntervalIndex .from_breaks (breaks , name = name , closed = closed )
1105
1145
@@ -1116,14 +1156,15 @@ def test_construction_from_timestamp(self, closed, name):
1116
1156
tm .assert_index_equal (result , expected )
1117
1157
1118
1158
# output truncates early if freq causes end to be skipped.
1119
- end = Timestamp ('2017-01-08' )
1159
+ end = Timestamp ('2017-01-08' , tz = tz )
1120
1160
result = interval_range (start = start , end = end , freq = freq , name = name ,
1121
1161
closed = closed )
1122
1162
tm .assert_index_equal (result , expected )
1123
1163
1124
1164
# combinations of start/end/periods with non-fixed freq
1125
1165
freq = 'M'
1126
- start , end = Timestamp ('2017-01-01' ), Timestamp ('2017-12-31' )
1166
+ start = Timestamp ('2017-01-01' , tz = tz )
1167
+ end = Timestamp ('2017-12-31' , tz = tz )
1127
1168
breaks = date_range (start = start , end = end , freq = freq )
1128
1169
expected = IntervalIndex .from_breaks (breaks , name = name , closed = closed )
1129
1170
@@ -1140,7 +1181,7 @@ def test_construction_from_timestamp(self, closed, name):
1140
1181
tm .assert_index_equal (result , expected )
1141
1182
1142
1183
# output truncates early if freq causes end to be skipped.
1143
- end = Timestamp ('2018-01-15' )
1184
+ end = Timestamp ('2018-01-15' , tz = tz )
1144
1185
result = interval_range (start = start , end = end , freq = freq , name = name ,
1145
1186
closed = closed )
1146
1187
tm .assert_index_equal (result , expected )
@@ -1308,6 +1349,13 @@ def test_errors(self):
1308
1349
with tm .assert_raises_regex (ValueError , msg ):
1309
1350
interval_range (end = Timedelta ('1 day' ), periods = 10 , freq = 'foo' )
1310
1351
1352
+ # mixed tz
1353
+ start = Timestamp ('2017-01-01' , tz = 'US/Eastern' )
1354
+ end = Timestamp ('2017-01-07' , tz = 'US/Pacific' )
1355
+ msg = 'Start and end cannot both be tz-aware with different timezones'
1356
+ with tm .assert_raises_regex (TypeError , msg ):
1357
+ interval_range (start = start , end = end )
1358
+
1311
1359
1312
1360
class TestIntervalTree (object ):
1313
1361
def setup_method (self , method ):
0 commit comments