Skip to content

Commit

Permalink
ERR: Timestamp replace compatibility
Browse files Browse the repository at this point in the history
closes pandas-dev#15240

Author: Sébastien de Menten <sdementen@gmail.com>
Author: sdementen <sdementen@users.noreply.github.com>
Author: Jeff Reback <jeff@reback.net>

Closes pandas-dev#15248 from sdementen/timestamp-replace-compatibility and squashes the following commits:

e70e75a [Jeff Reback] use tzinfo=object to accept None as a default parameter
52b6c2c [Sébastien de Menten] improve description of whatsnew item
9455ee9 [sdementen] fix for issue pandas-dev#15240
1a40777 [Sébastien de Menten] update what's new with bug fix
5263054 [Sébastien de Menten] fix typos + update doc
d5c7b0a [Sébastien de Menten] update exception type raised when wrong argument to Timestamp.replace
2ac141a [sdementen] fix for issue pandas-dev#15240
  • Loading branch information
sdementen authored and jreback committed Jan 28, 2017
1 parent 3853fe6 commit 66d8c41
Show file tree
Hide file tree
Showing 3 changed files with 41 additions and 38 deletions.
1 change: 1 addition & 0 deletions doc/source/whatsnew/v0.20.0.txt
Original file line number Diff line number Diff line change
Expand Up @@ -416,6 +416,7 @@ Performance Improvements
Bug Fixes
~~~~~~~~~

- Bug in ``Timestamp.replace`` now raises ``TypeError`` when incorrect argument names are given; previously this raised ``ValueError`` (:issue:`15240`)
- Bug in ``Index`` power operations with reversed operands (:issue:`14973`)
- Bug in ``TimedeltaIndex`` addition where overflow was being allowed without error (:issue:`14816`)
- Bug in ``TimedeltaIndex`` raising a ``ValueError`` when boolean indexing with ``loc`` (:issue:`14946`)
Expand Down
3 changes: 1 addition & 2 deletions pandas/tseries/tests/test_timezones.py
Original file line number Diff line number Diff line change
Expand Up @@ -826,7 +826,6 @@ def test_date_range_span_dst_transition(self):
def test_convert_datetime_list(self):
dr = date_range('2012-06-02', periods=10,
tz=self.tzstr('US/Eastern'), name='foo')

dr2 = DatetimeIndex(list(dr), name='foo')
self.assert_index_equal(dr, dr2)
self.assertEqual(dr.tz, dr2.tz)
Expand Down Expand Up @@ -1198,7 +1197,7 @@ def test_replace(self):
# error
def f():
dt.replace(foo=5)
self.assertRaises(ValueError, f)
self.assertRaises(TypeError, f)

def f():
dt.replace(hour=0.1)
Expand Down
75 changes: 39 additions & 36 deletions pandas/tslib.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -650,18 +650,25 @@ class Timestamp(_Timestamp):

astimezone = tz_convert

def replace(self, **kwds):
def replace(self, year=None, month=None, day=None,
hour=None, minute=None, second=None, microsecond=None,
nanosecond=None, tzinfo=object, fold=0):
"""
implements datetime.replace, handles nanoseconds
Parameters
----------
kwargs: key-value dict
accepted keywords are:
year, month, day, hour, minute, second, microsecond, nanosecond, tzinfo
values must be integer, or for tzinfo, a tz-convertible
year : int, optional
month : int, optional
day : int, optional
hour : int, optional
minute : int, optional
second : int, optional
microsecond : int, optional
nanosecond: int, optional
tzinfo : tz-convertible, optional
fold : int, optional, default is 0
added in 3.6, NotImplemented
Returns
-------
Expand All @@ -671,14 +678,14 @@ class Timestamp(_Timestamp):
cdef:
pandas_datetimestruct dts
int64_t value
object tzinfo, result, k, v
object _tzinfo, result, k, v
_TSObject ts

# set to naive if needed
tzinfo = self.tzinfo
_tzinfo = self.tzinfo
value = self.value
if tzinfo is not None:
value = tz_convert_single(value, 'UTC', tzinfo)
if _tzinfo is not None:
value = tz_convert_single(value, 'UTC', _tzinfo)

# setup components
pandas_datetime_to_datetimestruct(value, PANDAS_FR_ns, &dts)
Expand All @@ -692,39 +699,35 @@ class Timestamp(_Timestamp):
"{v} for {k}".format(v=type(v), k=k))
return v

for k, v in kwds.items():
if k == 'year':
dts.year = validate(k, v)
elif k == 'month':
dts.month = validate(k, v)
elif k == 'day':
dts.day = validate(k, v)
elif k == 'hour':
dts.hour = validate(k, v)
elif k == 'minute':
dts.min = validate(k, v)
elif k == 'second':
dts.sec = validate(k, v)
elif k == 'microsecond':
dts.us = validate(k, v)
elif k == 'nanosecond':
dts.ps = validate(k, v) * 1000
elif k == 'tzinfo':
tzinfo = v
else:
raise ValueError("invalid name {} passed".format(k))
if year is not None:
dts.year = validate('year', year)
if month is not None:
dts.month = validate('month', month)
if day is not None:
dts.day = validate('day', day)
if hour is not None:
dts.hour = validate('hour', hour)
if minute is not None:
dts.min = validate('minute', minute)
if second is not None:
dts.sec = validate('second', second)
if microsecond is not None:
dts.us = validate('microsecond', microsecond)
if nanosecond is not None:
dts.ps = validate('nanosecond', nanosecond) * 1000
if tzinfo is not object:
_tzinfo = tzinfo

# reconstruct & check bounds
value = pandas_datetimestruct_to_datetime(PANDAS_FR_ns, &dts)
if value != NPY_NAT:
_check_dts_bounds(&dts)

# set tz if needed
if tzinfo is not None:
value = tz_convert_single(value, tzinfo, 'UTC')

result = create_timestamp_from_ts(value, dts, tzinfo, self.freq)
if _tzinfo is not None:
value = tz_convert_single(value, _tzinfo, 'UTC')

result = create_timestamp_from_ts(value, dts, _tzinfo, self.freq)
return result

def isoformat(self, sep='T'):
Expand Down

0 comments on commit 66d8c41

Please sign in to comment.