tslib.pyx 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768
  1. import cython
  2. from cpython.datetime cimport (
  3. PyDate_Check,
  4. PyDateTime_Check,
  5. PyDateTime_IMPORT,
  6. datetime,
  7. tzinfo,
  8. )
  9. # import datetime C API
  10. PyDateTime_IMPORT
  11. cimport numpy as cnp
  12. from numpy cimport (
  13. float64_t,
  14. int64_t,
  15. ndarray,
  16. )
  17. import numpy as np
  18. cnp.import_array()
  19. import pytz
  20. from pandas._libs.tslibs.np_datetime cimport (
  21. _string_to_dts,
  22. check_dts_bounds,
  23. dt64_to_dtstruct,
  24. dtstruct_to_dt64,
  25. get_datetime64_value,
  26. npy_datetimestruct,
  27. pydate_to_dt64,
  28. pydatetime_to_dt64,
  29. )
  30. from pandas._libs.util cimport (
  31. is_datetime64_object,
  32. is_float_object,
  33. is_integer_object,
  34. )
  35. from pandas._libs.tslibs.np_datetime import OutOfBoundsDatetime
  36. from pandas._libs.tslibs.parsing import parse_datetime_string
  37. from pandas._libs.tslibs.conversion cimport (
  38. _TSObject,
  39. cast_from_unit,
  40. convert_datetime_to_tsobject,
  41. get_datetime64_nanos,
  42. precision_from_unit,
  43. )
  44. from pandas._libs.tslibs.nattype cimport (
  45. NPY_NAT,
  46. c_NaT as NaT,
  47. c_nat_strings as nat_strings,
  48. )
  49. from pandas._libs.tslibs.timestamps cimport _Timestamp
  50. from pandas._libs.tslibs.timestamps import Timestamp
  51. # Note: this is the only non-tslibs intra-pandas dependency here
  52. from pandas._libs.missing cimport checknull_with_nat_and_na
  53. from pandas._libs.tslibs.tzconversion cimport tz_localize_to_utc_single
  54. def _test_parse_iso8601(ts: str):
  55. """
  56. TESTING ONLY: Parse string into Timestamp using iso8601 parser. Used
  57. only for testing, actual construction uses `convert_str_to_tsobject`
  58. """
  59. cdef:
  60. _TSObject obj
  61. int out_local = 0, out_tzoffset = 0
  62. obj = _TSObject()
  63. if ts == 'now':
  64. return Timestamp.utcnow()
  65. elif ts == 'today':
  66. return Timestamp.now().normalize()
  67. _string_to_dts(ts, &obj.dts, &out_local, &out_tzoffset, True)
  68. obj.value = dtstruct_to_dt64(&obj.dts)
  69. check_dts_bounds(&obj.dts)
  70. if out_local == 1:
  71. obj.tzinfo = pytz.FixedOffset(out_tzoffset)
  72. obj.value = tz_localize_to_utc_single(obj.value, obj.tzinfo)
  73. return Timestamp(obj.value, tz=obj.tzinfo)
  74. else:
  75. return Timestamp(obj.value)
  76. @cython.wraparound(False)
  77. @cython.boundscheck(False)
  78. def format_array_from_datetime(
  79. ndarray[int64_t] values,
  80. tzinfo tz=None,
  81. str format=None,
  82. object na_rep=None
  83. ) -> np.ndarray:
  84. """
  85. return a np object array of the string formatted values
  86. Parameters
  87. ----------
  88. values : a 1-d i8 array
  89. tz : tzinfo or None, default None
  90. format : str or None, default None
  91. a strftime capable string
  92. na_rep : optional, default is None
  93. a nat format
  94. Returns
  95. -------
  96. np.ndarray[object]
  97. """
  98. cdef:
  99. int64_t val, ns, N = len(values)
  100. ndarray[int64_t] consider_values
  101. bint show_ms = False, show_us = False, show_ns = False
  102. bint basic_format = False
  103. ndarray[object] result = np.empty(N, dtype=object)
  104. object ts, res
  105. npy_datetimestruct dts
  106. if na_rep is None:
  107. na_rep = 'NaT'
  108. # if we don't have a format nor tz, then choose
  109. # a format based on precision
  110. basic_format = format is None and tz is None
  111. if basic_format:
  112. consider_values = values[values != NPY_NAT]
  113. show_ns = (consider_values % 1000).any()
  114. if not show_ns:
  115. consider_values //= 1000
  116. show_us = (consider_values % 1000).any()
  117. if not show_ms:
  118. consider_values //= 1000
  119. show_ms = (consider_values % 1000).any()
  120. for i in range(N):
  121. val = values[i]
  122. if val == NPY_NAT:
  123. result[i] = na_rep
  124. elif basic_format:
  125. dt64_to_dtstruct(val, &dts)
  126. res = (f'{dts.year}-{dts.month:02d}-{dts.day:02d} '
  127. f'{dts.hour:02d}:{dts.min:02d}:{dts.sec:02d}')
  128. if show_ns:
  129. ns = dts.ps // 1000
  130. res += f'.{ns + dts.us * 1000:09d}'
  131. elif show_us:
  132. res += f'.{dts.us:06d}'
  133. elif show_ms:
  134. res += f'.{dts.us // 1000:03d}'
  135. result[i] = res
  136. else:
  137. ts = Timestamp(val, tz=tz)
  138. if format is None:
  139. result[i] = str(ts)
  140. else:
  141. # invalid format string
  142. # requires dates > 1900
  143. try:
  144. result[i] = ts.strftime(format)
  145. except ValueError:
  146. result[i] = str(ts)
  147. return result
  148. def array_with_unit_to_datetime(
  149. ndarray values,
  150. str unit,
  151. str errors="coerce"
  152. ):
  153. """
  154. Convert the ndarray to datetime according to the time unit.
  155. This function converts an array of objects into a numpy array of
  156. datetime64[ns]. It returns the converted array
  157. and also returns the timezone offset
  158. if errors:
  159. - raise: return converted values or raise OutOfBoundsDatetime
  160. if out of range on the conversion or
  161. ValueError for other conversions (e.g. a string)
  162. - ignore: return non-convertible values as the same unit
  163. - coerce: NaT for non-convertibles
  164. Parameters
  165. ----------
  166. values : ndarray
  167. Date-like objects to convert.
  168. unit : str
  169. Time unit to use during conversion.
  170. errors : str, default 'raise'
  171. Error behavior when parsing.
  172. Returns
  173. -------
  174. result : ndarray of m8 values
  175. tz : parsed timezone offset or None
  176. """
  177. cdef:
  178. Py_ssize_t i, j, n=len(values)
  179. int64_t m
  180. int prec = 0
  181. ndarray[float64_t] fvalues
  182. bint is_ignore = errors=='ignore'
  183. bint is_coerce = errors=='coerce'
  184. bint is_raise = errors=='raise'
  185. bint need_to_iterate = True
  186. ndarray[int64_t] iresult
  187. ndarray[object] oresult
  188. ndarray mask
  189. object tz = None
  190. assert is_ignore or is_coerce or is_raise
  191. if unit == "ns":
  192. if issubclass(values.dtype.type, (np.integer, np.float_)):
  193. result = values.astype("M8[ns]", copy=False)
  194. else:
  195. result, tz = array_to_datetime(
  196. values.astype(object, copy=False),
  197. errors=errors,
  198. )
  199. return result, tz
  200. m, p = precision_from_unit(unit)
  201. if is_raise:
  202. # try a quick conversion to i8/f8
  203. # if we have nulls that are not type-compat
  204. # then need to iterate
  205. if values.dtype.kind == "i" or values.dtype.kind == "f":
  206. iresult = values.astype("i8", copy=False)
  207. # fill missing values by comparing to NPY_NAT
  208. mask = iresult == NPY_NAT
  209. iresult[mask] = 0
  210. fvalues = iresult.astype("f8") * m
  211. need_to_iterate = False
  212. if not need_to_iterate:
  213. # check the bounds
  214. if (fvalues < Timestamp.min.value).any() or (
  215. (fvalues > Timestamp.max.value).any()
  216. ):
  217. raise OutOfBoundsDatetime(f"cannot convert input with unit '{unit}'")
  218. if values.dtype.kind == "i":
  219. result = (iresult * m).astype("M8[ns]")
  220. elif values.dtype.kind == "f":
  221. fresult = (values * m).astype("f8")
  222. fresult[mask] = 0
  223. if prec:
  224. fresult = round(fresult, prec)
  225. result = fresult.astype("M8[ns]", copy=False)
  226. iresult = result.view("i8")
  227. iresult[mask] = NPY_NAT
  228. return result, tz
  229. result = np.empty(n, dtype='M8[ns]')
  230. iresult = result.view('i8')
  231. try:
  232. for i in range(n):
  233. val = values[i]
  234. if checknull_with_nat_and_na(val):
  235. iresult[i] = NPY_NAT
  236. elif is_integer_object(val) or is_float_object(val):
  237. if val != val or val == NPY_NAT:
  238. iresult[i] = NPY_NAT
  239. else:
  240. try:
  241. iresult[i] = cast_from_unit(val, unit)
  242. except OverflowError:
  243. if is_raise:
  244. raise OutOfBoundsDatetime(
  245. f"cannot convert input {val} with the unit '{unit}'"
  246. )
  247. elif is_ignore:
  248. raise AssertionError
  249. iresult[i] = NPY_NAT
  250. elif isinstance(val, str):
  251. if len(val) == 0 or val in nat_strings:
  252. iresult[i] = NPY_NAT
  253. else:
  254. try:
  255. iresult[i] = cast_from_unit(float(val), unit)
  256. except ValueError:
  257. if is_raise:
  258. raise ValueError(
  259. f"non convertible value {val} with the unit '{unit}'"
  260. )
  261. elif is_ignore:
  262. raise AssertionError
  263. iresult[i] = NPY_NAT
  264. except OverflowError:
  265. if is_raise:
  266. raise OutOfBoundsDatetime(
  267. f"cannot convert input {val} with the unit '{unit}'"
  268. )
  269. elif is_ignore:
  270. raise AssertionError
  271. iresult[i] = NPY_NAT
  272. else:
  273. if is_raise:
  274. raise ValueError(
  275. f"unit='{unit}' not valid with non-numerical val='{val}'"
  276. )
  277. if is_ignore:
  278. raise AssertionError
  279. iresult[i] = NPY_NAT
  280. return result, tz
  281. except AssertionError:
  282. pass
  283. # we have hit an exception
  284. # and are in ignore mode
  285. # redo as object
  286. oresult = np.empty(n, dtype=object)
  287. for i in range(n):
  288. val = values[i]
  289. if checknull_with_nat_and_na(val):
  290. oresult[i] = <object>NaT
  291. elif is_integer_object(val) or is_float_object(val):
  292. if val != val or val == NPY_NAT:
  293. oresult[i] = <object>NaT
  294. else:
  295. try:
  296. oresult[i] = Timestamp(cast_from_unit(val, unit))
  297. except OverflowError:
  298. oresult[i] = val
  299. elif isinstance(val, str):
  300. if len(val) == 0 or val in nat_strings:
  301. oresult[i] = <object>NaT
  302. else:
  303. oresult[i] = val
  304. return oresult, tz
  305. @cython.wraparound(False)
  306. @cython.boundscheck(False)
  307. cpdef array_to_datetime(
  308. ndarray[object] values,
  309. str errors='raise',
  310. bint dayfirst=False,
  311. bint yearfirst=False,
  312. bint utc=False,
  313. bint require_iso8601=False,
  314. bint allow_mixed=False,
  315. ):
  316. """
  317. Converts a 1D array of date-like values to a numpy array of either:
  318. 1) datetime64[ns] data
  319. 2) datetime.datetime objects, if OutOfBoundsDatetime or TypeError
  320. is encountered
  321. Also returns a pytz.FixedOffset if an array of strings with the same
  322. timezone offset is passed and utc=True is not passed. Otherwise, None
  323. is returned
  324. Handles datetime.date, datetime.datetime, np.datetime64 objects, numeric,
  325. strings
  326. Parameters
  327. ----------
  328. values : ndarray of object
  329. date-like objects to convert
  330. errors : str, default 'raise'
  331. error behavior when parsing
  332. dayfirst : bool, default False
  333. dayfirst parsing behavior when encountering datetime strings
  334. yearfirst : bool, default False
  335. yearfirst parsing behavior when encountering datetime strings
  336. utc : bool, default False
  337. indicator whether the dates should be UTC
  338. require_iso8601 : bool, default False
  339. indicator whether the datetime string should be iso8601
  340. allow_mixed : bool, default False
  341. Whether to allow mixed datetimes and integers.
  342. Returns
  343. -------
  344. np.ndarray
  345. May be datetime64[ns] or object dtype
  346. tzinfo or None
  347. """
  348. cdef:
  349. Py_ssize_t i, n = len(values)
  350. object val, py_dt, tz, tz_out = None
  351. ndarray[int64_t] iresult
  352. ndarray[object] oresult
  353. npy_datetimestruct dts
  354. bint utc_convert = bool(utc)
  355. bint seen_integer = False
  356. bint seen_string = False
  357. bint seen_datetime = False
  358. bint seen_datetime_offset = False
  359. bint is_raise = errors=='raise'
  360. bint is_ignore = errors=='ignore'
  361. bint is_coerce = errors=='coerce'
  362. bint is_same_offsets
  363. _TSObject _ts
  364. int64_t value
  365. int out_local = 0, out_tzoffset = 0
  366. float offset_seconds, tz_offset
  367. set out_tzoffset_vals = set()
  368. bint string_to_dts_failed
  369. # specify error conditions
  370. assert is_raise or is_ignore or is_coerce
  371. result = np.empty(n, dtype='M8[ns]')
  372. iresult = result.view('i8')
  373. try:
  374. for i in range(n):
  375. val = values[i]
  376. try:
  377. if checknull_with_nat_and_na(val):
  378. iresult[i] = NPY_NAT
  379. elif PyDateTime_Check(val):
  380. seen_datetime = True
  381. if val.tzinfo is not None:
  382. if utc_convert:
  383. _ts = convert_datetime_to_tsobject(val, None)
  384. iresult[i] = _ts.value
  385. else:
  386. raise ValueError('Tz-aware datetime.datetime '
  387. 'cannot be converted to '
  388. 'datetime64 unless utc=True')
  389. elif isinstance(val, _Timestamp):
  390. iresult[i] = val.value
  391. else:
  392. iresult[i] = pydatetime_to_dt64(val, &dts)
  393. check_dts_bounds(&dts)
  394. elif PyDate_Check(val):
  395. seen_datetime = True
  396. iresult[i] = pydate_to_dt64(val, &dts)
  397. check_dts_bounds(&dts)
  398. elif is_datetime64_object(val):
  399. seen_datetime = True
  400. iresult[i] = get_datetime64_nanos(val)
  401. elif is_integer_object(val) or is_float_object(val):
  402. # these must be ns unit by-definition
  403. seen_integer = True
  404. if val != val or val == NPY_NAT:
  405. iresult[i] = NPY_NAT
  406. elif is_raise or is_ignore:
  407. iresult[i] = val
  408. else:
  409. # coerce
  410. # we now need to parse this as if unit='ns'
  411. # we can ONLY accept integers at this point
  412. # if we have previously (or in future accept
  413. # datetimes/strings, then we must coerce)
  414. try:
  415. iresult[i] = cast_from_unit(val, 'ns')
  416. except OverflowError:
  417. iresult[i] = NPY_NAT
  418. elif isinstance(val, str):
  419. # string
  420. seen_string = True
  421. if len(val) == 0 or val in nat_strings:
  422. iresult[i] = NPY_NAT
  423. continue
  424. string_to_dts_failed = _string_to_dts(
  425. val, &dts, &out_local,
  426. &out_tzoffset, False
  427. )
  428. if string_to_dts_failed:
  429. # An error at this point is a _parsing_ error
  430. # specifically _not_ OutOfBoundsDatetime
  431. if _parse_today_now(val, &iresult[i]):
  432. continue
  433. elif require_iso8601:
  434. # if requiring iso8601 strings, skip trying
  435. # other formats
  436. if is_coerce:
  437. iresult[i] = NPY_NAT
  438. continue
  439. elif is_raise:
  440. raise ValueError(
  441. f"time data {val} doesn't match format specified"
  442. )
  443. return values, tz_out
  444. try:
  445. py_dt = parse_datetime_string(val,
  446. dayfirst=dayfirst,
  447. yearfirst=yearfirst)
  448. # If the dateutil parser returned tzinfo, capture it
  449. # to check if all arguments have the same tzinfo
  450. tz = py_dt.utcoffset()
  451. except (ValueError, OverflowError):
  452. if is_coerce:
  453. iresult[i] = NPY_NAT
  454. continue
  455. raise TypeError("invalid string coercion to datetime")
  456. if tz is not None:
  457. seen_datetime_offset = True
  458. # dateutil timezone objects cannot be hashed, so
  459. # store the UTC offsets in seconds instead
  460. out_tzoffset_vals.add(tz.total_seconds())
  461. else:
  462. # Add a marker for naive string, to track if we are
  463. # parsing mixed naive and aware strings
  464. out_tzoffset_vals.add('naive')
  465. _ts = convert_datetime_to_tsobject(py_dt, None)
  466. iresult[i] = _ts.value
  467. if not string_to_dts_failed:
  468. # No error reported by string_to_dts, pick back up
  469. # where we left off
  470. value = dtstruct_to_dt64(&dts)
  471. if out_local == 1:
  472. seen_datetime_offset = True
  473. # Store the out_tzoffset in seconds
  474. # since we store the total_seconds of
  475. # dateutil.tz.tzoffset objects
  476. out_tzoffset_vals.add(out_tzoffset * 60.)
  477. tz = pytz.FixedOffset(out_tzoffset)
  478. value = tz_localize_to_utc_single(value, tz)
  479. out_local = 0
  480. out_tzoffset = 0
  481. else:
  482. # Add a marker for naive string, to track if we are
  483. # parsing mixed naive and aware strings
  484. out_tzoffset_vals.add('naive')
  485. iresult[i] = value
  486. check_dts_bounds(&dts)
  487. else:
  488. if is_coerce:
  489. iresult[i] = NPY_NAT
  490. else:
  491. raise TypeError(f"{type(val)} is not convertible to datetime")
  492. except OutOfBoundsDatetime:
  493. if is_coerce:
  494. iresult[i] = NPY_NAT
  495. continue
  496. elif require_iso8601 and isinstance(val, str):
  497. # GH#19382 for just-barely-OutOfBounds falling back to
  498. # dateutil parser will return incorrect result because
  499. # it will ignore nanoseconds
  500. if is_raise:
  501. # Still raise OutOfBoundsDatetime,
  502. # as error message is informative.
  503. raise
  504. assert is_ignore
  505. return values, tz_out
  506. raise
  507. except OutOfBoundsDatetime:
  508. if is_raise:
  509. raise
  510. return ignore_errors_out_of_bounds_fallback(values), tz_out
  511. except TypeError:
  512. return _array_to_datetime_object(values, errors, dayfirst, yearfirst)
  513. if seen_datetime and seen_integer:
  514. # we have mixed datetimes & integers
  515. if is_coerce:
  516. # coerce all of the integers/floats to NaT, preserve
  517. # the datetimes and other convertibles
  518. for i in range(n):
  519. val = values[i]
  520. if is_integer_object(val) or is_float_object(val):
  521. result[i] = NPY_NAT
  522. elif allow_mixed:
  523. pass
  524. elif is_raise:
  525. raise ValueError("mixed datetimes and integers in passed array")
  526. else:
  527. return _array_to_datetime_object(values, errors, dayfirst, yearfirst)
  528. if seen_datetime_offset and not utc_convert:
  529. # GH#17697
  530. # 1) If all the offsets are equal, return one offset for
  531. # the parsed dates to (maybe) pass to DatetimeIndex
  532. # 2) If the offsets are different, then force the parsing down the
  533. # object path where an array of datetimes
  534. # (with individual dateutil.tzoffsets) are returned
  535. is_same_offsets = len(out_tzoffset_vals) == 1
  536. if not is_same_offsets:
  537. return _array_to_datetime_object(values, errors, dayfirst, yearfirst)
  538. else:
  539. tz_offset = out_tzoffset_vals.pop()
  540. tz_out = pytz.FixedOffset(tz_offset / 60.)
  541. return result, tz_out
  542. cdef ndarray[object] ignore_errors_out_of_bounds_fallback(ndarray[object] values):
  543. """
  544. Fallback for array_to_datetime if an OutOfBoundsDatetime is raised
  545. and errors == "ignore"
  546. Parameters
  547. ----------
  548. values : ndarray[object]
  549. Returns
  550. -------
  551. ndarray[object]
  552. """
  553. cdef:
  554. Py_ssize_t i, n = len(values)
  555. object val
  556. oresult = np.empty(n, dtype=object)
  557. for i in range(n):
  558. val = values[i]
  559. # set as nan except if its a NaT
  560. if checknull_with_nat_and_na(val):
  561. if isinstance(val, float):
  562. oresult[i] = np.nan
  563. else:
  564. oresult[i] = NaT
  565. elif is_datetime64_object(val):
  566. if get_datetime64_value(val) == NPY_NAT:
  567. oresult[i] = NaT
  568. else:
  569. oresult[i] = val.item()
  570. else:
  571. oresult[i] = val
  572. return oresult
  573. @cython.wraparound(False)
  574. @cython.boundscheck(False)
  575. cdef _array_to_datetime_object(
  576. ndarray[object] values,
  577. str errors,
  578. bint dayfirst=False,
  579. bint yearfirst=False,
  580. ):
  581. """
  582. Fall back function for array_to_datetime
  583. Attempts to parse datetime strings with dateutil to return an array
  584. of datetime objects
  585. Parameters
  586. ----------
  587. values : ndarray[object]
  588. date-like objects to convert
  589. errors : str
  590. error behavior when parsing
  591. dayfirst : bool, default False
  592. dayfirst parsing behavior when encountering datetime strings
  593. yearfirst : bool, default False
  594. yearfirst parsing behavior when encountering datetime strings
  595. Returns
  596. -------
  597. np.ndarray[object]
  598. Literal[None]
  599. """
  600. cdef:
  601. Py_ssize_t i, n = len(values)
  602. object val
  603. bint is_ignore = errors == 'ignore'
  604. bint is_coerce = errors == 'coerce'
  605. bint is_raise = errors == 'raise'
  606. ndarray[object] oresult
  607. npy_datetimestruct dts
  608. assert is_raise or is_ignore or is_coerce
  609. oresult = np.empty(n, dtype=object)
  610. # We return an object array and only attempt to parse:
  611. # 1) NaT or NaT-like values
  612. # 2) datetime strings, which we return as datetime.datetime
  613. for i in range(n):
  614. val = values[i]
  615. if checknull_with_nat_and_na(val) or PyDateTime_Check(val):
  616. # GH 25978. No need to parse NaT-like or datetime-like vals
  617. oresult[i] = val
  618. elif isinstance(val, str):
  619. if len(val) == 0 or val in nat_strings:
  620. oresult[i] = 'NaT'
  621. continue
  622. try:
  623. oresult[i] = parse_datetime_string(val, dayfirst=dayfirst,
  624. yearfirst=yearfirst)
  625. pydatetime_to_dt64(oresult[i], &dts)
  626. check_dts_bounds(&dts)
  627. except (ValueError, OverflowError):
  628. if is_coerce:
  629. oresult[i] = <object>NaT
  630. continue
  631. if is_raise:
  632. raise
  633. return values, None
  634. else:
  635. if is_raise:
  636. raise
  637. return values, None
  638. return oresult, None
  639. cdef inline bint _parse_today_now(str val, int64_t* iresult):
  640. # We delay this check for as long as possible
  641. # because it catches relatively rare cases
  642. if val == 'now':
  643. # Note: this is *not* the same as Timestamp('now')
  644. iresult[0] = Timestamp.utcnow().value
  645. return True
  646. elif val == 'today':
  647. iresult[0] = Timestamp.today().value
  648. return True
  649. return False