38
38
Timedelta ,
39
39
Timestamp ,
40
40
conversion ,
41
- iNaT ,
42
41
ints_to_pydatetime ,
43
42
)
44
43
from pandas ._libs .tslibs .timedeltas import array_to_timedelta64
@@ -1613,50 +1612,16 @@ def maybe_cast_to_datetime(
1613
1612
is_datetime64tz = is_datetime64tz_dtype (dtype )
1614
1613
is_timedelta64 = is_timedelta64_dtype (dtype )
1615
1614
1616
- if is_datetime64 or is_datetime64tz or is_timedelta64 :
1617
-
1618
- # Force the dtype if needed.
1619
- msg = (
1620
- f"The '{ dtype .name } ' dtype has no unit. "
1621
- f"Please pass in '{ dtype .name } [ns]' instead."
1622
- )
1615
+ vdtype = getattr (value , "dtype" , None )
1623
1616
1624
- if is_datetime64 :
1625
- # unpack e.g. SparseDtype
1626
- dtype = getattr (dtype , "subtype" , dtype )
1627
- if not is_dtype_equal (dtype , DT64NS_DTYPE ):
1628
-
1629
- # pandas supports dtype whose granularity is less than [ns]
1630
- # e.g., [ps], [fs], [as]
1631
- if dtype <= np .dtype ("M8[ns]" ):
1632
- if dtype .name == "datetime64" :
1633
- raise ValueError (msg )
1634
- dtype = DT64NS_DTYPE
1635
- else :
1636
- raise TypeError (
1637
- f"cannot convert datetimelike to dtype [{ dtype } ]"
1638
- )
1639
-
1640
- elif is_timedelta64 and not is_dtype_equal (dtype , TD64NS_DTYPE ):
1641
-
1642
- # pandas supports dtype whose granularity is less than [ns]
1643
- # e.g., [ps], [fs], [as]
1644
- if dtype <= np .dtype ("m8[ns]" ):
1645
- if dtype .name == "timedelta64" :
1646
- raise ValueError (msg )
1647
- dtype = TD64NS_DTYPE
1648
- else :
1649
- raise TypeError (f"cannot convert timedeltalike to dtype [{ dtype } ]" )
1617
+ if is_datetime64 or is_datetime64tz or is_timedelta64 :
1618
+ dtype = ensure_nanosecond_dtype (dtype )
1650
1619
1651
1620
if not is_sparse (value ):
1652
1621
value = np .array (value , copy = False )
1653
1622
1654
- # have a scalar array-like (e.g. NaT)
1655
- if value .ndim == 0 :
1656
- value = iNaT
1657
-
1658
1623
# we have an array of datetime or timedeltas & nulls
1659
- elif value .size or not is_dtype_equal (value .dtype , dtype ):
1624
+ if value .size or not is_dtype_equal (value .dtype , dtype ):
1660
1625
_disallow_mismatched_datetimelike (value , dtype )
1661
1626
1662
1627
try :
@@ -1665,6 +1630,8 @@ def maybe_cast_to_datetime(
1665
1630
# GH 25843: Remove tz information since the dtype
1666
1631
# didn't specify one
1667
1632
if dta .tz is not None :
1633
+ # equiv: dta.view(dtype)
1634
+ # Note: NOT equivalent to dta.astype(dtype)
1668
1635
dta = dta .tz_localize (None )
1669
1636
value = dta
1670
1637
elif is_datetime64tz :
@@ -1678,10 +1645,12 @@ def maybe_cast_to_datetime(
1678
1645
value = dta .astype (dtype , copy = False )
1679
1646
elif is_dt_string :
1680
1647
# Strings here are naive, so directly localize
1648
+ # equiv: dta.astype(dtype) # though deprecated
1681
1649
value = dta .tz_localize (dtype .tz )
1682
1650
else :
1683
1651
# Numeric values are UTC at this point,
1684
1652
# so localize and convert
1653
+ # equiv: Series(dta).astype(dtype) # though deprecated
1685
1654
value = dta .tz_localize ("UTC" ).tz_convert (dtype .tz )
1686
1655
elif is_timedelta64 :
1687
1656
# if successful, we get a ndarray[td64ns]
@@ -1694,9 +1663,7 @@ def maybe_cast_to_datetime(
1694
1663
pass
1695
1664
1696
1665
# coerce datetimelike to object
1697
- elif is_datetime64_dtype (
1698
- getattr (value , "dtype" , None )
1699
- ) and not is_datetime64_dtype (dtype ):
1666
+ elif is_datetime64_dtype (vdtype ) and not is_datetime64_dtype (dtype ):
1700
1667
if is_object_dtype (dtype ):
1701
1668
value = cast (np .ndarray , value )
1702
1669
@@ -1740,6 +1707,50 @@ def sanitize_to_nanoseconds(values: np.ndarray) -> np.ndarray:
1740
1707
return values
1741
1708
1742
1709
1710
+ def ensure_nanosecond_dtype (dtype : DtypeObj ) -> DtypeObj :
1711
+ """
1712
+ Convert dtypes with granularity less than nanosecond to nanosecond
1713
+
1714
+ >>> ensure_nanosecond_dtype(np.dtype("M8[s]"))
1715
+ dtype('<M8[ns]')
1716
+
1717
+ >>> ensure_nanosecond_dtype(np.dtype("m8[ps]"))
1718
+ TypeError: cannot convert timedeltalike to dtype [timedelta64[ps]]
1719
+ """
1720
+ msg = (
1721
+ f"The '{ dtype .name } ' dtype has no unit. "
1722
+ f"Please pass in '{ dtype .name } [ns]' instead."
1723
+ )
1724
+
1725
+ # unpack e.g. SparseDtype
1726
+ dtype = getattr (dtype , "subtype" , dtype )
1727
+
1728
+ if not isinstance (dtype , np .dtype ):
1729
+ # i.e. datetime64tz
1730
+ pass
1731
+
1732
+ elif dtype .kind == "M" and dtype != DT64NS_DTYPE :
1733
+ # pandas supports dtype whose granularity is less than [ns]
1734
+ # e.g., [ps], [fs], [as]
1735
+ if dtype <= np .dtype ("M8[ns]" ):
1736
+ if dtype .name == "datetime64" :
1737
+ raise ValueError (msg )
1738
+ dtype = DT64NS_DTYPE
1739
+ else :
1740
+ raise TypeError (f"cannot convert datetimelike to dtype [{ dtype } ]" )
1741
+
1742
+ elif dtype .kind == "m" and dtype != TD64NS_DTYPE :
1743
+ # pandas supports dtype whose granularity is less than [ns]
1744
+ # e.g., [ps], [fs], [as]
1745
+ if dtype <= np .dtype ("m8[ns]" ):
1746
+ if dtype .name == "timedelta64" :
1747
+ raise ValueError (msg )
1748
+ dtype = TD64NS_DTYPE
1749
+ else :
1750
+ raise TypeError (f"cannot convert timedeltalike to dtype [{ dtype } ]" )
1751
+ return dtype
1752
+
1753
+
1743
1754
def find_common_type (types : List [DtypeObj ]) -> DtypeObj :
1744
1755
"""
1745
1756
Find a common data type among the given dtypes.
0 commit comments