datetimes.py 42 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272
  1. from __future__ import annotations
  2. from collections import abc
  3. from datetime import datetime
  4. from functools import partial
  5. from itertools import islice
  6. from typing import (
  7. TYPE_CHECKING,
  8. Callable,
  9. Hashable,
  10. List,
  11. Tuple,
  12. TypedDict,
  13. Union,
  14. cast,
  15. overload,
  16. )
  17. import warnings
  18. import numpy as np
  19. from pandas._libs import (
  20. lib,
  21. tslib,
  22. )
  23. from pandas._libs.tslibs import (
  24. OutOfBoundsDatetime,
  25. Timedelta,
  26. Timestamp,
  27. astype_overflowsafe,
  28. get_unit_from_dtype,
  29. iNaT,
  30. is_supported_unit,
  31. nat_strings,
  32. parsing,
  33. timezones as libtimezones,
  34. )
  35. from pandas._libs.tslibs.conversion import precision_from_unit
  36. from pandas._libs.tslibs.parsing import (
  37. DateParseError,
  38. guess_datetime_format,
  39. )
  40. from pandas._libs.tslibs.strptime import array_strptime
  41. from pandas._typing import (
  42. AnyArrayLike,
  43. ArrayLike,
  44. DateTimeErrorChoices,
  45. npt,
  46. )
  47. from pandas.util._exceptions import find_stack_level
  48. from pandas.core.dtypes.common import (
  49. ensure_object,
  50. is_datetime64_dtype,
  51. is_datetime64tz_dtype,
  52. is_float,
  53. is_integer,
  54. is_integer_dtype,
  55. is_list_like,
  56. is_numeric_dtype,
  57. is_scalar,
  58. )
  59. from pandas.core.dtypes.generic import (
  60. ABCDataFrame,
  61. ABCSeries,
  62. )
  63. from pandas.core.dtypes.missing import notna
  64. from pandas.arrays import (
  65. DatetimeArray,
  66. IntegerArray,
  67. PandasArray,
  68. )
  69. from pandas.core import algorithms
  70. from pandas.core.algorithms import unique
  71. from pandas.core.arrays.base import ExtensionArray
  72. from pandas.core.arrays.datetimes import (
  73. maybe_convert_dtype,
  74. objects_to_datetime64ns,
  75. tz_to_dtype,
  76. )
  77. from pandas.core.construction import extract_array
  78. from pandas.core.indexes.base import Index
  79. from pandas.core.indexes.datetimes import DatetimeIndex
  80. if TYPE_CHECKING:
  81. from pandas._libs.tslibs.nattype import NaTType
  82. from pandas._libs.tslibs.timedeltas import UnitChoices
  83. from pandas import (
  84. DataFrame,
  85. Series,
  86. )
  87. # ---------------------------------------------------------------------
  88. # types used in annotations
  89. ArrayConvertible = Union[List, Tuple, AnyArrayLike]
  90. Scalar = Union[float, str]
  91. DatetimeScalar = Union[Scalar, datetime]
  92. DatetimeScalarOrArrayConvertible = Union[DatetimeScalar, ArrayConvertible]
  93. DatetimeDictArg = Union[List[Scalar], Tuple[Scalar, ...], AnyArrayLike]
  94. class YearMonthDayDict(TypedDict, total=True):
  95. year: DatetimeDictArg
  96. month: DatetimeDictArg
  97. day: DatetimeDictArg
  98. class FulldatetimeDict(YearMonthDayDict, total=False):
  99. hour: DatetimeDictArg
  100. hours: DatetimeDictArg
  101. minute: DatetimeDictArg
  102. minutes: DatetimeDictArg
  103. second: DatetimeDictArg
  104. seconds: DatetimeDictArg
  105. ms: DatetimeDictArg
  106. us: DatetimeDictArg
  107. ns: DatetimeDictArg
  108. DictConvertible = Union[FulldatetimeDict, "DataFrame"]
  109. start_caching_at = 50
  110. # ---------------------------------------------------------------------
  111. def _guess_datetime_format_for_array(arr, dayfirst: bool | None = False) -> str | None:
  112. # Try to guess the format based on the first non-NaN element, return None if can't
  113. if (first_non_null := tslib.first_non_null(arr)) != -1:
  114. if type(first_non_nan_element := arr[first_non_null]) is str:
  115. # GH#32264 np.str_ object
  116. guessed_format = guess_datetime_format(
  117. first_non_nan_element, dayfirst=dayfirst
  118. )
  119. if guessed_format is not None:
  120. return guessed_format
  121. # If there are multiple non-null elements, warn about
  122. # how parsing might not be consistent
  123. if tslib.first_non_null(arr[first_non_null + 1 :]) != -1:
  124. warnings.warn(
  125. "Could not infer format, so each element will be parsed "
  126. "individually, falling back to `dateutil`. To ensure parsing is "
  127. "consistent and as-expected, please specify a format.",
  128. UserWarning,
  129. stacklevel=find_stack_level(),
  130. )
  131. return None
  132. def should_cache(
  133. arg: ArrayConvertible, unique_share: float = 0.7, check_count: int | None = None
  134. ) -> bool:
  135. """
  136. Decides whether to do caching.
  137. If the percent of unique elements among `check_count` elements less
  138. than `unique_share * 100` then we can do caching.
  139. Parameters
  140. ----------
  141. arg: listlike, tuple, 1-d array, Series
  142. unique_share: float, default=0.7, optional
  143. 0 < unique_share < 1
  144. check_count: int, optional
  145. 0 <= check_count <= len(arg)
  146. Returns
  147. -------
  148. do_caching: bool
  149. Notes
  150. -----
  151. By default for a sequence of less than 50 items in size, we don't do
  152. caching; for the number of elements less than 5000, we take ten percent of
  153. all elements to check for a uniqueness share; if the sequence size is more
  154. than 5000, then we check only the first 500 elements.
  155. All constants were chosen empirically by.
  156. """
  157. do_caching = True
  158. # default realization
  159. if check_count is None:
  160. # in this case, the gain from caching is negligible
  161. if len(arg) <= start_caching_at:
  162. return False
  163. if len(arg) <= 5000:
  164. check_count = len(arg) // 10
  165. else:
  166. check_count = 500
  167. else:
  168. assert (
  169. 0 <= check_count <= len(arg)
  170. ), "check_count must be in next bounds: [0; len(arg)]"
  171. if check_count == 0:
  172. return False
  173. assert 0 < unique_share < 1, "unique_share must be in next bounds: (0; 1)"
  174. try:
  175. # We can't cache if the items are not hashable.
  176. unique_elements = set(islice(arg, check_count))
  177. except TypeError:
  178. return False
  179. if len(unique_elements) > check_count * unique_share:
  180. do_caching = False
  181. return do_caching
  182. def _maybe_cache(
  183. arg: ArrayConvertible,
  184. format: str | None,
  185. cache: bool,
  186. convert_listlike: Callable,
  187. ) -> Series:
  188. """
  189. Create a cache of unique dates from an array of dates
  190. Parameters
  191. ----------
  192. arg : listlike, tuple, 1-d array, Series
  193. format : string
  194. Strftime format to parse time
  195. cache : bool
  196. True attempts to create a cache of converted values
  197. convert_listlike : function
  198. Conversion function to apply on dates
  199. Returns
  200. -------
  201. cache_array : Series
  202. Cache of converted, unique dates. Can be empty
  203. """
  204. from pandas import Series
  205. cache_array = Series(dtype=object)
  206. if cache:
  207. # Perform a quicker unique check
  208. if not should_cache(arg):
  209. return cache_array
  210. unique_dates = unique(arg)
  211. if len(unique_dates) < len(arg):
  212. cache_dates = convert_listlike(unique_dates, format)
  213. # GH#45319
  214. try:
  215. cache_array = Series(cache_dates, index=unique_dates, copy=False)
  216. except OutOfBoundsDatetime:
  217. return cache_array
  218. # GH#39882 and GH#35888 in case of None and NaT we get duplicates
  219. if not cache_array.index.is_unique:
  220. cache_array = cache_array[~cache_array.index.duplicated()]
  221. return cache_array
  222. def _box_as_indexlike(
  223. dt_array: ArrayLike, utc: bool = False, name: Hashable = None
  224. ) -> Index:
  225. """
  226. Properly boxes the ndarray of datetimes to DatetimeIndex
  227. if it is possible or to generic Index instead
  228. Parameters
  229. ----------
  230. dt_array: 1-d array
  231. Array of datetimes to be wrapped in an Index.
  232. utc : bool
  233. Whether to convert/localize timestamps to UTC.
  234. name : string, default None
  235. Name for a resulting index
  236. Returns
  237. -------
  238. result : datetime of converted dates
  239. - DatetimeIndex if convertible to sole datetime64 type
  240. - general Index otherwise
  241. """
  242. if is_datetime64_dtype(dt_array):
  243. tz = "utc" if utc else None
  244. return DatetimeIndex(dt_array, tz=tz, name=name)
  245. return Index(dt_array, name=name, dtype=dt_array.dtype)
  246. def _convert_and_box_cache(
  247. arg: DatetimeScalarOrArrayConvertible,
  248. cache_array: Series,
  249. name: Hashable | None = None,
  250. ) -> Index:
  251. """
  252. Convert array of dates with a cache and wrap the result in an Index.
  253. Parameters
  254. ----------
  255. arg : integer, float, string, datetime, list, tuple, 1-d array, Series
  256. cache_array : Series
  257. Cache of converted, unique dates
  258. name : string, default None
  259. Name for a DatetimeIndex
  260. Returns
  261. -------
  262. result : Index-like of converted dates
  263. """
  264. from pandas import Series
  265. result = Series(arg, dtype=cache_array.index.dtype).map(cache_array)
  266. return _box_as_indexlike(result._values, utc=False, name=name)
  267. def _return_parsed_timezone_results(
  268. result: np.ndarray, timezones, utc: bool, name
  269. ) -> Index:
  270. """
  271. Return results from array_strptime if a %z or %Z directive was passed.
  272. Parameters
  273. ----------
  274. result : ndarray[int64]
  275. int64 date representations of the dates
  276. timezones : ndarray
  277. pytz timezone objects
  278. utc : bool
  279. Whether to convert/localize timestamps to UTC.
  280. name : string, default None
  281. Name for a DatetimeIndex
  282. Returns
  283. -------
  284. tz_result : Index-like of parsed dates with timezone
  285. """
  286. tz_results = np.empty(len(result), dtype=object)
  287. for zone in unique(timezones):
  288. mask = timezones == zone
  289. dta = DatetimeArray(result[mask]).tz_localize(zone)
  290. if utc:
  291. if dta.tzinfo is None:
  292. dta = dta.tz_localize("utc")
  293. else:
  294. dta = dta.tz_convert("utc")
  295. tz_results[mask] = dta
  296. return Index(tz_results, name=name)
  297. def _convert_listlike_datetimes(
  298. arg,
  299. format: str | None,
  300. name: Hashable = None,
  301. utc: bool = False,
  302. unit: str | None = None,
  303. errors: DateTimeErrorChoices = "raise",
  304. dayfirst: bool | None = None,
  305. yearfirst: bool | None = None,
  306. exact: bool = True,
  307. ):
  308. """
  309. Helper function for to_datetime. Performs the conversions of 1D listlike
  310. of dates
  311. Parameters
  312. ----------
  313. arg : list, tuple, ndarray, Series, Index
  314. date to be parsed
  315. name : object
  316. None or string for the Index name
  317. utc : bool
  318. Whether to convert/localize timestamps to UTC.
  319. unit : str
  320. None or string of the frequency of the passed data
  321. errors : str
  322. error handing behaviors from to_datetime, 'raise', 'coerce', 'ignore'
  323. dayfirst : bool
  324. dayfirst parsing behavior from to_datetime
  325. yearfirst : bool
  326. yearfirst parsing behavior from to_datetime
  327. exact : bool, default True
  328. exact format matching behavior from to_datetime
  329. Returns
  330. -------
  331. Index-like of parsed dates
  332. """
  333. if isinstance(arg, (list, tuple)):
  334. arg = np.array(arg, dtype="O")
  335. elif isinstance(arg, PandasArray):
  336. arg = np.array(arg)
  337. arg_dtype = getattr(arg, "dtype", None)
  338. # these are shortcutable
  339. tz = "utc" if utc else None
  340. if is_datetime64tz_dtype(arg_dtype):
  341. if not isinstance(arg, (DatetimeArray, DatetimeIndex)):
  342. return DatetimeIndex(arg, tz=tz, name=name)
  343. if utc:
  344. arg = arg.tz_convert(None).tz_localize("utc")
  345. return arg
  346. elif is_datetime64_dtype(arg_dtype):
  347. arg_dtype = cast(np.dtype, arg_dtype)
  348. if not is_supported_unit(get_unit_from_dtype(arg_dtype)):
  349. # We go to closest supported reso, i.e. "s"
  350. arg = astype_overflowsafe(
  351. # TODO: looks like we incorrectly raise with errors=="ignore"
  352. np.asarray(arg),
  353. np.dtype("M8[s]"),
  354. is_coerce=errors == "coerce",
  355. )
  356. if not isinstance(arg, (DatetimeArray, DatetimeIndex)):
  357. return DatetimeIndex(arg, tz=tz, name=name)
  358. elif utc:
  359. # DatetimeArray, DatetimeIndex
  360. return arg.tz_localize("utc")
  361. return arg
  362. elif unit is not None:
  363. if format is not None:
  364. raise ValueError("cannot specify both format and unit")
  365. return _to_datetime_with_unit(arg, unit, name, utc, errors)
  366. elif getattr(arg, "ndim", 1) > 1:
  367. raise TypeError(
  368. "arg must be a string, datetime, list, tuple, 1-d array, or Series"
  369. )
  370. # warn if passing timedelta64, raise for PeriodDtype
  371. # NB: this must come after unit transformation
  372. try:
  373. arg, _ = maybe_convert_dtype(arg, copy=False, tz=libtimezones.maybe_get_tz(tz))
  374. except TypeError:
  375. if errors == "coerce":
  376. npvalues = np.array(["NaT"], dtype="datetime64[ns]").repeat(len(arg))
  377. return DatetimeIndex(npvalues, name=name)
  378. elif errors == "ignore":
  379. idx = Index(arg, name=name)
  380. return idx
  381. raise
  382. arg = ensure_object(arg)
  383. if format is None:
  384. format = _guess_datetime_format_for_array(arg, dayfirst=dayfirst)
  385. # `format` could be inferred, or user didn't ask for mixed-format parsing.
  386. if format is not None and format != "mixed":
  387. return _array_strptime_with_fallback(arg, name, utc, format, exact, errors)
  388. result, tz_parsed = objects_to_datetime64ns(
  389. arg,
  390. dayfirst=dayfirst,
  391. yearfirst=yearfirst,
  392. utc=utc,
  393. errors=errors,
  394. allow_object=True,
  395. )
  396. if tz_parsed is not None:
  397. # We can take a shortcut since the datetime64 numpy array
  398. # is in UTC
  399. dta = DatetimeArray(result, dtype=tz_to_dtype(tz_parsed))
  400. return DatetimeIndex._simple_new(dta, name=name)
  401. return _box_as_indexlike(result, utc=utc, name=name)
  402. def _array_strptime_with_fallback(
  403. arg,
  404. name,
  405. utc: bool,
  406. fmt: str,
  407. exact: bool,
  408. errors: str,
  409. ) -> Index:
  410. """
  411. Call array_strptime, with fallback behavior depending on 'errors'.
  412. """
  413. result, timezones = array_strptime(arg, fmt, exact=exact, errors=errors, utc=utc)
  414. if any(tz is not None for tz in timezones):
  415. return _return_parsed_timezone_results(result, timezones, utc, name)
  416. return _box_as_indexlike(result, utc=utc, name=name)
  417. def _to_datetime_with_unit(arg, unit, name, utc: bool, errors: str) -> Index:
  418. """
  419. to_datetime specalized to the case where a 'unit' is passed.
  420. """
  421. arg = extract_array(arg, extract_numpy=True)
  422. # GH#30050 pass an ndarray to tslib.array_with_unit_to_datetime
  423. # because it expects an ndarray argument
  424. if isinstance(arg, IntegerArray):
  425. arr = arg.astype(f"datetime64[{unit}]")
  426. tz_parsed = None
  427. else:
  428. arg = np.asarray(arg)
  429. if arg.dtype.kind in ["i", "u"]:
  430. # Note we can't do "f" here because that could induce unwanted
  431. # rounding GH#14156, GH#20445
  432. arr = arg.astype(f"datetime64[{unit}]", copy=False)
  433. try:
  434. arr = astype_overflowsafe(arr, np.dtype("M8[ns]"), copy=False)
  435. except OutOfBoundsDatetime:
  436. if errors == "raise":
  437. raise
  438. arg = arg.astype(object)
  439. return _to_datetime_with_unit(arg, unit, name, utc, errors)
  440. tz_parsed = None
  441. elif arg.dtype.kind == "f":
  442. mult, _ = precision_from_unit(unit)
  443. mask = np.isnan(arg) | (arg == iNaT)
  444. fvalues = (arg * mult).astype("f8", copy=False)
  445. fvalues[mask] = 0
  446. if (fvalues < Timestamp.min._value).any() or (
  447. fvalues > Timestamp.max._value
  448. ).any():
  449. if errors != "raise":
  450. arg = arg.astype(object)
  451. return _to_datetime_with_unit(arg, unit, name, utc, errors)
  452. raise OutOfBoundsDatetime(f"cannot convert input with unit '{unit}'")
  453. arr = fvalues.astype("M8[ns]", copy=False)
  454. arr[mask] = np.datetime64("NaT", "ns")
  455. tz_parsed = None
  456. else:
  457. arg = arg.astype(object, copy=False)
  458. arr, tz_parsed = tslib.array_with_unit_to_datetime(arg, unit, errors=errors)
  459. if errors == "ignore":
  460. # Index constructor _may_ infer to DatetimeIndex
  461. result = Index._with_infer(arr, name=name)
  462. else:
  463. result = DatetimeIndex(arr, name=name)
  464. if not isinstance(result, DatetimeIndex):
  465. return result
  466. # GH#23758: We may still need to localize the result with tz
  467. # GH#25546: Apply tz_parsed first (from arg), then tz (from caller)
  468. # result will be naive but in UTC
  469. result = result.tz_localize("UTC").tz_convert(tz_parsed)
  470. if utc:
  471. if result.tz is None:
  472. result = result.tz_localize("utc")
  473. else:
  474. result = result.tz_convert("utc")
  475. return result
  476. def _adjust_to_origin(arg, origin, unit):
  477. """
  478. Helper function for to_datetime.
  479. Adjust input argument to the specified origin
  480. Parameters
  481. ----------
  482. arg : list, tuple, ndarray, Series, Index
  483. date to be adjusted
  484. origin : 'julian' or Timestamp
  485. origin offset for the arg
  486. unit : str
  487. passed unit from to_datetime, must be 'D'
  488. Returns
  489. -------
  490. ndarray or scalar of adjusted date(s)
  491. """
  492. if origin == "julian":
  493. original = arg
  494. j0 = Timestamp(0).to_julian_date()
  495. if unit != "D":
  496. raise ValueError("unit must be 'D' for origin='julian'")
  497. try:
  498. arg = arg - j0
  499. except TypeError as err:
  500. raise ValueError(
  501. "incompatible 'arg' type for given 'origin'='julian'"
  502. ) from err
  503. # preemptively check this for a nice range
  504. j_max = Timestamp.max.to_julian_date() - j0
  505. j_min = Timestamp.min.to_julian_date() - j0
  506. if np.any(arg > j_max) or np.any(arg < j_min):
  507. raise OutOfBoundsDatetime(
  508. f"{original} is Out of Bounds for origin='julian'"
  509. )
  510. else:
  511. # arg must be numeric
  512. if not (
  513. (is_scalar(arg) and (is_integer(arg) or is_float(arg)))
  514. or is_numeric_dtype(np.asarray(arg))
  515. ):
  516. raise ValueError(
  517. f"'{arg}' is not compatible with origin='{origin}'; "
  518. "it must be numeric with a unit specified"
  519. )
  520. # we are going to offset back to unix / epoch time
  521. try:
  522. offset = Timestamp(origin, unit=unit)
  523. except OutOfBoundsDatetime as err:
  524. raise OutOfBoundsDatetime(f"origin {origin} is Out of Bounds") from err
  525. except ValueError as err:
  526. raise ValueError(
  527. f"origin {origin} cannot be converted to a Timestamp"
  528. ) from err
  529. if offset.tz is not None:
  530. raise ValueError(f"origin offset {offset} must be tz-naive")
  531. td_offset = offset - Timestamp(0)
  532. # convert the offset to the unit of the arg
  533. # this should be lossless in terms of precision
  534. ioffset = td_offset // Timedelta(1, unit=unit)
  535. # scalars & ndarray-like can handle the addition
  536. if is_list_like(arg) and not isinstance(arg, (ABCSeries, Index, np.ndarray)):
  537. arg = np.asarray(arg)
  538. arg = arg + ioffset
  539. return arg
  540. @overload
  541. def to_datetime(
  542. arg: DatetimeScalar,
  543. errors: DateTimeErrorChoices = ...,
  544. dayfirst: bool = ...,
  545. yearfirst: bool = ...,
  546. utc: bool = ...,
  547. format: str | None = ...,
  548. exact: bool = ...,
  549. unit: str | None = ...,
  550. infer_datetime_format: bool = ...,
  551. origin=...,
  552. cache: bool = ...,
  553. ) -> Timestamp:
  554. ...
  555. @overload
  556. def to_datetime(
  557. arg: Series | DictConvertible,
  558. errors: DateTimeErrorChoices = ...,
  559. dayfirst: bool = ...,
  560. yearfirst: bool = ...,
  561. utc: bool = ...,
  562. format: str | None = ...,
  563. exact: bool = ...,
  564. unit: str | None = ...,
  565. infer_datetime_format: bool = ...,
  566. origin=...,
  567. cache: bool = ...,
  568. ) -> Series:
  569. ...
  570. @overload
  571. def to_datetime(
  572. arg: list | tuple | Index | ArrayLike,
  573. errors: DateTimeErrorChoices = ...,
  574. dayfirst: bool = ...,
  575. yearfirst: bool = ...,
  576. utc: bool = ...,
  577. format: str | None = ...,
  578. exact: bool = ...,
  579. unit: str | None = ...,
  580. infer_datetime_format: bool = ...,
  581. origin=...,
  582. cache: bool = ...,
  583. ) -> DatetimeIndex:
  584. ...
  585. def to_datetime(
  586. arg: DatetimeScalarOrArrayConvertible | DictConvertible,
  587. errors: DateTimeErrorChoices = "raise",
  588. dayfirst: bool = False,
  589. yearfirst: bool = False,
  590. utc: bool = False,
  591. format: str | None = None,
  592. exact: bool | lib.NoDefault = lib.no_default,
  593. unit: str | None = None,
  594. infer_datetime_format: lib.NoDefault | bool = lib.no_default,
  595. origin: str = "unix",
  596. cache: bool = True,
  597. ) -> DatetimeIndex | Series | DatetimeScalar | NaTType | None:
  598. """
  599. Convert argument to datetime.
  600. This function converts a scalar, array-like, :class:`Series` or
  601. :class:`DataFrame`/dict-like to a pandas datetime object.
  602. Parameters
  603. ----------
  604. arg : int, float, str, datetime, list, tuple, 1-d array, Series, DataFrame/dict-like
  605. The object to convert to a datetime. If a :class:`DataFrame` is provided, the
  606. method expects minimally the following columns: :const:`"year"`,
  607. :const:`"month"`, :const:`"day"`.
  608. errors : {'ignore', 'raise', 'coerce'}, default 'raise'
  609. - If :const:`'raise'`, then invalid parsing will raise an exception.
  610. - If :const:`'coerce'`, then invalid parsing will be set as :const:`NaT`.
  611. - If :const:`'ignore'`, then invalid parsing will return the input.
  612. dayfirst : bool, default False
  613. Specify a date parse order if `arg` is str or is list-like.
  614. If :const:`True`, parses dates with the day first, e.g. :const:`"10/11/12"`
  615. is parsed as :const:`2012-11-10`.
  616. .. warning::
  617. ``dayfirst=True`` is not strict, but will prefer to parse
  618. with day first.
  619. yearfirst : bool, default False
  620. Specify a date parse order if `arg` is str or is list-like.
  621. - If :const:`True` parses dates with the year first, e.g.
  622. :const:`"10/11/12"` is parsed as :const:`2010-11-12`.
  623. - If both `dayfirst` and `yearfirst` are :const:`True`, `yearfirst` is
  624. preceded (same as :mod:`dateutil`).
  625. .. warning::
  626. ``yearfirst=True`` is not strict, but will prefer to parse
  627. with year first.
  628. utc : bool, default False
  629. Control timezone-related parsing, localization and conversion.
  630. - If :const:`True`, the function *always* returns a timezone-aware
  631. UTC-localized :class:`Timestamp`, :class:`Series` or
  632. :class:`DatetimeIndex`. To do this, timezone-naive inputs are
  633. *localized* as UTC, while timezone-aware inputs are *converted* to UTC.
  634. - If :const:`False` (default), inputs will not be coerced to UTC.
  635. Timezone-naive inputs will remain naive, while timezone-aware ones
  636. will keep their time offsets. Limitations exist for mixed
  637. offsets (typically, daylight savings), see :ref:`Examples
  638. <to_datetime_tz_examples>` section for details.
  639. See also: pandas general documentation about `timezone conversion and
  640. localization
  641. <https://pandas.pydata.org/pandas-docs/stable/user_guide/timeseries.html
  642. #time-zone-handling>`_.
  643. format : str, default None
  644. The strftime to parse time, e.g. :const:`"%d/%m/%Y"`. See
  645. `strftime documentation
  646. <https://docs.python.org/3/library/datetime.html
  647. #strftime-and-strptime-behavior>`_ for more information on choices, though
  648. note that :const:`"%f"` will parse all the way up to nanoseconds.
  649. You can also pass:
  650. - "ISO8601", to parse any `ISO8601 <https://en.wikipedia.org/wiki/ISO_8601>`_
  651. time string (not necessarily in exactly the same format);
  652. - "mixed", to infer the format for each element individually. This is risky,
  653. and you should probably use it along with `dayfirst`.
  654. exact : bool, default True
  655. Control how `format` is used:
  656. - If :const:`True`, require an exact `format` match.
  657. - If :const:`False`, allow the `format` to match anywhere in the target
  658. string.
  659. Cannot be used alongside ``format='ISO8601'`` or ``format='mixed'``.
  660. unit : str, default 'ns'
  661. The unit of the arg (D,s,ms,us,ns) denote the unit, which is an
  662. integer or float number. This will be based off the origin.
  663. Example, with ``unit='ms'`` and ``origin='unix'``, this would calculate
  664. the number of milliseconds to the unix epoch start.
  665. infer_datetime_format : bool, default False
  666. If :const:`True` and no `format` is given, attempt to infer the format
  667. of the datetime strings based on the first non-NaN element,
  668. and if it can be inferred, switch to a faster method of parsing them.
  669. In some cases this can increase the parsing speed by ~5-10x.
  670. .. deprecated:: 2.0.0
  671. A strict version of this argument is now the default, passing it has
  672. no effect.
  673. origin : scalar, default 'unix'
  674. Define the reference date. The numeric values would be parsed as number
  675. of units (defined by `unit`) since this reference date.
  676. - If :const:`'unix'` (or POSIX) time; origin is set to 1970-01-01.
  677. - If :const:`'julian'`, unit must be :const:`'D'`, and origin is set to
  678. beginning of Julian Calendar. Julian day number :const:`0` is assigned
  679. to the day starting at noon on January 1, 4713 BC.
  680. - If Timestamp convertible (Timestamp, dt.datetime, np.datetimt64 or date
  681. string), origin is set to Timestamp identified by origin.
  682. - If a float or integer, origin is the millisecond difference
  683. relative to 1970-01-01.
  684. cache : bool, default True
  685. If :const:`True`, use a cache of unique, converted dates to apply the
  686. datetime conversion. May produce significant speed-up when parsing
  687. duplicate date strings, especially ones with timezone offsets. The cache
  688. is only used when there are at least 50 values. The presence of
  689. out-of-bounds values will render the cache unusable and may slow down
  690. parsing.
  691. Returns
  692. -------
  693. datetime
  694. If parsing succeeded.
  695. Return type depends on input (types in parenthesis correspond to
  696. fallback in case of unsuccessful timezone or out-of-range timestamp
  697. parsing):
  698. - scalar: :class:`Timestamp` (or :class:`datetime.datetime`)
  699. - array-like: :class:`DatetimeIndex` (or :class:`Series` with
  700. :class:`object` dtype containing :class:`datetime.datetime`)
  701. - Series: :class:`Series` of :class:`datetime64` dtype (or
  702. :class:`Series` of :class:`object` dtype containing
  703. :class:`datetime.datetime`)
  704. - DataFrame: :class:`Series` of :class:`datetime64` dtype (or
  705. :class:`Series` of :class:`object` dtype containing
  706. :class:`datetime.datetime`)
  707. Raises
  708. ------
  709. ParserError
  710. When parsing a date from string fails.
  711. ValueError
  712. When another datetime conversion error happens. For example when one
  713. of 'year', 'month', day' columns is missing in a :class:`DataFrame`, or
  714. when a Timezone-aware :class:`datetime.datetime` is found in an array-like
  715. of mixed time offsets, and ``utc=False``.
  716. See Also
  717. --------
  718. DataFrame.astype : Cast argument to a specified dtype.
  719. to_timedelta : Convert argument to timedelta.
  720. convert_dtypes : Convert dtypes.
  721. Notes
  722. -----
  723. Many input types are supported, and lead to different output types:
  724. - **scalars** can be int, float, str, datetime object (from stdlib :mod:`datetime`
  725. module or :mod:`numpy`). They are converted to :class:`Timestamp` when
  726. possible, otherwise they are converted to :class:`datetime.datetime`.
  727. None/NaN/null scalars are converted to :const:`NaT`.
  728. - **array-like** can contain int, float, str, datetime objects. They are
  729. converted to :class:`DatetimeIndex` when possible, otherwise they are
  730. converted to :class:`Index` with :class:`object` dtype, containing
  731. :class:`datetime.datetime`. None/NaN/null entries are converted to
  732. :const:`NaT` in both cases.
  733. - **Series** are converted to :class:`Series` with :class:`datetime64`
  734. dtype when possible, otherwise they are converted to :class:`Series` with
  735. :class:`object` dtype, containing :class:`datetime.datetime`. None/NaN/null
  736. entries are converted to :const:`NaT` in both cases.
  737. - **DataFrame/dict-like** are converted to :class:`Series` with
  738. :class:`datetime64` dtype. For each row a datetime is created from assembling
  739. the various dataframe columns. Column keys can be common abbreviations
  740. like [‘year’, ‘month’, ‘day’, ‘minute’, ‘second’, ‘ms’, ‘us’, ‘ns’]) or
  741. plurals of the same.
  742. The following causes are responsible for :class:`datetime.datetime` objects
  743. being returned (possibly inside an :class:`Index` or a :class:`Series` with
  744. :class:`object` dtype) instead of a proper pandas designated type
  745. (:class:`Timestamp`, :class:`DatetimeIndex` or :class:`Series`
  746. with :class:`datetime64` dtype):
  747. - when any input element is before :const:`Timestamp.min` or after
  748. :const:`Timestamp.max`, see `timestamp limitations
  749. <https://pandas.pydata.org/pandas-docs/stable/user_guide/timeseries.html
  750. #timeseries-timestamp-limits>`_.
  751. - when ``utc=False`` (default) and the input is an array-like or
  752. :class:`Series` containing mixed naive/aware datetime, or aware with mixed
  753. time offsets. Note that this happens in the (quite frequent) situation when
  754. the timezone has a daylight savings policy. In that case you may wish to
  755. use ``utc=True``.
  756. Examples
  757. --------
  758. **Handling various input formats**
  759. Assembling a datetime from multiple columns of a :class:`DataFrame`. The keys
  760. can be common abbreviations like ['year', 'month', 'day', 'minute', 'second',
  761. 'ms', 'us', 'ns']) or plurals of the same
  762. >>> df = pd.DataFrame({'year': [2015, 2016],
  763. ... 'month': [2, 3],
  764. ... 'day': [4, 5]})
  765. >>> pd.to_datetime(df)
  766. 0 2015-02-04
  767. 1 2016-03-05
  768. dtype: datetime64[ns]
  769. Using a unix epoch time
  770. >>> pd.to_datetime(1490195805, unit='s')
  771. Timestamp('2017-03-22 15:16:45')
  772. >>> pd.to_datetime(1490195805433502912, unit='ns')
  773. Timestamp('2017-03-22 15:16:45.433502912')
  774. .. warning:: For float arg, precision rounding might happen. To prevent
  775. unexpected behavior use a fixed-width exact type.
  776. Using a non-unix epoch origin
  777. >>> pd.to_datetime([1, 2, 3], unit='D',
  778. ... origin=pd.Timestamp('1960-01-01'))
  779. DatetimeIndex(['1960-01-02', '1960-01-03', '1960-01-04'],
  780. dtype='datetime64[ns]', freq=None)
  781. **Differences with strptime behavior**
  782. :const:`"%f"` will parse all the way up to nanoseconds.
  783. >>> pd.to_datetime('2018-10-26 12:00:00.0000000011',
  784. ... format='%Y-%m-%d %H:%M:%S.%f')
  785. Timestamp('2018-10-26 12:00:00.000000001')
  786. **Non-convertible date/times**
  787. If a date does not meet the `timestamp limitations
  788. <https://pandas.pydata.org/pandas-docs/stable/user_guide/timeseries.html
  789. #timeseries-timestamp-limits>`_, passing ``errors='ignore'``
  790. will return the original input instead of raising any exception.
  791. Passing ``errors='coerce'`` will force an out-of-bounds date to :const:`NaT`,
  792. in addition to forcing non-dates (or non-parseable dates) to :const:`NaT`.
  793. >>> pd.to_datetime('13000101', format='%Y%m%d', errors='ignore')
  794. '13000101'
  795. >>> pd.to_datetime('13000101', format='%Y%m%d', errors='coerce')
  796. NaT
  797. .. _to_datetime_tz_examples:
  798. **Timezones and time offsets**
  799. The default behaviour (``utc=False``) is as follows:
  800. - Timezone-naive inputs are converted to timezone-naive :class:`DatetimeIndex`:
  801. >>> pd.to_datetime(['2018-10-26 12:00:00', '2018-10-26 13:00:15'])
  802. DatetimeIndex(['2018-10-26 12:00:00', '2018-10-26 13:00:15'],
  803. dtype='datetime64[ns]', freq=None)
  804. - Timezone-aware inputs *with constant time offset* are converted to
  805. timezone-aware :class:`DatetimeIndex`:
  806. >>> pd.to_datetime(['2018-10-26 12:00 -0500', '2018-10-26 13:00 -0500'])
  807. DatetimeIndex(['2018-10-26 12:00:00-05:00', '2018-10-26 13:00:00-05:00'],
  808. dtype='datetime64[ns, UTC-05:00]', freq=None)
  809. - However, timezone-aware inputs *with mixed time offsets* (for example
  810. issued from a timezone with daylight savings, such as Europe/Paris)
  811. are **not successfully converted** to a :class:`DatetimeIndex`. Instead a
  812. simple :class:`Index` containing :class:`datetime.datetime` objects is
  813. returned:
  814. >>> pd.to_datetime(['2020-10-25 02:00 +0200', '2020-10-25 04:00 +0100'])
  815. Index([2020-10-25 02:00:00+02:00, 2020-10-25 04:00:00+01:00],
  816. dtype='object')
  817. - A mix of timezone-aware and timezone-naive inputs is also converted to
  818. a simple :class:`Index` containing :class:`datetime.datetime` objects:
  819. >>> from datetime import datetime
  820. >>> pd.to_datetime(["2020-01-01 01:00:00-01:00", datetime(2020, 1, 1, 3, 0)])
  821. Index([2020-01-01 01:00:00-01:00, 2020-01-01 03:00:00], dtype='object')
  822. |
  823. Setting ``utc=True`` solves most of the above issues:
  824. - Timezone-naive inputs are *localized* as UTC
  825. >>> pd.to_datetime(['2018-10-26 12:00', '2018-10-26 13:00'], utc=True)
  826. DatetimeIndex(['2018-10-26 12:00:00+00:00', '2018-10-26 13:00:00+00:00'],
  827. dtype='datetime64[ns, UTC]', freq=None)
  828. - Timezone-aware inputs are *converted* to UTC (the output represents the
  829. exact same datetime, but viewed from the UTC time offset `+00:00`).
  830. >>> pd.to_datetime(['2018-10-26 12:00 -0530', '2018-10-26 12:00 -0500'],
  831. ... utc=True)
  832. DatetimeIndex(['2018-10-26 17:30:00+00:00', '2018-10-26 17:00:00+00:00'],
  833. dtype='datetime64[ns, UTC]', freq=None)
  834. - Inputs can contain both string or datetime, the above
  835. rules still apply
  836. >>> pd.to_datetime(['2018-10-26 12:00', datetime(2020, 1, 1, 18)], utc=True)
  837. DatetimeIndex(['2018-10-26 12:00:00+00:00', '2020-01-01 18:00:00+00:00'],
  838. dtype='datetime64[ns, UTC]', freq=None)
  839. """
  840. if exact is not lib.no_default and format in {"mixed", "ISO8601"}:
  841. raise ValueError("Cannot use 'exact' when 'format' is 'mixed' or 'ISO8601'")
  842. if infer_datetime_format is not lib.no_default:
  843. warnings.warn(
  844. "The argument 'infer_datetime_format' is deprecated and will "
  845. "be removed in a future version. "
  846. "A strict version of it is now the default, see "
  847. "https://pandas.pydata.org/pdeps/0004-consistent-to-datetime-parsing.html. "
  848. "You can safely remove this argument.",
  849. stacklevel=find_stack_level(),
  850. )
  851. if arg is None:
  852. return None
  853. if origin != "unix":
  854. arg = _adjust_to_origin(arg, origin, unit)
  855. convert_listlike = partial(
  856. _convert_listlike_datetimes,
  857. utc=utc,
  858. unit=unit,
  859. dayfirst=dayfirst,
  860. yearfirst=yearfirst,
  861. errors=errors,
  862. exact=exact,
  863. )
  864. # pylint: disable-next=used-before-assignment
  865. result: Timestamp | NaTType | Series | Index
  866. if isinstance(arg, Timestamp):
  867. result = arg
  868. if utc:
  869. if arg.tz is not None:
  870. result = arg.tz_convert("utc")
  871. else:
  872. result = arg.tz_localize("utc")
  873. elif isinstance(arg, ABCSeries):
  874. cache_array = _maybe_cache(arg, format, cache, convert_listlike)
  875. if not cache_array.empty:
  876. result = arg.map(cache_array)
  877. else:
  878. values = convert_listlike(arg._values, format)
  879. result = arg._constructor(values, index=arg.index, name=arg.name)
  880. elif isinstance(arg, (ABCDataFrame, abc.MutableMapping)):
  881. result = _assemble_from_unit_mappings(arg, errors, utc)
  882. elif isinstance(arg, Index):
  883. cache_array = _maybe_cache(arg, format, cache, convert_listlike)
  884. if not cache_array.empty:
  885. result = _convert_and_box_cache(arg, cache_array, name=arg.name)
  886. else:
  887. result = convert_listlike(arg, format, name=arg.name)
  888. elif is_list_like(arg):
  889. try:
  890. # error: Argument 1 to "_maybe_cache" has incompatible type
  891. # "Union[float, str, datetime, List[Any], Tuple[Any, ...], ExtensionArray,
  892. # ndarray[Any, Any], Series]"; expected "Union[List[Any], Tuple[Any, ...],
  893. # Union[Union[ExtensionArray, ndarray[Any, Any]], Index, Series], Series]"
  894. argc = cast(
  895. Union[list, tuple, ExtensionArray, np.ndarray, "Series", Index], arg
  896. )
  897. cache_array = _maybe_cache(argc, format, cache, convert_listlike)
  898. except OutOfBoundsDatetime:
  899. # caching attempts to create a DatetimeIndex, which may raise
  900. # an OOB. If that's the desired behavior, then just reraise...
  901. if errors == "raise":
  902. raise
  903. # ... otherwise, continue without the cache.
  904. from pandas import Series
  905. cache_array = Series([], dtype=object) # just an empty array
  906. if not cache_array.empty:
  907. result = _convert_and_box_cache(argc, cache_array)
  908. else:
  909. result = convert_listlike(argc, format)
  910. else:
  911. result = convert_listlike(np.array([arg]), format)[0]
  912. if isinstance(arg, bool) and isinstance(result, np.bool_):
  913. result = bool(result) # TODO: avoid this kludge.
  914. # error: Incompatible return value type (got "Union[Timestamp, NaTType,
  915. # Series, Index]", expected "Union[DatetimeIndex, Series, float, str,
  916. # NaTType, None]")
  917. return result # type: ignore[return-value]
  918. # mappings for assembling units
  919. _unit_map = {
  920. "year": "year",
  921. "years": "year",
  922. "month": "month",
  923. "months": "month",
  924. "day": "day",
  925. "days": "day",
  926. "hour": "h",
  927. "hours": "h",
  928. "minute": "m",
  929. "minutes": "m",
  930. "second": "s",
  931. "seconds": "s",
  932. "ms": "ms",
  933. "millisecond": "ms",
  934. "milliseconds": "ms",
  935. "us": "us",
  936. "microsecond": "us",
  937. "microseconds": "us",
  938. "ns": "ns",
  939. "nanosecond": "ns",
  940. "nanoseconds": "ns",
  941. }
  942. def _assemble_from_unit_mappings(arg, errors: DateTimeErrorChoices, utc: bool):
  943. """
  944. assemble the unit specified fields from the arg (DataFrame)
  945. Return a Series for actual parsing
  946. Parameters
  947. ----------
  948. arg : DataFrame
  949. errors : {'ignore', 'raise', 'coerce'}, default 'raise'
  950. - If :const:`'raise'`, then invalid parsing will raise an exception
  951. - If :const:`'coerce'`, then invalid parsing will be set as :const:`NaT`
  952. - If :const:`'ignore'`, then invalid parsing will return the input
  953. utc : bool
  954. Whether to convert/localize timestamps to UTC.
  955. Returns
  956. -------
  957. Series
  958. """
  959. from pandas import (
  960. DataFrame,
  961. to_numeric,
  962. to_timedelta,
  963. )
  964. arg = DataFrame(arg)
  965. if not arg.columns.is_unique:
  966. raise ValueError("cannot assemble with duplicate keys")
  967. # replace passed unit with _unit_map
  968. def f(value):
  969. if value in _unit_map:
  970. return _unit_map[value]
  971. # m is case significant
  972. if value.lower() in _unit_map:
  973. return _unit_map[value.lower()]
  974. return value
  975. unit = {k: f(k) for k in arg.keys()}
  976. unit_rev = {v: k for k, v in unit.items()}
  977. # we require at least Ymd
  978. required = ["year", "month", "day"]
  979. req = sorted(set(required) - set(unit_rev.keys()))
  980. if len(req):
  981. _required = ",".join(req)
  982. raise ValueError(
  983. "to assemble mappings requires at least that "
  984. f"[year, month, day] be specified: [{_required}] is missing"
  985. )
  986. # keys we don't recognize
  987. excess = sorted(set(unit_rev.keys()) - set(_unit_map.values()))
  988. if len(excess):
  989. _excess = ",".join(excess)
  990. raise ValueError(
  991. f"extra keys have been passed to the datetime assemblage: [{_excess}]"
  992. )
  993. def coerce(values):
  994. # we allow coercion to if errors allows
  995. values = to_numeric(values, errors=errors)
  996. # prevent overflow in case of int8 or int16
  997. if is_integer_dtype(values):
  998. values = values.astype("int64", copy=False)
  999. return values
  1000. values = (
  1001. coerce(arg[unit_rev["year"]]) * 10000
  1002. + coerce(arg[unit_rev["month"]]) * 100
  1003. + coerce(arg[unit_rev["day"]])
  1004. )
  1005. try:
  1006. values = to_datetime(values, format="%Y%m%d", errors=errors, utc=utc)
  1007. except (TypeError, ValueError) as err:
  1008. raise ValueError(f"cannot assemble the datetimes: {err}") from err
  1009. units: list[UnitChoices] = ["h", "m", "s", "ms", "us", "ns"]
  1010. for u in units:
  1011. value = unit_rev.get(u)
  1012. if value is not None and value in arg:
  1013. try:
  1014. values += to_timedelta(coerce(arg[value]), unit=u, errors=errors)
  1015. except (TypeError, ValueError) as err:
  1016. raise ValueError(
  1017. f"cannot assemble the datetimes [{value}]: {err}"
  1018. ) from err
  1019. return values
  1020. def _attempt_YYYYMMDD(arg: npt.NDArray[np.object_], errors: str) -> np.ndarray | None:
  1021. """
  1022. try to parse the YYYYMMDD/%Y%m%d format, try to deal with NaT-like,
  1023. arg is a passed in as an object dtype, but could really be ints/strings
  1024. with nan-like/or floats (e.g. with nan)
  1025. Parameters
  1026. ----------
  1027. arg : np.ndarray[object]
  1028. errors : {'raise','ignore','coerce'}
  1029. """
  1030. def calc(carg):
  1031. # calculate the actual result
  1032. carg = carg.astype(object, copy=False)
  1033. parsed = parsing.try_parse_year_month_day(
  1034. carg / 10000, carg / 100 % 100, carg % 100
  1035. )
  1036. return tslib.array_to_datetime(parsed, errors=errors)[0]
  1037. def calc_with_mask(carg, mask):
  1038. result = np.empty(carg.shape, dtype="M8[ns]")
  1039. iresult = result.view("i8")
  1040. iresult[~mask] = iNaT
  1041. masked_result = calc(carg[mask].astype(np.float64).astype(np.int64))
  1042. result[mask] = masked_result.astype("M8[ns]")
  1043. return result
  1044. # try intlike / strings that are ints
  1045. try:
  1046. return calc(arg.astype(np.int64))
  1047. except (ValueError, OverflowError, TypeError):
  1048. pass
  1049. # a float with actual np.nan
  1050. try:
  1051. carg = arg.astype(np.float64)
  1052. return calc_with_mask(carg, notna(carg))
  1053. except (ValueError, OverflowError, TypeError):
  1054. pass
  1055. # string with NaN-like
  1056. try:
  1057. # error: Argument 2 to "isin" has incompatible type "List[Any]"; expected
  1058. # "Union[Union[ExtensionArray, ndarray], Index, Series]"
  1059. mask = ~algorithms.isin(arg, list(nat_strings)) # type: ignore[arg-type]
  1060. return calc_with_mask(arg, mask)
  1061. except (ValueError, OverflowError, TypeError):
  1062. pass
  1063. return None
  1064. __all__ = [
  1065. "DateParseError",
  1066. "should_cache",
  1067. "to_datetime",
  1068. ]