@@ -2246,21 +2246,29 @@ def _sequence_to_dt64ns(
2246
2246
else :
2247
2247
# data comes back here as either i8 to denote UTC timestamps
2248
2248
# or M8[ns] to denote wall times
2249
- data , inferred_tz = objects_to_datetime64ns (
2249
+ converted , inferred_tz = objects_to_datetime64ns (
2250
2250
data ,
2251
2251
dayfirst = dayfirst ,
2252
2252
yearfirst = yearfirst ,
2253
2253
allow_object = False ,
2254
2254
)
2255
+ copy = False
2255
2256
if tz and inferred_tz :
2256
2257
# two timezones: convert to intended from base UTC repr
2257
- assert data .dtype == "i8"
2258
+ assert converted .dtype == "i8"
2258
2259
# GH#42505
2259
2260
# by convention, these are _already_ UTC, e.g
2260
- return data .view (DT64NS_DTYPE ), tz , None
2261
+ result = converted .view (DT64NS_DTYPE )
2261
2262
2262
2263
elif inferred_tz :
2263
2264
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
2264
2272
2265
2273
data_dtype = data .dtype
2266
2274
@@ -2275,40 +2283,10 @@ def _sequence_to_dt64ns(
2275
2283
# tz-naive DatetimeArray or ndarray[datetime64]
2276
2284
if isinstance (data , DatetimeArray ):
2277
2285
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
2288
2286
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
+ )
2312
2290
2313
2291
else :
2314
2292
# must be integer dtype otherwise
@@ -2328,6 +2306,53 @@ def _sequence_to_dt64ns(
2328
2306
return result , tz , inferred_freq
2329
2307
2330
2308
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
+
2331
2356
def objects_to_datetime64ns (
2332
2357
data : np .ndarray ,
2333
2358
dayfirst ,
0 commit comments