Skip to content

Commit 2c81129

Browse files
discortjreback
authored andcommitted
BUG: pandas.Series.dt.round inconsistent behaviour on NAT's with different arguments
closes #14940 Author: discort <[email protected]> Closes #15124 from discort/dt_round_bug_14940 and squashes the following commits: 9e77191 [discort] added a test for Timestamp 52c897a [discort] BUG: added maybe_mask_results to '_round' method
1 parent 7ad6c65 commit 2c81129

File tree

4 files changed

+27
-1
lines changed

4 files changed

+27
-1
lines changed

doc/source/whatsnew/v0.20.0.txt

+2
Original file line numberDiff line numberDiff line change
@@ -368,3 +368,5 @@ Bug Fixes
368368

369369

370370
- Bug in ``pd.read_csv()`` for the C engine where ``usecols`` were being indexed incorrectly with ``parse_dates`` (:issue:`14792`)
371+
372+
- Bug in ``Series.dt.round`` inconsistent behaviour on NAT's with different arguments (:issue:`14940`)

pandas/tseries/base.py

+1
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,7 @@ def _round(self, freq, rounder):
8484
values = _ensure_datetimelike_to_i8(self)
8585

8686
result = (unit * rounder(values / float(unit))).astype('i8')
87+
result = self._maybe_mask_results(result, fill_value=tslib.NaT)
8788
attribs = self._get_attributes_dict()
8889
if 'freq' in attribs:
8990
attribs['freq'] = None

pandas/tseries/tests/test_timeseries.py

+18
Original file line numberDiff line numberDiff line change
@@ -4453,6 +4453,15 @@ def test_nat_operations(self):
44534453
self.assertEqual(s.min(), exp)
44544454
self.assertEqual(s.max(), exp)
44554455

4456+
def test_round_nat(self):
4457+
# GH14940
4458+
s = Series([pd.NaT])
4459+
expected = Series(pd.NaT)
4460+
for method in ["round", "floor", "ceil"]:
4461+
round_method = getattr(s.dt, method)
4462+
for freq in ["s", "5s", "min", "5min", "h", "5h"]:
4463+
assert_series_equal(round_method(freq), expected)
4464+
44564465

44574466
class TestTimestamp(tm.TestCase):
44584467
def test_class_ops_pytz(self):
@@ -4861,6 +4870,15 @@ def test_is_leap_year(self):
48614870
self.assertFalse(pd.NaT.is_leap_year)
48624871
self.assertIsInstance(pd.NaT.is_leap_year, bool)
48634872

4873+
def test_round_nat(self):
4874+
# GH14940
4875+
ts = Timestamp('nat')
4876+
print(dir(ts))
4877+
for method in ["round", "floor", "ceil"]:
4878+
round_method = getattr(ts, method)
4879+
for freq in ["s", "5s", "min", "5min", "h", "5h"]:
4880+
self.assertIs(round_method(freq), ts)
4881+
48644882

48654883
class TestSlicing(tm.TestCase):
48664884
def test_slice_year(self):

pandas/tslib.pyx

+6-1
Original file line numberDiff line numberDiff line change
@@ -885,7 +885,12 @@ def _make_nan_func(func_name):
885885
f.__name__ = func_name
886886
return f
887887

888+
889+
# GH14940
890+
_round_methods = ['round', 'floor', 'ceil']
891+
888892
_nat_methods = ['date', 'now', 'replace', 'to_pydatetime', 'today']
893+
_nat_methods.extend(_round_methods)
889894

890895
_nan_methods = ['weekday', 'isoweekday', 'total_seconds']
891896

@@ -895,7 +900,7 @@ _implemented_methods.extend(_nan_methods)
895900

896901
for _method_name in _nat_methods:
897902
# not all methods exist in all versions of Python
898-
if hasattr(NaTType, _method_name):
903+
if hasattr(NaTType, _method_name) or _method_name in _round_methods:
899904
setattr(NaTType, _method_name, _make_nat_func(_method_name))
900905

901906
for _method_name in _nan_methods:

0 commit comments

Comments
 (0)