Skip to content

Commit 0cd5428

Browse files
authored
REF: implement _construct_from_dt64_naive (#55672)
1 parent 0299809 commit 0cd5428

File tree

1 file changed

+61
-36
lines changed

1 file changed

+61
-36
lines changed

pandas/core/arrays/datetimes.py

+61-36
Original file line numberDiff line numberDiff line change
@@ -2246,21 +2246,29 @@ def _sequence_to_dt64ns(
22462246
else:
22472247
# data comes back here as either i8 to denote UTC timestamps
22482248
# or M8[ns] to denote wall times
2249-
data, inferred_tz = objects_to_datetime64ns(
2249+
converted, inferred_tz = objects_to_datetime64ns(
22502250
data,
22512251
dayfirst=dayfirst,
22522252
yearfirst=yearfirst,
22532253
allow_object=False,
22542254
)
2255+
copy = False
22552256
if tz and inferred_tz:
22562257
# two timezones: convert to intended from base UTC repr
2257-
assert data.dtype == "i8"
2258+
assert converted.dtype == "i8"
22582259
# GH#42505
22592260
# by convention, these are _already_ UTC, e.g
2260-
return data.view(DT64NS_DTYPE), tz, None
2261+
result = converted.view(DT64NS_DTYPE)
22612262

22622263
elif inferred_tz:
22632264
tz = inferred_tz
2265+
result = converted.view(DT64NS_DTYPE)
2266+
2267+
else:
2268+
result, _ = _construct_from_dt64_naive(
2269+
converted, tz=tz, copy=copy, ambiguous=ambiguous
2270+
)
2271+
return result, tz, None
22642272

22652273
data_dtype = data.dtype
22662274

@@ -2275,40 +2283,10 @@ def _sequence_to_dt64ns(
22752283
# tz-naive DatetimeArray or ndarray[datetime64]
22762284
if isinstance(data, DatetimeArray):
22772285
data = data._ndarray
2278-
new_dtype = data.dtype
2279-
data_unit = get_unit_from_dtype(new_dtype)
2280-
if not is_supported_unit(data_unit):
2281-
# Cast to the nearest supported unit, generally "s"
2282-
new_reso = get_supported_reso(data_unit)
2283-
new_unit = npy_unit_to_abbrev(new_reso)
2284-
new_dtype = np.dtype(f"M8[{new_unit}]")
2285-
data = astype_overflowsafe(data, dtype=new_dtype, copy=False)
2286-
data_unit = get_unit_from_dtype(new_dtype)
2287-
copy = False
22882286

2289-
if data.dtype.byteorder == ">":
2290-
# TODO: better way to handle this? non-copying alternative?
2291-
# without this, test_constructor_datetime64_bigendian fails
2292-
data = data.astype(data.dtype.newbyteorder("<"))
2293-
new_dtype = data.dtype
2294-
copy = False
2295-
2296-
if tz is not None:
2297-
# Convert tz-naive to UTC
2298-
# TODO: if tz is UTC, are there situations where we *don't* want a
2299-
# copy? tz_localize_to_utc always makes one.
2300-
shape = data.shape
2301-
if data.ndim > 1:
2302-
data = data.ravel()
2303-
2304-
data = tzconversion.tz_localize_to_utc(
2305-
data.view("i8"), tz, ambiguous=ambiguous, creso=data_unit
2306-
)
2307-
data = data.view(new_dtype)
2308-
data = data.reshape(shape)
2309-
2310-
assert data.dtype == new_dtype, data.dtype
2311-
result = data
2287+
result, copy = _construct_from_dt64_naive(
2288+
data, tz=tz, copy=copy, ambiguous=ambiguous
2289+
)
23122290

23132291
else:
23142292
# must be integer dtype otherwise
@@ -2328,6 +2306,53 @@ def _sequence_to_dt64ns(
23282306
return result, tz, inferred_freq
23292307

23302308

2309+
def _construct_from_dt64_naive(
2310+
data: np.ndarray, *, tz: tzinfo | None, copy: bool, ambiguous: TimeAmbiguous
2311+
) -> tuple[np.ndarray, bool]:
2312+
"""
2313+
Convert datetime64 data to a supported dtype, localizing if necessary.
2314+
"""
2315+
# Caller is responsible for ensuring
2316+
# lib.is_np_dtype(data.dtype)
2317+
2318+
new_dtype = data.dtype
2319+
data_unit = get_unit_from_dtype(new_dtype)
2320+
if not is_supported_unit(data_unit):
2321+
# Cast to the nearest supported unit, generally "s"
2322+
new_reso = get_supported_reso(data_unit)
2323+
new_unit = npy_unit_to_abbrev(new_reso)
2324+
new_dtype = np.dtype(f"M8[{new_unit}]")
2325+
data = astype_overflowsafe(data, dtype=new_dtype, copy=False)
2326+
data_unit = get_unit_from_dtype(new_dtype)
2327+
copy = False
2328+
2329+
if data.dtype.byteorder == ">":
2330+
# TODO: better way to handle this? non-copying alternative?
2331+
# without this, test_constructor_datetime64_bigendian fails
2332+
data = data.astype(data.dtype.newbyteorder("<"))
2333+
new_dtype = data.dtype
2334+
copy = False
2335+
2336+
if tz is not None:
2337+
# Convert tz-naive to UTC
2338+
# TODO: if tz is UTC, are there situations where we *don't* want a
2339+
# copy? tz_localize_to_utc always makes one.
2340+
shape = data.shape
2341+
if data.ndim > 1:
2342+
data = data.ravel()
2343+
2344+
data = tzconversion.tz_localize_to_utc(
2345+
data.view("i8"), tz, ambiguous=ambiguous, creso=data_unit
2346+
)
2347+
data = data.view(new_dtype)
2348+
data = data.reshape(shape)
2349+
2350+
assert data.dtype == new_dtype, data.dtype
2351+
result = data
2352+
2353+
return result, copy
2354+
2355+
23312356
def objects_to_datetime64ns(
23322357
data: np.ndarray,
23332358
dayfirst,

0 commit comments

Comments
 (0)