Skip to content

ENH: support nanoseconds in Period constructor #38175

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 13 commits into from
Dec 2, 2020
11 changes: 10 additions & 1 deletion pandas/_libs/tslibs/period.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -2345,6 +2345,7 @@ class Period(_Period):

if freq is not None:
freq = cls._maybe_convert_freq(freq)
nanosecond = 0

if ordinal is not None and value is not None:
raise ValueError("Only value or ordinal but not both should be "
Expand Down Expand Up @@ -2394,6 +2395,14 @@ class Period(_Period):
value = str(value)
value = value.upper()
dt, reso = parse_time_string(value, freq)
try:
ts = Timestamp(value)
Comment on lines 2397 to +2399
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Aren't we effectively doing the parsing twice, this way? (once in parse_time_string, once in Timestamp) Any way to avoid this?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes - @jreback suggested integrating this a bit more into parse_time_string

I opened #38312 to track resolution (I'll have a go at it if no one else does)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks!

except ValueError:
nanosecond = 0
else:
nanosecond = ts.nanosecond
if nanosecond != 0:
reso = 'nanosecond'
if dt is NaT:
ordinal = NPY_NAT

Expand Down Expand Up @@ -2425,7 +2434,7 @@ class Period(_Period):
base = freq_to_dtype_code(freq)
ordinal = period_ordinal(dt.year, dt.month, dt.day,
dt.hour, dt.minute, dt.second,
dt.microsecond, 0, base)
dt.microsecond, 1000*nanosecond, base)

return cls._from_ordinal(ordinal, freq)

Expand Down
16 changes: 16 additions & 0 deletions pandas/tests/scalar/period/test_period.py
Original file line number Diff line number Diff line change
Expand Up @@ -487,6 +487,22 @@ def test_period_cons_combined(self):
with pytest.raises(ValueError, match=msg):
Period("2011-01", freq="1D1W")

@pytest.mark.parametrize("day", ["1970/01/01 ", "2020-12-31 ", "1981/09/13 "])
@pytest.mark.parametrize("hour", ["00:00:00", "00:00:01", "23:59:59", "12:00:59"])
@pytest.mark.parametrize(
"sec_float, expected",
[
(".000000001", 1),
(".000000999", 999),
(".123456789", 789),
(".999999999", 999),
],
)
def test_period_constructor_nanosecond(self, day, hour, sec_float, expected):
# GH 34621

assert Period(day + hour + sec_float).start_time.nanosecond == expected

@pytest.mark.parametrize("hour", range(24))
def test_period_large_ordinal(self, hour):
# Issue #36430
Expand Down