diff --git a/doc/source/whatsnew/v2.0.0.rst b/doc/source/whatsnew/v2.0.0.rst index d8609737b8c7a..b70dcb0ae99fa 100644 --- a/doc/source/whatsnew/v2.0.0.rst +++ b/doc/source/whatsnew/v2.0.0.rst @@ -658,7 +658,7 @@ Datetimelike - Bug in subtracting a ``datetime`` scalar from :class:`DatetimeIndex` failing to retain the original ``freq`` attribute (:issue:`48818`) - Bug in ``pandas.tseries.holiday.Holiday`` where a half-open date interval causes inconsistent return types from :meth:`USFederalHolidayCalendar.holidays` (:issue:`49075`) - Bug in rendering :class:`DatetimeIndex` and :class:`Series` and :class:`DataFrame` with timezone-aware dtypes with ``dateutil`` or ``zoneinfo`` timezones near daylight-savings transitions (:issue:`49684`) -- Bug in :func:`to_datetime` was raising ``ValueError`` when parsing :class:`Timestamp` or ``datetime`` objects with non-ISO8601 ``format`` (:issue:`49298`) +- Bug in :func:`to_datetime` was raising ``ValueError`` when parsing :class:`Timestamp`, ``datetime``, or ``np.datetime64`` objects with non-ISO8601 ``format`` (:issue:`49298`, :issue:`50036`) - Timedelta diff --git a/pandas/_libs/tslibs/strptime.pyx b/pandas/_libs/tslibs/strptime.pyx index c56b4891da428..9a315106b75cd 100644 --- a/pandas/_libs/tslibs/strptime.pyx +++ b/pandas/_libs/tslibs/strptime.pyx @@ -14,13 +14,17 @@ from _thread import allocate_lock as _thread_allocate_lock import numpy as np import pytz +cimport numpy as cnp from numpy cimport ( int64_t, ndarray, ) from pandas._libs.missing cimport checknull_with_nat_and_na -from pandas._libs.tslibs.conversion cimport convert_timezone +from pandas._libs.tslibs.conversion cimport ( + convert_timezone, + get_datetime64_nanos, +) from pandas._libs.tslibs.nattype cimport ( NPY_NAT, c_nat_strings as nat_strings, @@ -33,6 +37,9 @@ from pandas._libs.tslibs.np_datetime cimport ( pydatetime_to_dt64, ) from pandas._libs.tslibs.timestamps cimport _Timestamp +from pandas._libs.util cimport is_datetime64_object + +cnp.import_array() cdef dict _parse_code_table = {"y": 0, @@ -166,6 +173,9 @@ def array_strptime( check_dts_bounds(&dts) result_timezone[i] = val.tzinfo continue + elif is_datetime64_object(val): + iresult[i] = get_datetime64_nanos(val, NPY_FR_ns) + continue else: val = str(val) diff --git a/pandas/tests/tools/test_to_datetime.py b/pandas/tests/tools/test_to_datetime.py index 7df45975475dd..59be88e245fd0 100644 --- a/pandas/tests/tools/test_to_datetime.py +++ b/pandas/tests/tools/test_to_datetime.py @@ -758,6 +758,19 @@ def test_to_datetime_today_now_unicode_bytes(self, arg): def test_to_datetime_dt64s(self, cache, dt): assert to_datetime(dt, cache=cache) == Timestamp(dt) + @pytest.mark.parametrize( + "arg, format", + [ + ("2001-01-01", "%Y-%m-%d"), + ("01-01-2001", "%d-%m-%Y"), + ], + ) + def test_to_datetime_dt64s_and_str(self, arg, format): + # https://github.com/pandas-dev/pandas/issues/50036 + result = to_datetime([arg, np.datetime64("2020-01-01")], format=format) + expected = DatetimeIndex(["2001-01-01", "2020-01-01"]) + tm.assert_index_equal(result, expected) + @pytest.mark.parametrize( "dt", [np.datetime64("1000-01-01"), np.datetime64("5000-01-02")] )