32
32
from pandas .core import ops
33
33
34
34
from pandas .tseries .frequencies import to_offset
35
- from pandas .tseries .offsets import Tick , Day , generate_range
35
+ from pandas .tseries .offsets import Tick , generate_range
36
36
37
37
from pandas .core .arrays import datetimelike as dtl
38
38
@@ -239,56 +239,33 @@ def _generate_range(cls, start, end, periods, freq, tz=None,
239
239
start , end , _normalized = _maybe_normalize_endpoints (start , end ,
240
240
normalize )
241
241
242
- tz , inferred_tz = _infer_tz_from_endpoints (start , end , tz )
243
-
244
- if hasattr ( freq , 'delta' ) and freq != Day () :
245
- # sub-Day Tick
246
- if inferred_tz is None and tz is not None :
247
- # naive dates
248
- if start is not None and start . tz is None :
249
- start = start . tz_localize ( tz , ambiguous = False )
250
-
251
- if end is not None and end . tz is None :
252
- end = end . tz_localize ( tz , ambiguous = False )
253
-
254
- if start and end :
255
- if start .tz is None and end .tz is not None :
256
- start = start . tz_localize ( end . tz , ambiguous = False )
257
-
258
- if end .tz is None and start .tz is not None :
259
- end = end . tz_localize ( start . tz , ambiguous = False )
260
-
242
+ tz , _ = _infer_tz_from_endpoints (start , end , tz )
243
+
244
+ if tz is not None :
245
+ # Localize the start and end arguments
246
+ start = _maybe_localize_point (
247
+ start , getattr ( start , 'tz' , None ), start , freq , tz
248
+ )
249
+ end = _maybe_localize_point (
250
+ end , getattr ( end , 'tz' , None ), end , freq , tz
251
+ )
252
+ if start and end :
253
+ # Make sure start and end have the same tz
254
+ start = _maybe_localize_point (
255
+ start , start .tz , end .tz , freq , tz
256
+ )
257
+ end = _maybe_localize_point (
258
+ end , end .tz , start .tz , freq , tz
259
+ )
260
+ if freq is not None :
261
261
if cls ._use_cached_range (freq , _normalized , start , end ):
262
+ # Currently always False; never hit
263
+ # Should be reimplemented as apart of GH 17914
262
264
index = cls ._cached_range (start , end , periods = periods ,
263
265
freq = freq )
264
266
else :
265
267
index = _generate_regular_range (cls , start , end , periods , freq )
266
268
267
- else :
268
-
269
- if tz is not None :
270
- # naive dates
271
- if start is not None and start .tz is not None :
272
- start = start .replace (tzinfo = None )
273
-
274
- if end is not None and end .tz is not None :
275
- end = end .replace (tzinfo = None )
276
-
277
- if start and end :
278
- if start .tz is None and end .tz is not None :
279
- end = end .replace (tzinfo = None )
280
-
281
- if end .tz is None and start .tz is not None :
282
- start = start .replace (tzinfo = None )
283
-
284
- if freq is not None :
285
- if cls ._use_cached_range (freq , _normalized , start , end ):
286
- index = cls ._cached_range (start , end , periods = periods ,
287
- freq = freq )
288
- else :
289
- index = _generate_regular_range (cls , start , end ,
290
- periods , freq )
291
-
292
269
if tz is not None and getattr (index , 'tz' , None ) is None :
293
270
arr = conversion .tz_localize_to_utc (
294
271
ensure_int64 (index .values ),
@@ -302,12 +279,12 @@ def _generate_range(cls, start, end, periods, freq, tz=None,
302
279
start = start .tz_localize (tz ).asm8
303
280
if end is not None :
304
281
end = end .tz_localize (tz ).asm8
305
- else :
306
- # Create a linearly spaced date_range in local time
307
- start = start . tz_localize ( tz )
308
- end = end . tz_localize ( tz )
309
- arr = np . linspace ( start . value , end . value , periods )
310
- index = cls . _simple_new ( arr . astype ( 'M8[ns]' ), freq = None , tz = tz )
282
+ else :
283
+ # Create a linearly spaced date_range in local time
284
+ arr = np . linspace ( start . value , end . value , periods )
285
+ index = cls . _simple_new (
286
+ arr . astype ( 'M8[ns]' , copy = False ), freq = None , tz = tz
287
+ )
311
288
312
289
if not left_closed and len (index ) and index [0 ] == start :
313
290
index = index [1 :]
@@ -1256,10 +1233,10 @@ def _generate_regular_range(cls, start, end, periods, freq):
1256
1233
data = cls ._simple_new (data .view (_NS_DTYPE ), None , tz = tz )
1257
1234
else :
1258
1235
tz = None
1236
+ # start and end should have the same timezone by this point
1259
1237
if isinstance (start , Timestamp ):
1260
1238
tz = start .tz
1261
-
1262
- if isinstance (end , Timestamp ):
1239
+ elif isinstance (end , Timestamp ):
1263
1240
tz = end .tz
1264
1241
1265
1242
xdr = generate_range (start = start , end = end ,
@@ -1330,3 +1307,32 @@ def _maybe_normalize_endpoints(start, end, normalize):
1330
1307
_normalized = _normalized and end .time () == _midnight
1331
1308
1332
1309
return start , end , _normalized
1310
+
1311
+
1312
+ def _maybe_localize_point (ts , is_none , is_not_none , freq , tz ):
1313
+ """
1314
+ Localize a start or end Timestamp to the timezone of the corresponding
1315
+ start or end Timestamp
1316
+
1317
+ Parameters
1318
+ ----------
1319
+ ts : start or end Timestamp to potentially localize
1320
+ is_none : argument that should be None
1321
+ is_not_none : argument that should not be None
1322
+ freq : Tick, DateOffset, or None
1323
+ tz : str, timezone object or None
1324
+
1325
+ Returns
1326
+ -------
1327
+ ts : Timestamp
1328
+ """
1329
+ # Make sure start and end are timezone localized if:
1330
+ # 1) freq = a Timedelta-like frequency (Tick)
1331
+ # 2) freq = None i.e. generating a linspaced range
1332
+ if isinstance (freq , Tick ) or freq is None :
1333
+ localize_args = {'tz' : tz , 'ambiguous' : False }
1334
+ else :
1335
+ localize_args = {'tz' : None }
1336
+ if is_none is None and is_not_none is not None :
1337
+ ts = ts .tz_localize (** localize_args )
1338
+ return ts
0 commit comments