diff --git a/RELEASE.rst b/RELEASE.rst index 4f82f7b458737..977491b554cd8 100644 --- a/RELEASE.rst +++ b/RELEASE.rst @@ -69,6 +69,8 @@ pandas 0.11.1 - support python3 (via ``PyTables 3.0.0``) (GH3750_) - Add modulo operator to Series, DataFrame - Add ``date`` method to DatetimeIndex + - Timestamp.min and Timestamp.max now represent valid Timestamp instances instead + of the default datetime.min and datetime.max (respectively). - Simplified the API and added a describe method to Categorical - ``melt`` now accepts the optional parameters ``var_name`` and ``value_name`` to specify custom column names of the returned DataFrame (GH3649_), diff --git a/doc/source/gotchas.rst b/doc/source/gotchas.rst index 45369cb7ddb08..0b736d8ddbe11 100644 --- a/doc/source/gotchas.rst +++ b/doc/source/gotchas.rst @@ -271,9 +271,10 @@ can be represented using a 64-bit integer is limited to approximately 584 years: .. ipython:: python - begin = Timestamp(-9223285636854775809L) + begin = Timestamp.min begin - end = Timestamp(np.iinfo(np.int64).max) + + end = Timestamp.max end If you need to represent time series data outside the nanosecond timespan, use diff --git a/doc/source/v0.11.1.txt b/doc/source/v0.11.1.txt index dfc36258a680f..d5357da16d2bb 100644 --- a/doc/source/v0.11.1.txt +++ b/doc/source/v0.11.1.txt @@ -289,8 +289,12 @@ Enhancements dff.groupby('B').filter(lambda x: len(x) > 2, dropna=False) - Series and DataFrame hist methods now take a ``figsize`` argument (GH3834_) + - DatetimeIndexes no longer try to convert mixed-integer indexes during join operations (GH3877_) + + - Timestamp.min and Timestamp.max now represent valid Timestamp instances instead + of the default datetime.min and datetime.max (respectively). Bug Fixes diff --git a/pandas/tests/test_tseries.py b/pandas/tests/test_tseries.py index eaeb3325685ec..54c00e798f08a 100644 --- a/pandas/tests/test_tseries.py +++ b/pandas/tests/test_tseries.py @@ -2,7 +2,7 @@ from numpy import nan import numpy as np -from pandas import Index, isnull +from pandas import Index, isnull, Timestamp from pandas.util.testing import assert_almost_equal import pandas.util.testing as common import pandas.lib as lib @@ -683,6 +683,22 @@ def test_int_index(self): expected = arr.sum(1) assert_almost_equal(result, expected) + +class TestTsUtil(unittest.TestCase): + def test_min_valid(self): + # Ensure that Timestamp.min is a valid Timestamp + Timestamp(Timestamp.min) + + def test_max_valid(self): + # Ensure that Timestamp.max is a valid Timestamp + Timestamp(Timestamp.max) + + def test_to_datetime_bijective(self): + # Ensure that converting to datetime and back only loses precision + # by going from nanoseconds to microseconds. + self.assertEqual(Timestamp(Timestamp.max.to_pydatetime()).value/1000, Timestamp.max.value/1000) + self.assertEqual(Timestamp(Timestamp.min.to_pydatetime()).value/1000, Timestamp.min.value/1000) + if __name__ == '__main__': import nose nose.runmodule(argv=[__file__, '-vvs', '-x', '--pdb', '--pdb-failure'], diff --git a/pandas/tslib.pyx b/pandas/tslib.pyx index ec11de7392680..3a0f7d9264174 100644 --- a/pandas/tslib.pyx +++ b/pandas/tslib.pyx @@ -388,6 +388,15 @@ cpdef object get_value_box(ndarray arr, object loc): return util.get_value_1d(arr, i) +# Add the min and max fields at the class level +# These are defined as magic numbers due to strange +# wraparound behavior when using the true int64 lower boundary +cdef int64_t _NS_LOWER_BOUND = -9223285636854775000LL +cdef int64_t _NS_UPPER_BOUND = 9223372036854775807LL +Timestamp.min = Timestamp(_NS_LOWER_BOUND) +Timestamp.max = Timestamp(_NS_UPPER_BOUND) + + #---------------------------------------------------------------------- # Frequency inference @@ -769,8 +778,6 @@ cdef inline object _get_zone(object tz): except AttributeError: return tz -# cdef int64_t _NS_LOWER_BOUND = -9223285636854775809LL -# cdef int64_t _NS_UPPER_BOUND = -9223372036854775807LL cdef inline _check_dts_bounds(int64_t value, pandas_datetimestruct *dts): cdef pandas_datetimestruct dts2 @@ -2868,4 +2875,4 @@ def _calc_julian_from_U_or_W(year, week_of_year, day_of_week, week_starts_Mon): return 1 + days_to_week + day_of_week # def _strptime_time(data_string, format="%a %b %d %H:%M:%S %Y"): -# return _strptime(data_string, format)[0] +# return _strptime(data_string, format)[0] \ No newline at end of file