Skip to content

Commit d498ea1

Browse files
committed
Handle construction from scalar
1 parent fa6421c commit d498ea1

File tree

3 files changed

+62
-1
lines changed

3 files changed

+62
-1
lines changed

pandas/_libs/lib.pyx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2589,7 +2589,7 @@ def maybe_convert_objects(ndarray[object] objects,
25892589
seen.object_ = True
25902590
break
25912591
elif PyTime_Check(val):
2592-
if convert_non_numeric:
2592+
if convert_non_numeric and val.tzinfo is None:
25932593
seen.time_ = True
25942594
else:
25952595
seen.object_ = True
@@ -2660,6 +2660,7 @@ def maybe_convert_objects(ndarray[object] objects,
26602660

26612661
elif seen.time_:
26622662
if is_time_array(objects):
2663+
# FIXME: need to ensure this is not timetz
26632664
opt = get_option("future.infer_time")
26642665
if opt is True:
26652666
import pyarrow as pa

pandas/core/dtypes/cast.py

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@
2020

2121
import numpy as np
2222

23+
from pandas._config import get_option
24+
2325
from pandas._libs import lib
2426
from pandas._libs.missing import (
2527
NA,
@@ -40,6 +42,7 @@
4042
IntCastingNaNError,
4143
LossySetitemError,
4244
)
45+
from pandas.util._exceptions import find_stack_level
4346

4447
from pandas.core.dtypes.common import (
4548
ensure_int8,
@@ -819,6 +822,29 @@ def infer_dtype_from_scalar(val) -> tuple[DtypeObj, Any]:
819822
val = val.asm8
820823
dtype = val.dtype
821824

825+
elif isinstance(val, dt.time):
826+
if val.tzinfo is None:
827+
# pyarrow doesn't have a dtype for timetz.
828+
opt = get_option("future.infer_time")
829+
if opt is None:
830+
warnings.warn(
831+
"Pandas type inference with a `datetime.time` "
832+
"object is deprecated. In a future version, this will give "
833+
"time32[pyarrow] dtype, which will require pyarrow to be "
834+
"installed. To opt in to the new behavior immediately set "
835+
"`pd.set_option('future.infer_time', True)`. To keep the "
836+
"old behavior pass `dtype=object`.",
837+
FutureWarning,
838+
stacklevel=find_stack_level(),
839+
)
840+
elif opt is True:
841+
import pyarrow as pa
842+
843+
pa_dtype = pa.time64("us")
844+
from pandas.core.arrays.arrow import ArrowDtype
845+
846+
dtype = ArrowDtype(pa_dtype)
847+
822848
elif is_bool(val):
823849
dtype = np.dtype(np.bool_)
824850

pandas/tests/frame/test_constructors.py

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3154,6 +3154,40 @@ def test_tzaware_data_tznaive_dtype(self, constructor, box, frame_or_series):
31543154
with pytest.raises(err, match=msg):
31553155
constructor(ts, dtype="M8[ns]")
31563156

3157+
@pytest.mark.parametrize(
3158+
"future", [pytest.param(True, marks=td.skip_if_no("pyarrow")), False, None]
3159+
)
3160+
def test_from_pytime(self, constructor, box, frame_or_series, future):
3161+
item = Timestamp("2023-05-04 08:53").time()
3162+
3163+
warn = None
3164+
if box is list or (box is dict and frame_or_series is Series):
3165+
msg = (
3166+
"Pandas type inference with a sequence of `datetime.time` "
3167+
"objects is deprecated"
3168+
)
3169+
else:
3170+
msg = "Pandas type inference with a `datetime.time` object is deprecated"
3171+
exp_dtype = np.dtype(object)
3172+
if future is None:
3173+
warn = FutureWarning
3174+
elif future is True:
3175+
import pyarrow as pa
3176+
3177+
pa_type = pa.time64("us")
3178+
exp_dtype = pd.ArrowDtype(pa_type)
3179+
3180+
with pd.option_context("future.infer_time", future):
3181+
with tm.assert_produces_warning(warn, match=msg):
3182+
result = constructor(item)
3183+
dtype = tm.get_dtype(result)
3184+
assert dtype == exp_dtype
3185+
3186+
aware = Timestamp("2023-05-04 08:53", tz="US/Pacific").timetz()
3187+
result2 = constructor(aware)
3188+
dtype = tm.get_dtype(result2)
3189+
assert dtype == np.dtype(object)
3190+
31573191

31583192
# TODO: better location for this test?
31593193
class TestAllowNonNano:

0 commit comments

Comments
 (0)