Skip to content

Commit a8a4f0b

Browse files
committed
ENH: Allow Timestamp to accept Nanosecond argument
Add additional test Add gh issue number in test
1 parent e97be6f commit a8a4f0b

File tree

5 files changed

+25
-10
lines changed

5 files changed

+25
-10
lines changed

doc/source/whatsnew/v0.23.0.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -577,6 +577,7 @@ Datetimelike API Changes
577577
- Operations between a :class:`Series` with dtype ``dtype='datetime64[ns]'`` and a :class:`PeriodIndex` will correctly raises ``TypeError`` (:issue:`18850`)
578578
- Subtraction of :class:`Series` with timezone-aware ``dtype='datetime64[ns]'`` with mis-matched timezones will raise ``TypeError`` instead of ``ValueError`` (:issue:`18817`)
579579
- :func:`pandas.merge` provides a more informative error message when trying to merge on timezone-aware and timezone-naive columns (:issue:`15800`)
580+
- :class:`Timestamp` constructor now accepts a `nanosecond` keyword or positional argument (:issue:`18898`)
580581

581582
.. _whatsnew_0230.api.other:
582583

pandas/_libs/tslibs/conversion.pxd

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,8 @@ cdef class _TSObject:
1616

1717

1818
cdef convert_to_tsobject(object ts, object tz, object unit,
19-
bint dayfirst, bint yearfirst)
19+
bint dayfirst, bint yearfirst,
20+
int32_t nanos=*)
2021

2122
cdef _TSObject convert_datetime_to_tsobject(datetime ts, object tz,
2223
int32_t nanos=*)

pandas/_libs/tslibs/conversion.pyx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -252,7 +252,7 @@ cpdef int64_t pydt_to_i8(object pydt) except? -1:
252252

253253

254254
cdef convert_to_tsobject(object ts, object tz, object unit,
255-
bint dayfirst, bint yearfirst):
255+
bint dayfirst, bint yearfirst, int32_t nanos=0):
256256
"""
257257
Extract datetime and int64 from any of:
258258
- np.int64 (with unit providing a possible modifier)
@@ -297,11 +297,11 @@ cdef convert_to_tsobject(object ts, object tz, object unit,
297297
obj.value = ts
298298
dt64_to_dtstruct(ts, &obj.dts)
299299
elif PyDateTime_Check(ts):
300-
return convert_datetime_to_tsobject(ts, tz)
300+
return convert_datetime_to_tsobject(ts, tz, nanos)
301301
elif PyDate_Check(ts):
302302
# Keep the converter same as PyDateTime's
303303
ts = datetime.combine(ts, datetime_time())
304-
return convert_datetime_to_tsobject(ts, tz)
304+
return convert_datetime_to_tsobject(ts, tz, nanos)
305305
elif getattr(ts, '_typ', None) == 'period':
306306
raise ValueError("Cannot convert Period to Timestamp "
307307
"unambiguously. Use to_timestamp")

pandas/_libs/tslibs/timestamps.pyx

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -423,7 +423,7 @@ class Timestamp(_Timestamp):
423423
example, 's' means seconds and 'ms' means milliseconds.
424424
year, month, day : int
425425
.. versionadded:: 0.19.0
426-
hour, minute, second, microsecond : int, optional, default 0
426+
hour, minute, second, microsecond, nanosecond : int, optional, default 0
427427
.. versionadded:: 0.19.0
428428
tzinfo : datetime.tzinfo, optional, default None
429429
.. versionadded:: 0.19.0
@@ -556,7 +556,7 @@ class Timestamp(_Timestamp):
556556
object freq=None, tz=None, unit=None,
557557
year=None, month=None, day=None,
558558
hour=None, minute=None, second=None, microsecond=None,
559-
tzinfo=None):
559+
tzinfo=None, nanosecond=None):
560560
# The parameter list folds together legacy parameter names (the first
561561
# four) and positional and keyword parameter names from pydatetime.
562562
#
@@ -596,20 +596,20 @@ class Timestamp(_Timestamp):
596596
return Timestamp(datetime(year, month, day, hour or 0,
597597
minute or 0, second or 0,
598598
microsecond or 0, tzinfo),
599-
tz=tz)
599+
nanosecond=nanosecond, tz=tz)
600600
elif is_integer_object(freq):
601601
# User passed positional arguments:
602602
# Timestamp(year, month, day[, hour[, minute[, second[,
603603
# microsecond[, tzinfo]]]]])
604604
return Timestamp(datetime(ts_input, freq, tz, unit or 0,
605605
year or 0, month or 0, day or 0,
606-
hour), tz=hour)
606+
hour), nanosecond=minute, tz=hour)
607607

608608
if tzinfo is not None:
609609
# User passed tzinfo instead of tz; avoid silently ignoring
610610
tz, tzinfo = tzinfo, None
611611

612-
ts = convert_to_tsobject(ts_input, tz, unit, 0, 0)
612+
ts = convert_to_tsobject(ts_input, tz, unit, 0, 0, nanosecond or 0)
613613

614614
if ts.value == NPY_NAT:
615615
return NaT

pandas/tests/scalar/timestamp/test_timestamp.py

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88

99
from dateutil.tz import tzutc
1010
from pytz import timezone, utc
11-
from datetime import datetime, timedelta
11+
from datetime import datetime, timedelta, date
1212

1313
import pandas.util.testing as tm
1414
import pandas.util._test_decorators as td
@@ -385,6 +385,19 @@ def test_constructor_fromordinal(self):
385385
ts = Timestamp.fromordinal(dt_tz.toordinal(), tz='US/Eastern')
386386
assert ts.to_pydatetime() == dt_tz
387387

388+
@pytest.mark.parametrize('result', [
389+
Timestamp(datetime(2000, 1, 1), nanosecond=1),
390+
Timestamp(date(2000, 1, 1), nanosecond=1),
391+
Timestamp(year=2000, month=1, day=1, nanosecond=1),
392+
Timestamp(year=2000, month=1, day=1, tz='UTC', nanosecond=1),
393+
Timestamp(2000, 1, 1, 0, 0, 0, 0, None, 1),
394+
Timestamp(2000, 1, 1, 0, 0, 0, 0, pytz.UTC, 1)])
395+
def test_constructor_nanosecond(self, result):
396+
# GH 18898
397+
expected = Timestamp(datetime(2000, 1, 1), tz=result.tz)
398+
expected = expected + Timedelta(nanoseconds=1)
399+
assert result == expected
400+
388401
def test_out_of_bounds_value(self):
389402
one_us = np.timedelta64(1).astype('timedelta64[us]')
390403

0 commit comments

Comments
 (0)