diff --git a/pandas/_libs/src/datetime/pd_datetime.c b/pandas/_libs/src/datetime/pd_datetime.c index 19de51be6e1b2..1a45c6883fa9d 100644 --- a/pandas/_libs/src/datetime/pd_datetime.c +++ b/pandas/_libs/src/datetime/pd_datetime.c @@ -71,7 +71,9 @@ static int convert_pydatetime_to_datetimestruct(PyObject *dtobj, out->min = PyLong_AsLong(PyObject_GetAttrString(obj, "minute")); out->sec = PyLong_AsLong(PyObject_GetAttrString(obj, "second")); out->us = PyLong_AsLong(PyObject_GetAttrString(obj, "microsecond")); - + if (PyObject_HasAttrString(obj, "nanosecond")) { + out->ps = 1000 * PyLong_AsLong(PyObject_GetAttrString(obj, "nanosecond")); + } if (PyObject_HasAttrString(obj, "tzinfo")) { PyObject *offset = extract_utc_offset(obj); /* Apply the time zone offset if datetime obj is tz-aware */ diff --git a/pandas/tests/io/json/test_pandas.py b/pandas/tests/io/json/test_pandas.py index db120588b234c..73e52b35dc32e 100644 --- a/pandas/tests/io/json/test_pandas.py +++ b/pandas/tests/io/json/test_pandas.py @@ -1216,6 +1216,26 @@ def test_datetime_tz(self): s_naive = Series(tz_naive) assert stz.to_json() == s_naive.to_json() + def test_tz_nano_datetimes(self): + df = DataFrame( + { + "date": Series( + [ + datetime.datetime( + 2024, 1, 1, 0, 0, 0, 000000, tzinfo=datetime.timezone.utc + ) + ] + ) + } + ) + df.date = df.date + np.timedelta64(1, "ns") + buf = StringIO() + df.to_json(buf, date_unit="ns", orient="columns", date_format="iso") + buf.seek(0) + tm.assert_frame_equal( + read_json(buf), df, check_index_type=False, check_dtype=False + ) + def test_sparse(self): # GH4377 df.to_json segfaults with non-ndarray blocks df = DataFrame(np.random.default_rng(2).standard_normal((10, 4)))