From 288059adfb751d52be57e444198198518d256c05 Mon Sep 17 00:00:00 2001 From: Joe Jevnik Date: Mon, 15 Feb 2016 17:56:42 -0500 Subject: [PATCH] NaT.isoformat() returns 'NaT'. NaT.isoformat() returning 'NaT' allows users to use Timestamp to rehydrate any _Timestamp object from its isoformat. This means that it is safe to use _Timestamp.isoformat() as a serialization format for timestamps where NaT is a valid value. Author: Joe Jevnik Closes #12300 from llllllllll/nat-isoformat and squashes the following commits: eb34f07 [Joe Jevnik] ENH: NaT.isoformat() returns 'NaT'. --- doc/source/whatsnew/v0.18.0.txt | 7 +++++++ pandas/tests/test_format.py | 5 +++++ pandas/tseries/tests/test_timeseries.py | 9 ++++++--- pandas/tslib.pyx | 6 +++++- 4 files changed, 23 insertions(+), 4 deletions(-) diff --git a/doc/source/whatsnew/v0.18.0.txt b/doc/source/whatsnew/v0.18.0.txt index 8751886c2c86c..8429739902927 100644 --- a/doc/source/whatsnew/v0.18.0.txt +++ b/doc/source/whatsnew/v0.18.0.txt @@ -437,6 +437,8 @@ Backwards incompatible API changes - ``Series.head(0)`` and ``Series.tail(0)`` return empty series, rather than ``self``. (:issue:`11937`) - ``to_msgpack`` and ``read_msgpack`` encoding now defaults to ``'utf-8'``. (:issue:`12170`) - the order of keyword arguments to text file parsing functions (``.read_csv()``, ``.read_table()``, ``.read_fwf()``) changed to group related arguments. (:issue:`11555`) +- ``NaTType.isoformat`` now returns the string ``'NaT`` to allow the result to + be passed to the constructor of ``Timestamp``. (:issue:`12300`) NaT and Timedelta operations ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -507,6 +509,11 @@ Subtraction by ``Timedelta`` in a ``Series`` by a ``Timestamp`` works (:issue:`1 pd.Timestamp('2012-01-01') - ser +``NaT.isoformat()`` now returns ``'NaT'``. This change allows allows +``pd.Timestamp`` to rehydrate any timestamp like object from its isoformat +(:issue:`12300`). + + Signature change for .rank ^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/pandas/tests/test_format.py b/pandas/tests/test_format.py index 2ad25ad738649..cb5241c205d03 100644 --- a/pandas/tests/test_format.py +++ b/pandas/tests/test_format.py @@ -10,6 +10,7 @@ from pandas.compat import range, zip, lrange, StringIO, PY3, lzip, u import pandas.compat as compat import itertools +from operator import methodcaller import os import sys from textwrap import dedent @@ -4083,6 +4084,10 @@ def test_tz_dateutil(self): dt_datetime_us = datetime(2013, 1, 2, 12, 1, 3, 45, tzinfo=utc) self.assertEqual(str(dt_datetime_us), str(Timestamp(dt_datetime_us))) + def test_nat_representations(self): + for f in (str, repr, methodcaller('isoformat')): + self.assertEqual(f(pd.NaT), 'NaT') + if __name__ == '__main__': nose.runmodule(argv=[__file__, '-vvs', '-x', '--pdb', '--pdb-failure'], diff --git a/pandas/tseries/tests/test_timeseries.py b/pandas/tseries/tests/test_timeseries.py index 5665e502b8558..2c5620769d1b4 100644 --- a/pandas/tseries/tests/test_timeseries.py +++ b/pandas/tseries/tests/test_timeseries.py @@ -973,9 +973,9 @@ def test_NaT_methods(self): # GH 9513 raise_methods = ['astimezone', 'combine', 'ctime', 'dst', 'fromordinal', 'fromtimestamp', 'isocalendar', - 'isoformat', 'strftime', 'strptime', 'time', - 'timestamp', 'timetuple', 'timetz', 'toordinal', - 'tzname', 'utcfromtimestamp', 'utcnow', 'utcoffset', + 'strftime', 'strptime', 'time', 'timestamp', + 'timetuple', 'timetz', 'toordinal', 'tzname', + 'utcfromtimestamp', 'utcnow', 'utcoffset', 'utctimetuple'] nat_methods = ['date', 'now', 'replace', 'to_datetime', 'today'] nan_methods = ['weekday', 'isoweekday'] @@ -992,6 +992,9 @@ def test_NaT_methods(self): if hasattr(NaT, method): self.assertIs(getattr(NaT, method)(), NaT) + # GH 12300 + self.assertEqual(NaT.isoformat(), 'NaT') + def test_to_datetime_types(self): # empty string diff --git a/pandas/tslib.pyx b/pandas/tslib.pyx index 112a41b72f3ea..04ee609814b5b 100644 --- a/pandas/tslib.pyx +++ b/pandas/tslib.pyx @@ -673,6 +673,10 @@ class NaTType(_NaT): def __str__(self): return 'NaT' + def isoformat(self, sep='T'): + # This allows Timestamp(ts.isoformat()) to always correctly roundtrip. + return 'NaT' + def __hash__(self): return NPY_NAT @@ -736,7 +740,7 @@ _nat_methods = ['date', 'now', 'replace', 'to_datetime', 'today'] _nan_methods = ['weekday', 'isoweekday', 'total_seconds'] -_implemented_methods = ['to_datetime64'] +_implemented_methods = ['to_datetime64', 'isoformat'] _implemented_methods.extend(_nat_methods) _implemented_methods.extend(_nan_methods)