From f9e2ad56f483b215c0d066d6c3f0b99885f202a5 Mon Sep 17 00:00:00 2001 From: Brock Mendel Date: Tue, 17 Oct 2017 10:27:37 -0700 Subject: [PATCH 01/16] Add timestamp method+test; closes #17329 --- pandas/_libs/tslib.pyx | 6 +++++- pandas/tests/scalar/test_timestamp.py | 12 ++++++++++++ 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/pandas/_libs/tslib.pyx b/pandas/_libs/tslib.pyx index f58aaa0ce3234..192bb87908950 100644 --- a/pandas/_libs/tslib.pyx +++ b/pandas/_libs/tslib.pyx @@ -1405,6 +1405,10 @@ cdef class _Timestamp(datetime): def __get__(self): return np.datetime64(self.value, 'ns') + def timestamp(self): + # py27 compat, see GH#17329 + return self.value / 1e9 + cdef PyTypeObject* ts_type = Timestamp @@ -3635,7 +3639,7 @@ cpdef int64_t tz_convert_single(int64_t val, object tz1, object tz2): """ Convert the val (in i8) from timezone1 to timezone2 - This is a single timezone versoin of tz_convert + This is a single timezone version of tz_convert Parameters ---------- diff --git a/pandas/tests/scalar/test_timestamp.py b/pandas/tests/scalar/test_timestamp.py index c1b9f858a08de..b6380160ea7c0 100644 --- a/pandas/tests/scalar/test_timestamp.py +++ b/pandas/tests/scalar/test_timestamp.py @@ -1079,6 +1079,18 @@ def test_is_leap_year(self): dt = Timestamp('2100-01-01 00:00:00', tz=tz) assert not dt.is_leap_year + def test_timestamp(self): + # Gh#17329 + # tz-naive --> treat it as if it were UTC for purposes of timestamp() + ts = Timestamp.now() + uts = ts.replace(tz=utc) + assert ts.timestamp() == uts.timestamp() + + tsc = Timestamp('2014-10-11 11:00:01.12345678', tz='US/Central') + utsc = tsc.tz_convert('UTC') + # utsc is a different representation of the same time + assert tsc.timestamp() == utsc.timestamp() + class TestTimestampNsOperations(object): From aa7b06d164f8eec69e738c6c0fc742437f22dd8d Mon Sep 17 00:00:00 2001 From: Brock Mendel Date: Tue, 17 Oct 2017 10:34:35 -0700 Subject: [PATCH 02/16] whatsnew entry --- doc/source/whatsnew/v0.21.0.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/doc/source/whatsnew/v0.21.0.txt b/doc/source/whatsnew/v0.21.0.txt index 598e452640781..a154eca50618c 100644 --- a/doc/source/whatsnew/v0.21.0.txt +++ b/doc/source/whatsnew/v0.21.0.txt @@ -235,6 +235,7 @@ Other Enhancements - Improved the import time of pandas by about 2.25x. (:issue:`16764`) - :func:`read_json` and :func:`to_json` now accept a ``compression`` argument which allows them to transparently handle compressed files. (:issue:`17798`) - :func:`Series.reindex`, :func:`DataFrame.reindex`, :func:`Index.get_indexer` now support list-like argument for ``tolerance``. (:issue:`17367`) +- :meth:`Timestamp.timestamp` is now available in python 2.7. (:issue:`17329`) .. _whatsnew_0210.api_breaking: From 4155b0321aeda0448f787bdf0dd432a83165714c Mon Sep 17 00:00:00 2001 From: Brock Mendel Date: Tue, 17 Oct 2017 11:04:30 -0700 Subject: [PATCH 03/16] typo fixup tz-->tzinfo --- pandas/tests/scalar/test_timestamp.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pandas/tests/scalar/test_timestamp.py b/pandas/tests/scalar/test_timestamp.py index b6380160ea7c0..f2c8462b25b8e 100644 --- a/pandas/tests/scalar/test_timestamp.py +++ b/pandas/tests/scalar/test_timestamp.py @@ -1083,7 +1083,7 @@ def test_timestamp(self): # Gh#17329 # tz-naive --> treat it as if it were UTC for purposes of timestamp() ts = Timestamp.now() - uts = ts.replace(tz=utc) + uts = ts.replace(tzinfo=utc) assert ts.timestamp() == uts.timestamp() tsc = Timestamp('2014-10-11 11:00:01.12345678', tz='US/Central') From c73c2fea2d6b65d5e828df8e68a663e74d85c79f Mon Sep 17 00:00:00 2001 From: Brock Mendel Date: Tue, 17 Oct 2017 11:46:41 -0700 Subject: [PATCH 04/16] fixup python-->Python --- doc/source/whatsnew/v0.21.0.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/source/whatsnew/v0.21.0.txt b/doc/source/whatsnew/v0.21.0.txt index a154eca50618c..c46d545cd827c 100644 --- a/doc/source/whatsnew/v0.21.0.txt +++ b/doc/source/whatsnew/v0.21.0.txt @@ -235,7 +235,7 @@ Other Enhancements - Improved the import time of pandas by about 2.25x. (:issue:`16764`) - :func:`read_json` and :func:`to_json` now accept a ``compression`` argument which allows them to transparently handle compressed files. (:issue:`17798`) - :func:`Series.reindex`, :func:`DataFrame.reindex`, :func:`Index.get_indexer` now support list-like argument for ``tolerance``. (:issue:`17367`) -- :meth:`Timestamp.timestamp` is now available in python 2.7. (:issue:`17329`) +- :meth:`Timestamp.timestamp` is now available in Python 2.7. (:issue:`17329`) .. _whatsnew_0210.api_breaking: From 66d4a2b810b367734d2cc117b296969423e6e0a2 Mon Sep 17 00:00:00 2001 From: Brock Mendel Date: Tue, 17 Oct 2017 12:09:39 -0700 Subject: [PATCH 05/16] Add timestamp method to NaT in py2 --- pandas/_libs/tslib.pyx | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/pandas/_libs/tslib.pyx b/pandas/_libs/tslib.pyx index 192bb87908950..eeb611d98c716 100644 --- a/pandas/_libs/tslib.pyx +++ b/pandas/_libs/tslib.pyx @@ -956,8 +956,7 @@ class NaTType(_NaT): combine = _make_error_func('combine', None) utcnow = _make_error_func('utcnow', None) - if PY3: - timestamp = _make_error_func('timestamp', datetime) + timestamp = _make_error_func('timestamp', datetime) # GH9513 NaT methods (except to_datetime64) to raise, return np.nan, or # return NaT create functions that raise, for binding to NaTType From 54ebd131621df2b6a677cb36b155a76311250039 Mon Sep 17 00:00:00 2001 From: Brock Mendel Date: Tue, 17 Oct 2017 14:16:53 -0700 Subject: [PATCH 06/16] fix docstring mismatch --- pandas/_libs/tslib.pyx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pandas/_libs/tslib.pyx b/pandas/_libs/tslib.pyx index eeb611d98c716..54200ede69669 100644 --- a/pandas/_libs/tslib.pyx +++ b/pandas/_libs/tslib.pyx @@ -956,7 +956,7 @@ class NaTType(_NaT): combine = _make_error_func('combine', None) utcnow = _make_error_func('utcnow', None) - timestamp = _make_error_func('timestamp', datetime) + timestamp = _make_error_func('timestamp', Timestamp) # GH9513 NaT methods (except to_datetime64) to raise, return np.nan, or # return NaT create functions that raise, for binding to NaTType From a88419dc89729467502dde3c19fcc8ad12115150 Mon Sep 17 00:00:00 2001 From: Brock Mendel Date: Tue, 17 Oct 2017 16:02:29 -0700 Subject: [PATCH 07/16] add docstring, test against timestamp in py3 --- pandas/_libs/tslib.pyx | 1 + pandas/tests/scalar/test_timestamp.py | 6 +++++- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/pandas/_libs/tslib.pyx b/pandas/_libs/tslib.pyx index 54200ede69669..73ef8494062cb 100644 --- a/pandas/_libs/tslib.pyx +++ b/pandas/_libs/tslib.pyx @@ -1405,6 +1405,7 @@ cdef class _Timestamp(datetime): return np.datetime64(self.value, 'ns') def timestamp(self): + """Return POSIX timestamp as float.""" # py27 compat, see GH#17329 return self.value / 1e9 diff --git a/pandas/tests/scalar/test_timestamp.py b/pandas/tests/scalar/test_timestamp.py index f2c8462b25b8e..d72bbaa1c372f 100644 --- a/pandas/tests/scalar/test_timestamp.py +++ b/pandas/tests/scalar/test_timestamp.py @@ -1080,7 +1080,7 @@ def test_is_leap_year(self): assert not dt.is_leap_year def test_timestamp(self): - # Gh#17329 + # GH#17329 # tz-naive --> treat it as if it were UTC for purposes of timestamp() ts = Timestamp.now() uts = ts.replace(tzinfo=utc) @@ -1091,6 +1091,10 @@ def test_timestamp(self): # utsc is a different representation of the same time assert tsc.timestamp() == utsc.timestamp() + if PY3: + dt = ts.to_pydatetime() + assert dt.timestamp() == ts.timestamp() - ts.nanoseconds + class TestTimestampNsOperations(object): From 49accab98acb8457cddd8ffc8919c9b847d7d8e5 Mon Sep 17 00:00:00 2001 From: Brock Mendel Date: Tue, 17 Oct 2017 16:33:38 -0700 Subject: [PATCH 08/16] add timestamp to api.rst --- doc/source/api.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/doc/source/api.rst b/doc/source/api.rst index 1e63a938ff389..858c7f28cfd38 100644 --- a/doc/source/api.rst +++ b/doc/source/api.rst @@ -1793,6 +1793,7 @@ Methods Timestamp.strftime Timestamp.strptime Timestamp.time + Timestamp.timestamp Timestamp.timetuple Timestamp.timetz Timestamp.to_datetime64 From 698e6880a6ba00e7d558baf8d0f800a78af83275 Mon Sep 17 00:00:00 2001 From: Brock Mendel Date: Wed, 18 Oct 2017 10:13:17 -0700 Subject: [PATCH 09/16] fixup missing import --- pandas/tests/scalar/test_timestamp.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pandas/tests/scalar/test_timestamp.py b/pandas/tests/scalar/test_timestamp.py index d72bbaa1c372f..bb0dfa063425e 100644 --- a/pandas/tests/scalar/test_timestamp.py +++ b/pandas/tests/scalar/test_timestamp.py @@ -19,7 +19,7 @@ from pandas._libs import tslib, period from pandas._libs.tslibs.timezones import get_timezone -from pandas.compat import lrange, long +from pandas.compat import lrange, long, PY3 from pandas.util.testing import assert_series_equal from pandas.compat.numpy import np_datetime64_compat from pandas import (Timestamp, date_range, Period, Timedelta, compat, From 5eed82b93e0ced4a70bf0e22c892b4846eaa1137 Mon Sep 17 00:00:00 2001 From: Brock Mendel Date: Thu, 19 Oct 2017 21:25:29 -0700 Subject: [PATCH 10/16] typo fixup --- pandas/tests/scalar/test_timestamp.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pandas/tests/scalar/test_timestamp.py b/pandas/tests/scalar/test_timestamp.py index bb0dfa063425e..5d299d3a678bb 100644 --- a/pandas/tests/scalar/test_timestamp.py +++ b/pandas/tests/scalar/test_timestamp.py @@ -1093,7 +1093,7 @@ def test_timestamp(self): if PY3: dt = ts.to_pydatetime() - assert dt.timestamp() == ts.timestamp() - ts.nanoseconds + assert dt.timestamp() == ts.timestamp() - ts.nanosecond class TestTimestampNsOperations(object): From 715b74024fbfaca182eb1869ac816f87e4ef4b81 Mon Sep 17 00:00:00 2001 From: Brock Mendel Date: Fri, 20 Oct 2017 08:35:31 -0700 Subject: [PATCH 11/16] fix timestamp test --- pandas/tests/scalar/test_timestamp.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pandas/tests/scalar/test_timestamp.py b/pandas/tests/scalar/test_timestamp.py index 5d299d3a678bb..f5c838ee6f34c 100644 --- a/pandas/tests/scalar/test_timestamp.py +++ b/pandas/tests/scalar/test_timestamp.py @@ -1093,7 +1093,7 @@ def test_timestamp(self): if PY3: dt = ts.to_pydatetime() - assert dt.timestamp() == ts.timestamp() - ts.nanosecond + assert dt.timestamp() == round(ts.timestamp(), 6) class TestTimestampNsOperations(object): From b7747ec88e4e56897f6432a102570aaf7bf3bc7a Mon Sep 17 00:00:00 2001 From: Brock Mendel Date: Fri, 20 Oct 2017 16:26:15 -0700 Subject: [PATCH 12/16] add test for NaT.timestamp --- pandas/tests/scalar/test_timestamp.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/pandas/tests/scalar/test_timestamp.py b/pandas/tests/scalar/test_timestamp.py index f5c838ee6f34c..9ddf8e5e6c3ad 100644 --- a/pandas/tests/scalar/test_timestamp.py +++ b/pandas/tests/scalar/test_timestamp.py @@ -1092,9 +1092,12 @@ def test_timestamp(self): assert tsc.timestamp() == utsc.timestamp() if PY3: + # should agree with datetime.timestamp method dt = ts.to_pydatetime() assert dt.timestamp() == round(ts.timestamp(), 6) + pytest.raises(ValueError, NaT.timestamp) + class TestTimestampNsOperations(object): From 237be98afd697d86d4ebaa45f7c1343750e6ab5e Mon Sep 17 00:00:00 2001 From: Brock Mendel Date: Sat, 21 Oct 2017 12:23:43 -0700 Subject: [PATCH 13/16] Move nat timestamp test to test_nat --- pandas/tests/scalar/test_nat.py | 5 +++++ pandas/tests/scalar/test_timestamp.py | 2 -- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/pandas/tests/scalar/test_nat.py b/pandas/tests/scalar/test_nat.py index 135e4c544de41..ce554545c246e 100644 --- a/pandas/tests/scalar/test_nat.py +++ b/pandas/tests/scalar/test_nat.py @@ -123,6 +123,11 @@ def test_round_nat(klass): assert round_method(freq) is ts +def test_timestamp(): + # GH#17329 + pytest.raises(ValueError, NaT.timestamp) + + def test_NaT_methods(): # GH 9513 raise_methods = ['astimezone', 'combine', 'ctime', 'dst', diff --git a/pandas/tests/scalar/test_timestamp.py b/pandas/tests/scalar/test_timestamp.py index 9ddf8e5e6c3ad..8fe1ebfe03078 100644 --- a/pandas/tests/scalar/test_timestamp.py +++ b/pandas/tests/scalar/test_timestamp.py @@ -1096,8 +1096,6 @@ def test_timestamp(self): dt = ts.to_pydatetime() assert dt.timestamp() == round(ts.timestamp(), 6) - pytest.raises(ValueError, NaT.timestamp) - class TestTimestampNsOperations(object): From a775671a420f86b7f820d35ef874f7af6c42d525 Mon Sep 17 00:00:00 2001 From: Brock Mendel Date: Sat, 21 Oct 2017 12:54:50 -0700 Subject: [PATCH 14/16] round timestamp to 6 digits; merge nat test --- pandas/_libs/tslib.pyx | 2 +- pandas/tests/scalar/test_nat.py | 8 ++------ 2 files changed, 3 insertions(+), 7 deletions(-) diff --git a/pandas/_libs/tslib.pyx b/pandas/_libs/tslib.pyx index 73ef8494062cb..0493211ec546d 100644 --- a/pandas/_libs/tslib.pyx +++ b/pandas/_libs/tslib.pyx @@ -1407,7 +1407,7 @@ cdef class _Timestamp(datetime): def timestamp(self): """Return POSIX timestamp as float.""" # py27 compat, see GH#17329 - return self.value / 1e9 + return round(self.value / 1e9, 6) cdef PyTypeObject* ts_type = Timestamp diff --git a/pandas/tests/scalar/test_nat.py b/pandas/tests/scalar/test_nat.py index ce554545c246e..0e69371511294 100644 --- a/pandas/tests/scalar/test_nat.py +++ b/pandas/tests/scalar/test_nat.py @@ -123,19 +123,15 @@ def test_round_nat(klass): assert round_method(freq) is ts -def test_timestamp(): - # GH#17329 - pytest.raises(ValueError, NaT.timestamp) - - def test_NaT_methods(): # GH 9513 + # GH 17329 for `timestamp` raise_methods = ['astimezone', 'combine', 'ctime', 'dst', 'fromordinal', 'fromtimestamp', 'isocalendar', 'strftime', 'strptime', 'time', 'timestamp', 'timetuple', 'timetz', 'toordinal', 'tzname', 'utcfromtimestamp', 'utcnow', 'utcoffset', - 'utctimetuple'] + 'utctimetuple', 'timestamp'] nat_methods = ['date', 'now', 'replace', 'to_datetime', 'today', 'tz_convert', 'tz_localize'] nan_methods = ['weekday', 'isoweekday'] From 8f6d8d5165d96d8895dea90a778aec8b05139f91 Mon Sep 17 00:00:00 2001 From: Brock Mendel Date: Sat, 21 Oct 2017 12:55:45 -0700 Subject: [PATCH 15/16] remove rounding from timestamp test --- pandas/tests/scalar/test_timestamp.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pandas/tests/scalar/test_timestamp.py b/pandas/tests/scalar/test_timestamp.py index 8fe1ebfe03078..c160471bd0981 100644 --- a/pandas/tests/scalar/test_timestamp.py +++ b/pandas/tests/scalar/test_timestamp.py @@ -1094,7 +1094,7 @@ def test_timestamp(self): if PY3: # should agree with datetime.timestamp method dt = ts.to_pydatetime() - assert dt.timestamp() == round(ts.timestamp(), 6) + assert dt.timestamp() == ts.timestamp() class TestTimestampNsOperations(object): From 7992462076a8f9b9d165451b732df15bf5384e77 Mon Sep 17 00:00:00 2001 From: Brock Mendel Date: Fri, 27 Oct 2017 12:58:58 -0700 Subject: [PATCH 16/16] move whatsnew to 0.21.1 --- doc/source/whatsnew/v0.21.0.txt | 1 - doc/source/whatsnew/v0.21.1.txt | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/doc/source/whatsnew/v0.21.0.txt b/doc/source/whatsnew/v0.21.0.txt index 90d44c734adb5..4c460eeb85b82 100644 --- a/doc/source/whatsnew/v0.21.0.txt +++ b/doc/source/whatsnew/v0.21.0.txt @@ -338,7 +338,6 @@ Various enhancements - :func:`read_excel` raises ``ImportError`` with a better message if ``xlrd`` is not installed. (:issue:`17613`) - :meth:`DataFrame.assign` will preserve the original order of ``**kwargs`` for Python 3.6+ users instead of sorting the column names. (:issue:`14207`) - :func:`Series.reindex`, :func:`DataFrame.reindex`, :func:`Index.get_indexer` now support list-like argument for ``tolerance``. (:issue:`17367`) -- :meth:`Timestamp.timestamp` is now available in Python 2.7. (:issue:`17329`) .. _whatsnew_0210.api_breaking: diff --git a/doc/source/whatsnew/v0.21.1.txt b/doc/source/whatsnew/v0.21.1.txt index 422a239e86ece..5e941b0d6c765 100644 --- a/doc/source/whatsnew/v0.21.1.txt +++ b/doc/source/whatsnew/v0.21.1.txt @@ -21,7 +21,7 @@ New features Other Enhancements ^^^^^^^^^^^^^^^^^^ -- +- :meth:`Timestamp.timestamp` is now available in Python 2.7. (:issue:`17329`) - -