diff --git a/pandas/io/tests/data/legacy_pickle/0.13.0/0.13.0_x86_64_darwin_2.7.6.pickle b/pandas/io/tests/data/legacy_pickle/0.13.0/0.13.0_x86_64_darwin_2.7.6.pickle new file mode 100644 index 0000000000000..4f5bdada3c7da Binary files /dev/null and b/pandas/io/tests/data/legacy_pickle/0.13.0/0.13.0_x86_64_darwin_2.7.6.pickle differ diff --git a/pandas/io/tests/data/legacy_pickle/0.14.0/0.14.0_x86_64_darwin_2.7.6.pickle b/pandas/io/tests/data/legacy_pickle/0.14.0/0.14.0_x86_64_darwin_2.7.6.pickle new file mode 100644 index 0000000000000..1b1652fc03c27 Binary files /dev/null and b/pandas/io/tests/data/legacy_pickle/0.14.0/0.14.0_x86_64_darwin_2.7.6.pickle differ diff --git a/pandas/io/tests/generate_legacy_pickles.py b/pandas/io/tests/generate_legacy_pickles.py index 48d0fd57d831b..3a0386c7660d4 100644 --- a/pandas/io/tests/generate_legacy_pickles.py +++ b/pandas/io/tests/generate_legacy_pickles.py @@ -58,7 +58,7 @@ def create_data(): from pandas import (Series,TimeSeries,DataFrame,Panel, SparseSeries,SparseTimeSeries,SparseDataFrame,SparsePanel, Index,MultiIndex,PeriodIndex, - date_range,bdate_range,Timestamp) + date_range,period_range,bdate_range,Timestamp) nan = np.nan data = { @@ -70,7 +70,9 @@ def create_data(): } index = dict(int = Index(np.arange(10)), - date = date_range('20130101',periods=10)) + date = date_range('20130101',periods=10), + period = period_range('2013-01-01', freq='M', periods=10)) + mi = dict(reg2 = MultiIndex.from_tuples(tuple(zip(*[['bar', 'bar', 'baz', 'baz', 'foo', 'foo', 'qux', 'qux'], ['one', 'two', 'one', 'two', 'one', 'two', 'one', 'two']])), names=['first', 'second'])) diff --git a/pandas/tseries/frequencies.py b/pandas/tseries/frequencies.py index 441a5e8a99c78..fe61e5f0acd9b 100644 --- a/pandas/tseries/frequencies.py +++ b/pandas/tseries/frequencies.py @@ -30,20 +30,40 @@ class FreqGroup(object): class Resolution(object): - RESO_US = 0 - RESO_SEC = 1 - RESO_MIN = 2 - RESO_HR = 3 - RESO_DAY = 4 + RESO_US = tslib.US_RESO + RESO_MS = tslib.MS_RESO + RESO_SEC = tslib.S_RESO + RESO_MIN = tslib.T_RESO + RESO_HR = tslib.H_RESO + RESO_DAY = tslib.D_RESO + + _reso_str_map = { + RESO_US: 'microsecond', + RESO_MS: 'millisecond', + RESO_SEC: 'second', + RESO_MIN: 'minute', + RESO_HR: 'hour', + RESO_DAY: 'day'} + + _reso_period_map = { + 'year': 'A', + 'quarter': 'Q', + 'month': 'M', + 'day': 'D', + 'hour': 'H', + 'minute': 'T', + 'second': 'S', + 'millisecond': 'L', + 'microsecond': 'U', + 'nanosecond': 'N'} @classmethod def get_str(cls, reso): - return {cls.RESO_US: 'microsecond', - cls.RESO_SEC: 'second', - cls.RESO_MIN: 'minute', - cls.RESO_HR: 'hour', - cls.RESO_DAY: 'day'}.get(reso, 'day') + return cls._reso_str_map.get(reso, 'day') + @classmethod + def get_freq(cls, resostr): + return cls._reso_period_map[resostr] def get_reso_string(reso): return Resolution.get_str(reso) @@ -571,22 +591,9 @@ def _period_alias_dictionary(): return alias_dict -_reso_period_map = { - "year": "A", - "quarter": "Q", - "month": "M", - "day": "D", - "hour": "H", - "minute": "T", - "second": "S", - "millisecond": "L", - "microsecond": "U", - "nanosecond": "N", -} - def _infer_period_group(freqstr): - return _period_group(_reso_period_map[freqstr]) + return _period_group(Resolution._reso_period_map[freqstr]) def _period_group(freqstr): diff --git a/pandas/tseries/period.py b/pandas/tseries/period.py index 77e9677f0b723..cceac61f392a8 100644 --- a/pandas/tseries/period.py +++ b/pandas/tseries/period.py @@ -111,8 +111,14 @@ def __init__(self, value=None, freq=None, ordinal=None, elif isinstance(value, compat.string_types) or com.is_integer(value): if com.is_integer(value): value = str(value) + value = value.upper() - dt, freq = _get_date_and_freq(value, freq) + dt, _, reso = parse_time_string(value, freq) + if freq is None: + try: + freq = _freq_mod.Resolution.get_freq(reso) + except KeyError: + raise ValueError("Invalid frequency or could not infer: %s" % reso) elif isinstance(value, datetime): dt = value @@ -451,36 +457,6 @@ def strftime(self, fmt): return tslib.period_format(self.ordinal, base, fmt) -def _get_date_and_freq(value, freq): - value = value.upper() - dt, _, reso = parse_time_string(value, freq) - - if freq is None: - if reso == 'year': - freq = 'A' - elif reso == 'quarter': - freq = 'Q' - elif reso == 'month': - freq = 'M' - elif reso == 'day': - freq = 'D' - elif reso == 'hour': - freq = 'H' - elif reso == 'minute': - freq = 'T' - elif reso == 'second': - freq = 'S' - elif reso == 'microsecond': - if dt.microsecond % 1000 == 0: - freq = 'L' - else: - freq = 'U' - else: - raise ValueError("Invalid frequency or could not infer: %s" % reso) - - return dt, freq - - def _get_ordinals(data, freq): f = lambda x: Period(x, freq=freq).ordinal if isinstance(data[0], Period): diff --git a/pandas/tseries/tests/test_period.py b/pandas/tseries/tests/test_period.py index c4bac4b9b14f0..42edb799b4c89 100644 --- a/pandas/tseries/tests/test_period.py +++ b/pandas/tseries/tests/test_period.py @@ -227,6 +227,14 @@ def test_period_constructor(self): i2 = Period(datetime(2007, 1, 1), freq='M') self.assertEqual(i1, i2) + i1 = Period('2007-01-01 09:00:00.001') + expected = Period(datetime(2007, 1, 1, 9, 0, 0, 1000), freq='L') + self.assertEqual(i1, expected) + + i1 = Period('2007-01-01 09:00:00.00101') + expected = Period(datetime(2007, 1, 1, 9, 0, 0, 1010), freq='U') + self.assertEqual(i1, expected) + self.assertRaises(ValueError, Period, ordinal=200701) self.assertRaises(ValueError, Period, '2007-1-1', freq='X') diff --git a/pandas/tseries/tests/test_tslib.py b/pandas/tseries/tests/test_tslib.py index 72ab9141609b4..82f05a0de4588 100644 --- a/pandas/tseries/tests/test_tslib.py +++ b/pandas/tseries/tests/test_tslib.py @@ -476,6 +476,17 @@ def test_addition_subtraction_preserve_frequency(self): self.assertEqual((timestamp_instance + timedelta64_instance).freq, original_freq) self.assertEqual((timestamp_instance - timedelta64_instance).freq, original_freq) + def test_resolution(self): + + for freq, expected in zip(['A', 'Q', 'M', 'D', 'H', 'T', 'S', 'L', 'U'], + [tslib.D_RESO, tslib.D_RESO, tslib.D_RESO, tslib.D_RESO, + tslib.H_RESO, tslib.T_RESO,tslib.S_RESO, tslib.MS_RESO, tslib.US_RESO]): + for tz in [None, 'Asia/Tokyo', 'US/Eastern']: + idx = date_range(start='2013-04-01', periods=30, freq=freq, tz=tz) + result = tslib.resolution(idx.asi8, idx.tz) + self.assertEqual(result, expected) + + if __name__ == '__main__': nose.runmodule(argv=[__file__, '-vvs', '-x', '--pdb', '--pdb-failure'], exit=False) diff --git a/pandas/tseries/tools.py b/pandas/tseries/tools.py index f8043b23a58af..b4ab813d3debe 100644 --- a/pandas/tseries/tools.py +++ b/pandas/tseries/tools.py @@ -508,8 +508,11 @@ def dateutil_parse(timestr, default, if reso is None: raise ValueError("Cannot parse date.") - if reso == 'microsecond' and repl['microsecond'] == 0: - reso = 'second' + if reso == 'microsecond': + if repl['microsecond'] == 0: + reso = 'second' + elif repl['microsecond'] % 1000 == 0: + reso = 'millisecond' ret = default.replace(**repl) if res.weekday is not None and not res.day: diff --git a/pandas/tslib.pyx b/pandas/tslib.pyx index 39d80521fbdb5..090b49bde68a6 100644 --- a/pandas/tslib.pyx +++ b/pandas/tslib.pyx @@ -3372,13 +3372,16 @@ cpdef resolution(ndarray[int64_t] stamps, tz=None): return reso US_RESO = 0 -S_RESO = 1 -T_RESO = 2 -H_RESO = 3 -D_RESO = 4 +MS_RESO = 1 +S_RESO = 2 +T_RESO = 3 +H_RESO = 4 +D_RESO = 5 cdef inline int _reso_stamp(pandas_datetimestruct *dts): if dts.us != 0: + if dts.us % 1000 == 0: + return MS_RESO return US_RESO elif dts.sec != 0: return S_RESO