Skip to content

Commit a13a95f

Browse files
authored
REF: move mixed-int handling from maybe_cast_to_datetime (#40187)
1 parent 179b3e6 commit a13a95f

File tree

2 files changed

+47
-28
lines changed

2 files changed

+47
-28
lines changed

pandas/core/arrays/datetimes.py

+38-2
Original file line numberDiff line numberDiff line change
@@ -1904,6 +1904,23 @@ def std(
19041904
# Constructor Helpers
19051905

19061906

1907+
def sequence_to_datetimes(
1908+
data, allow_object: bool = False
1909+
) -> Union[np.ndarray, DatetimeArray]:
1910+
"""
1911+
Parse/convert the passed data to either DatetimeArray or np.ndarray[object].
1912+
"""
1913+
result, tz, freq = sequence_to_dt64ns(
1914+
data, allow_object=allow_object, allow_mixed=True
1915+
)
1916+
if result.dtype == object:
1917+
return result
1918+
1919+
dtype = tz_to_dtype(tz)
1920+
dta = DatetimeArray._simple_new(result, freq=freq, dtype=dtype)
1921+
return dta
1922+
1923+
19071924
def sequence_to_dt64ns(
19081925
data,
19091926
dtype=None,
@@ -1912,6 +1929,9 @@ def sequence_to_dt64ns(
19121929
dayfirst=False,
19131930
yearfirst=False,
19141931
ambiguous="raise",
1932+
*,
1933+
allow_object: bool = False,
1934+
allow_mixed: bool = False,
19151935
):
19161936
"""
19171937
Parameters
@@ -1924,6 +1944,11 @@ def sequence_to_dt64ns(
19241944
yearfirst : bool, default False
19251945
ambiguous : str, bool, or arraylike, default 'raise'
19261946
See pandas._libs.tslibs.tzconversion.tz_localize_to_utc.
1947+
allow_object : bool, default False
1948+
Whether to return an object-dtype ndarray instead of raising if the
1949+
data contains more than one timezone.
1950+
allow_mixed : bool, default False
1951+
Interpret integers as timestamps when datetime objects are also present.
19271952
19281953
Returns
19291954
-------
@@ -1987,14 +2012,21 @@ def sequence_to_dt64ns(
19872012
# data comes back here as either i8 to denote UTC timestamps
19882013
# or M8[ns] to denote wall times
19892014
data, inferred_tz = objects_to_datetime64ns(
1990-
data, dayfirst=dayfirst, yearfirst=yearfirst
2015+
data,
2016+
dayfirst=dayfirst,
2017+
yearfirst=yearfirst,
2018+
allow_object=allow_object,
2019+
allow_mixed=allow_mixed,
19912020
)
19922021
if tz and inferred_tz:
19932022
# two timezones: convert to intended from base UTC repr
19942023
data = tzconversion.tz_convert_from_utc(data.view("i8"), tz)
19952024
data = data.view(DT64NS_DTYPE)
19962025
elif inferred_tz:
19972026
tz = inferred_tz
2027+
elif allow_object and data.dtype == object:
2028+
# We encountered mixed-timezones.
2029+
return data, None, None
19982030

19992031
data_dtype = data.dtype
20002032

@@ -2053,6 +2085,7 @@ def objects_to_datetime64ns(
20532085
errors="raise",
20542086
require_iso8601=False,
20552087
allow_object=False,
2088+
allow_mixed: bool = False,
20562089
):
20572090
"""
20582091
Convert data to array of timestamps.
@@ -2069,6 +2102,8 @@ def objects_to_datetime64ns(
20692102
allow_object : bool
20702103
Whether to return an object-dtype ndarray instead of raising if the
20712104
data contains more than one timezone.
2105+
allow_mixed : bool, default False
2106+
Interpret integers as timestamps when datetime objects are also present.
20722107
20732108
Returns
20742109
-------
@@ -2097,6 +2132,7 @@ def objects_to_datetime64ns(
20972132
dayfirst=dayfirst,
20982133
yearfirst=yearfirst,
20992134
require_iso8601=require_iso8601,
2135+
allow_mixed=allow_mixed,
21002136
)
21012137
result = result.reshape(data.shape, order=order)
21022138
except ValueError as err:
@@ -2133,7 +2169,7 @@ def objects_to_datetime64ns(
21332169
raise TypeError(result)
21342170

21352171

2136-
def maybe_convert_dtype(data, copy):
2172+
def maybe_convert_dtype(data, copy: bool):
21372173
"""
21382174
Convert data based on dtype conventions, issuing deprecation warnings
21392175
or errors where appropriate.

pandas/core/dtypes/cast.py

+9-26
Original file line numberDiff line numberDiff line change
@@ -29,10 +29,7 @@
2929

3030
import numpy as np
3131

32-
from pandas._libs import (
33-
lib,
34-
tslib,
35-
)
32+
from pandas._libs import lib
3633
from pandas._libs.tslibs import (
3734
NaT,
3835
OutOfBoundsDatetime,
@@ -1605,8 +1602,8 @@ def maybe_cast_to_datetime(
16051602
try to cast the array/value to a datetimelike dtype, converting float
16061603
nan to iNaT
16071604
"""
1605+
from pandas.core.arrays.datetimes import sequence_to_datetimes
16081606
from pandas.core.arrays.timedeltas import sequence_to_td64ns
1609-
from pandas.core.tools.datetimes import to_datetime
16101607

16111608
if not is_list_like(value):
16121609
raise TypeError("value must be listlike")
@@ -1664,19 +1661,19 @@ def maybe_cast_to_datetime(
16641661

16651662
try:
16661663
if is_datetime64:
1667-
dti = to_datetime(value, errors="raise")
1664+
dta = sequence_to_datetimes(value, allow_object=False)
16681665
# GH 25843: Remove tz information since the dtype
16691666
# didn't specify one
1670-
if dti.tz is not None:
1671-
dti = dti.tz_localize(None)
1672-
value = dti._values
1667+
if dta.tz is not None:
1668+
dta = dta.tz_localize(None)
1669+
value = dta
16731670
elif is_datetime64tz:
16741671
# The string check can be removed once issue #13712
16751672
# is solved. String data that is passed with a
16761673
# datetime64tz is assumed to be naive which should
16771674
# be localized to the timezone.
16781675
is_dt_string = is_string_dtype(value.dtype)
1679-
dta = to_datetime(value, errors="raise").array
1676+
dta = sequence_to_datetimes(value, allow_object=False)
16801677
if dta.tz is not None:
16811678
value = dta.astype(dtype, copy=False)
16821679
elif is_dt_string:
@@ -1691,24 +1688,10 @@ def maybe_cast_to_datetime(
16911688
value, _ = sequence_to_td64ns(value)
16921689
except OutOfBoundsDatetime:
16931690
raise
1694-
except ValueError as err:
1691+
except ValueError:
16951692
# TODO(GH#40048): only catch dateutil's ParserError
16961693
# once we can reliably import it in all supported versions
1697-
if "mixed datetimes and integers in passed array" in str(err):
1698-
# We need to catch this in array_to_datetime, otherwise
1699-
# we end up going through numpy which will lose nanoseconds
1700-
# from Timestamps
1701-
try:
1702-
i8vals, tz = tslib.array_to_datetime(
1703-
value, allow_mixed=True
1704-
)
1705-
except ValueError:
1706-
pass
1707-
else:
1708-
from pandas.core.arrays import DatetimeArray
1709-
1710-
dta = DatetimeArray(i8vals).tz_localize(tz)
1711-
value = dta
1694+
pass
17121695

17131696
# coerce datetimelike to object
17141697
elif is_datetime64_dtype(

0 commit comments

Comments
 (0)