Skip to content

Commit e9cef99

Browse files
committed
Merge branch 'infer_freq' of https://github.com/rockg/pandas into rockg-infer_freq
Conflicts: doc/source/whatsnew/v0.15.2.txt
2 parents 1757d6e + 90c1fc4 commit e9cef99

File tree

3 files changed

+61
-2
lines changed

3 files changed

+61
-2
lines changed

doc/source/whatsnew/v0.15.2.txt

+28
Original file line numberDiff line numberDiff line change
@@ -63,5 +63,33 @@ Bug Fixes
6363
- Bug in slicing a multi-index with an empty list and at least one boolean indexer (:issue:`8781`)
6464
- ``io.data.Options`` now raises ``RemoteDataError`` when no expiry dates are available from Yahoo (:issue:`8761`).
6565
- ``Timedelta`` kwargs may now be numpy ints and floats (:issue:`8757`).
66+
67+
68+
69+
70+
71+
72+
73+
74+
75+
6676
- Skip testing of histogram plots for matplotlib <= 1.2 (:issue:`8648`).
77+
78+
79+
80+
81+
82+
6783
- Bug where ``get_data_google``returned object dtypes (:issue:`3995`)
84+
85+
86+
87+
88+
89+
90+
91+
92+
93+
94+
- Bug in `pd.infer_freq`/`DataFrame.inferred_freq` that prevented proper sub-daily frequency inference
95+
when the index contained DST days (:issue:`8772`).

pandas/tseries/frequencies.py

+15-2
Original file line numberDiff line numberDiff line change
@@ -698,6 +698,8 @@ def __init__(self, index, warn=True):
698698
self.index = index
699699
self.values = np.asarray(index).view('i8')
700700

701+
# This moves the values, which are implicitly in UTC, to the
702+
# the timezone so they are in local time
701703
if hasattr(index,'tz'):
702704
if index.tz is not None:
703705
self.values = tslib.tz_convert(self.values, 'UTC', index.tz)
@@ -712,10 +714,18 @@ def __init__(self, index, warn=True):
712714
@cache_readonly
713715
def deltas(self):
714716
return tslib.unique_deltas(self.values)
717+
718+
@cache_readonly
719+
def deltas_asi8(self):
720+
return tslib.unique_deltas(self.index.asi8)
715721

716722
@cache_readonly
717723
def is_unique(self):
718724
return len(self.deltas) == 1
725+
726+
@cache_readonly
727+
def is_unique_asi8(self):
728+
return len(self.deltas_asi8) == 1
719729

720730
def get_freq(self):
721731
if not self.is_monotonic or not self.index.is_unique:
@@ -725,9 +735,12 @@ def get_freq(self):
725735
if _is_multiple(delta, _ONE_DAY):
726736
return self._infer_daily_rule()
727737
else:
728-
# Possibly intraday frequency
729-
if not self.is_unique:
738+
# Possibly intraday frequency. Here we use the
739+
# original .asi8 values as the modified values
740+
# will not work around DST transitions. See #8772
741+
if not self.is_unique_asi8:
730742
return None
743+
delta = self.deltas_asi8[0]
731744
if _is_multiple(delta, _ONE_HOUR):
732745
# Hours
733746
return _maybe_add_count('H', delta / _ONE_HOUR)

pandas/tseries/tests/test_frequencies.py

+18
Original file line numberDiff line numberDiff line change
@@ -268,6 +268,24 @@ def test_infer_freq_tz(self):
268268
idx = DatetimeIndex(dates, tz=tz)
269269
self.assertEqual(idx.inferred_freq, expected)
270270

271+
def test_infer_freq_tz_transition(self):
272+
# Tests for #8772
273+
date_pairs = [['2013-11-02', '2013-11-5'], #Fall DST
274+
['2014-03-08', '2014-03-11'], #Spring DST
275+
['2014-01-01', '2014-01-03']] #Regular Time
276+
freqs = ['3H', '10T', '3601S', '3600001L', '3600000001U', '3600000000001N']
277+
278+
for tz in [None, 'Australia/Sydney', 'Asia/Tokyo', 'Europe/Paris',
279+
'US/Pacific', 'US/Eastern']:
280+
for date_pair in date_pairs:
281+
for freq in freqs:
282+
idx = date_range(date_pair[0], date_pair[1], freq=freq, tz=tz)
283+
print(idx)
284+
self.assertEqual(idx.inferred_freq, freq)
285+
286+
index = date_range("2013-11-03", periods=5, freq="3H").tz_localize("America/Chicago")
287+
self.assertIsNone(index.inferred_freq)
288+
271289
def test_not_monotonic(self):
272290
rng = _dti(['1/31/2000', '1/31/2001', '1/31/2002'])
273291
rng = rng[::-1]

0 commit comments

Comments
 (0)