Skip to content

Commit 3883a00

Browse files
committed
Handle construction from scalar
1 parent 5b4ea4c commit 3883a00

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
@@ -2621,7 +2621,7 @@ def maybe_convert_objects(ndarray[object] objects,
26212621
seen.object_ = True
26222622
break
26232623
elif PyTime_Check(val):
2624-
if convert_non_numeric:
2624+
if convert_non_numeric and val.tzinfo is None:
26252625
seen.time_ = True
26262626
else:
26272627
seen.object_ = True
@@ -2692,6 +2692,7 @@ def maybe_convert_objects(ndarray[object] objects,
26922692

26932693
elif seen.time_:
26942694
if is_time_array(objects):
2695+
# FIXME: need to ensure this is not timetz
26952696
opt = get_option("future.infer_time")
26962697
if opt is True:
26972698
import pyarrow as pa

pandas/core/dtypes/cast.py

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

1919
import numpy as np
2020

21+
from pandas._config import get_option
22+
2123
from pandas._libs import lib
2224
from pandas._libs.missing import (
2325
NA,
@@ -38,6 +40,7 @@
3840
IntCastingNaNError,
3941
LossySetitemError,
4042
)
43+
from pandas.util._exceptions import find_stack_level
4144

4245
from pandas.core.dtypes.common import (
4346
ensure_int8,
@@ -822,6 +825,29 @@ def infer_dtype_from_scalar(val) -> tuple[DtypeObj, Any]:
822825
val = val.asm8
823826
dtype = val.dtype
824827

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

pandas/tests/frame/test_constructors.py

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

3171+
@pytest.mark.parametrize(
3172+
"future", [pytest.param(True, marks=td.skip_if_no("pyarrow")), False, None]
3173+
)
3174+
def test_from_pytime(self, constructor, box, frame_or_series, future):
3175+
item = Timestamp("2023-05-04 08:53").time()
3176+
3177+
warn = None
3178+
if box is list or (box is dict and frame_or_series is Series):
3179+
msg = (
3180+
"Pandas type inference with a sequence of `datetime.time` "
3181+
"objects is deprecated"
3182+
)
3183+
else:
3184+
msg = "Pandas type inference with a `datetime.time` object is deprecated"
3185+
exp_dtype = np.dtype(object)
3186+
if future is None:
3187+
warn = FutureWarning
3188+
elif future is True:
3189+
import pyarrow as pa
3190+
3191+
pa_type = pa.time64("us")
3192+
exp_dtype = pd.ArrowDtype(pa_type)
3193+
3194+
with pd.option_context("future.infer_time", future):
3195+
with tm.assert_produces_warning(warn, match=msg):
3196+
result = constructor(item)
3197+
dtype = tm.get_dtype(result)
3198+
assert dtype == exp_dtype
3199+
3200+
aware = Timestamp("2023-05-04 08:53", tz="US/Pacific").timetz()
3201+
result2 = constructor(aware)
3202+
dtype = tm.get_dtype(result2)
3203+
assert dtype == np.dtype(object)
3204+
31713205

31723206
# TODO: better location for this test?
31733207
class TestAllowNonNano:

0 commit comments

Comments
 (0)