Skip to content

Commit 4062597

Browse files
author
Matt Roeschke
committed
Modify and simplify logic of date_range
1 parent 9605aa1 commit 4062597

File tree

2 files changed

+45
-71
lines changed

2 files changed

+45
-71
lines changed

pandas/core/arrays/datetimes.py

Lines changed: 42 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@
3232
from pandas.core import ops
3333

3434
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
3636

3737
from pandas.core.arrays import datetimelike as dtl
3838

@@ -239,75 +239,58 @@ def _generate_range(cls, start, end, periods, freq, tz=None,
239239
start, end, _normalized = _maybe_normalize_endpoints(start, end,
240240
normalize)
241241

242-
tz, inferred_tz = _infer_tz_from_endpoints(start, end, tz)
242+
tz, _ = _infer_tz_from_endpoints(start, end, tz)
243243

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)
244+
# If we have a Timedelta-like frequency (Tick) make sure tz
245+
# is set before generating the range. For relative frequencies,
246+
# generate the range with naive dates.
247+
localize_args = {'tz': None}
248+
if isinstance(freq, Tick):
249+
localize_args = {'tz': tz, 'ambiguous': False}
250+
if tz is not None:
251+
# Localize the start and end arguments
252+
if start is not None and start.tz is None:
253+
start = start.tz_localize(**localize_args)
250254

251-
if end is not None and end.tz is None:
252-
end = end.tz_localize(tz, ambiguous=False)
255+
if end is not None and end.tz is None:
256+
end = end.tz_localize(**localize_args)
253257

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)
258+
if start and end:
259+
# Make sure start and end have the same tz
260+
if start.tz is None and end.tz is not None:
261+
start = start.tz_localize(**localize_args)
257262

258-
if end.tz is None and start.tz is not None:
259-
end = end.tz_localize(start.tz, ambiguous=False)
263+
if end.tz is None and start.tz is not None:
264+
end = end.tz_localize(**localize_args)
260265

266+
if freq is not None:
261267
if cls._use_cached_range(freq, _normalized, start, end):
268+
# Currently always False; never hit
262269
index = cls._cached_range(start, end, periods=periods,
263270
freq=freq)
264271
else:
265272
index = _generate_regular_range(cls, start, end, periods, freq)
266273

267-
else:
274+
# TODO: Is this ever hit?
275+
if tz is not None and getattr(index, 'tz', None) is None:
276+
arr = conversion.tz_localize_to_utc(
277+
ensure_int64(index.values),
278+
tz, ambiguous=ambiguous)
268279

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-
if tz is not None and getattr(index, 'tz', None) is None:
293-
arr = conversion.tz_localize_to_utc(
294-
ensure_int64(index.values),
295-
tz, ambiguous=ambiguous)
296-
297-
index = cls(arr)
298-
299-
# index is localized datetime64 array -> have to convert
300-
# start/end as well to compare
301-
if start is not None:
302-
start = start.tz_localize(tz).asm8
303-
if end is not None:
304-
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)
280+
index = cls(arr)
281+
282+
# index is localized datetime64 array -> have to convert
283+
# start/end as well to compare
284+
if start is not None:
285+
start = start.tz_localize(tz).asm8
286+
if end is not None:
287+
end = end.tz_localize(tz).asm8
288+
else:
289+
# Create a linearly spaced date_range in local time
290+
start = start.tz_localize(tz)
291+
end = end.tz_localize(tz)
292+
arr = np.linspace(start.value, end.value, periods)
293+
index = cls._simple_new(arr.astype('M8[ns]'), freq=None, tz=tz)
311294

312295
if not left_closed and len(index) and index[0] == start:
313296
index = index[1:]
@@ -1255,12 +1238,10 @@ def _generate_regular_range(cls, start, end, periods, freq):
12551238
data = cls._simple_new(data.view(_NS_DTYPE), None, tz=tz)
12561239
else:
12571240
tz = None
1241+
# Start and end should have the same timestamp by this point
12581242
if isinstance(start, Timestamp):
12591243
tz = start.tz
12601244

1261-
if isinstance(end, Timestamp):
1262-
tz = end.tz
1263-
12641245
xdr = generate_range(start=start, end=end,
12651246
periods=periods, offset=freq)
12661247

pandas/tseries/offsets.py

Lines changed: 3 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2348,7 +2348,7 @@ class Nano(Tick):
23482348

23492349

23502350
def generate_range(start=None, end=None, periods=None,
2351-
offset=BDay(), time_rule=None):
2351+
offset=BDay()):
23522352
"""
23532353
Generates a sequence of dates corresponding to the specified time
23542354
offset. Similar to dateutil.rrule except uses pandas DateOffset
@@ -2358,27 +2358,20 @@ def generate_range(start=None, end=None, periods=None,
23582358
----------
23592359
start : datetime (default None)
23602360
end : datetime (default None)
2361-
periods : int, optional
2362-
time_rule : (legacy) name of DateOffset object to be used, optional
2363-
Corresponds with names expected by tseries.frequencies.get_offset
2361+
periods : int, (default None)
2362+
offset : DateOffset, (default BDay())
23642363
23652364
Notes
23662365
-----
23672366
* This method is faster for generating weekdays than dateutil.rrule
23682367
* At least two of (start, end, periods) must be specified.
23692368
* If both start and end are specified, the returned dates will
23702369
satisfy start <= date <= end.
2371-
* If both time_rule and offset are specified, time_rule supersedes offset.
23722370
23732371
Returns
23742372
-------
23752373
dates : generator object
2376-
23772374
"""
2378-
if time_rule is not None:
2379-
from pandas.tseries.frequencies import get_offset
2380-
2381-
offset = get_offset(time_rule)
23822375

23832376
start = to_datetime(start)
23842377
end = to_datetime(end)

0 commit comments

Comments
 (0)