diff --git a/doc/source/release.rst b/doc/source/release.rst index b161d1f785114..0e6924e4b0122 100644 --- a/doc/source/release.rst +++ b/doc/source/release.rst @@ -150,6 +150,7 @@ Improvements to existing features (e.g. MonthEnd,BusinessMonthEnd), (:issue:`6479`) - perf improvements in single-dtyped indexing (:issue:`6484`) - ``StataWriter`` and ``DataFrame.to_stata`` accept time stamp and data labels (:issue:`6545`) +- offset/freq info now in Timestamp __repr__ (:issue:`4553`) .. _release.bug_fixes-0.14.0: diff --git a/pandas/tseries/tests/test_tslib.py b/pandas/tseries/tests/test_tslib.py index 0700e38d831d1..19703b9e30ef6 100644 --- a/pandas/tseries/tests/test_tslib.py +++ b/pandas/tseries/tests/test_tslib.py @@ -13,6 +13,41 @@ import pandas.util.testing as tm class TestTimestamp(tm.TestCase): + def test_repr(self): + date = '2014-03-07' + tz = 'US/Eastern' + freq = 'M' + + date_only = Timestamp(date) + self.assertIn(date, repr(date_only)) + self.assertNotIn(tz, repr(date_only)) + self.assertNotIn(freq, repr(date_only)) + self.assertEqual(date_only, eval(repr(date_only))) + + date_tz = Timestamp(date, tz=tz) + self.assertIn(date, repr(date_tz)) + self.assertIn(tz, repr(date_tz)) + self.assertNotIn(freq, repr(date_tz)) + self.assertEqual(date_tz, eval(repr(date_tz))) + + date_freq = Timestamp(date, offset=freq) + self.assertIn(date, repr(date_freq)) + self.assertNotIn(tz, repr(date_freq)) + self.assertIn(freq, repr(date_freq)) + self.assertEqual(date_freq, eval(repr(date_freq))) + + date_tz_freq = Timestamp(date, tz=tz, offset=freq) + self.assertIn(date, repr(date_tz_freq)) + self.assertIn(tz, repr(date_tz_freq)) + self.assertIn(freq, repr(date_tz_freq)) + self.assertEqual(date_tz_freq, eval(repr(date_tz_freq))) + + # this can cause the tz field to be populated, but it's redundant to information in the datestring + date_with_utc_offset = Timestamp('2014-03-13 00:00:00-0400', tz=None) + self.assertIn('2014-03-13 00:00:00-0400', repr(date_with_utc_offset)) + self.assertNotIn('tzoffset', repr(date_with_utc_offset)) + self.assertEqual(date_with_utc_offset, eval(repr(date_with_utc_offset))) + def test_bounds_with_different_units(self): out_of_bounds_dates = ( '1677-09-21', diff --git a/pandas/tslib.pyx b/pandas/tslib.pyx index da767b77d934c..88559fdfee9de 100644 --- a/pandas/tslib.pyx +++ b/pandas/tslib.pyx @@ -34,6 +34,7 @@ cimport cython from datetime import timedelta, datetime from datetime import time as datetime_time +from dateutil.tz import tzoffset from pandas.compat import parse_date from sys import version_info @@ -183,6 +184,10 @@ class Timestamp(_Timestamp): if ts.value == NPY_NAT: return NaT + if util.is_string_object(offset): + from pandas.tseries.frequencies import to_offset + offset = to_offset(offset) + # make datetime happy ts_base = _Timestamp.__new__(cls, ts.dts.year, ts.dts.month, ts.dts.day, ts.dts.hour, ts.dts.min, @@ -196,26 +201,28 @@ class Timestamp(_Timestamp): return ts_base def __repr__(self): - result = self._repr_base + stamp = self._repr_base zone = None try: - result += self.strftime('%z') + stamp += self.strftime('%z') if self.tzinfo: zone = _get_zone(self.tzinfo) except ValueError: year2000 = self.replace(year=2000) - result += year2000.strftime('%z') + stamp += year2000.strftime('%z') if self.tzinfo: zone = _get_zone(self.tzinfo) try: - result += zone.strftime(' %%Z') + stamp += zone.strftime(' %%Z') except: pass - zone = "'%s'" % zone if zone else 'None' - return "Timestamp('%s', tz=%s)" % (result, zone) + tz = ", tz='{0}'".format(zone) if zone is not None and not isinstance(zone, tzoffset) else "" + offset = ", offset='{0}'".format(self.offset.freqstr) if self.offset is not None else "" + + return "Timestamp('{stamp}'{tz}{offset})".format(stamp=stamp, tz=tz, offset=offset) @property def _date_repr(self):