diff --git a/ibis/backends/duckdb/__init__.py b/ibis/backends/duckdb/__init__.py index 3b8bc0667fb0..0d032f4720ed 100644 --- a/ibis/backends/duckdb/__init__.py +++ b/ibis/backends/duckdb/__init__.py @@ -1393,7 +1393,7 @@ def execute( # but calling `to_pylist()` will render it as None col.null_count ) - else col.to_pandas(timestamp_as_object=True) + else col.to_pandas() ) for name, col in zip(table.column_names, table.columns) } diff --git a/ibis/backends/tests/test_asof_join.py b/ibis/backends/tests/test_asof_join.py index bcf253c709d5..ce5f8245522b 100644 --- a/ibis/backends/tests/test_asof_join.py +++ b/ibis/backends/tests/test_asof_join.py @@ -111,7 +111,8 @@ def test_asof_join(con, time_left, time_right, time_df1, time_df2, direction, op result = result.sort_values(["group", "time"]).reset_index(drop=True) expected = expected.sort_values(["group", "time"]).reset_index(drop=True) - tm.assert_frame_equal(result[expected.columns], expected) + # duckdb returns datetime64[us], pandas defaults to use datetime64[ns] + tm.assert_frame_equal(result[expected.columns], expected, check_dtype=False) with pytest.raises(AssertionError): tm.assert_series_equal(result["time"], result["time_right"]) diff --git a/ibis/formats/pandas.py b/ibis/formats/pandas.py index c27c7ee426ea..b20777ccfa7f 100644 --- a/ibis/formats/pandas.py +++ b/ibis/formats/pandas.py @@ -200,8 +200,10 @@ def convert_Boolean(cls, s, dtype, pandas_type): @classmethod def convert_Timestamp(cls, s, dtype, pandas_type): - if isinstance(dtype, pd.DatetimeTZDtype): - return s.dt.tz_convert(dtype.timezone) + if isinstance(pandas_type, pd.DatetimeTZDtype) and isinstance( + s.dtype, pd.DatetimeTZDtype + ): + return s if s.dtype == pandas_type else s.dt.tz_convert(dtype.timezone) elif pdt.is_datetime64_dtype(s.dtype): return s.dt.tz_localize(dtype.timezone) else: diff --git a/ibis/tests/benchmarks/test_benchmarks.py b/ibis/tests/benchmarks/test_benchmarks.py index 99e32b9f4122..027058c25479 100644 --- a/ibis/tests/benchmarks/test_benchmarks.py +++ b/ibis/tests/benchmarks/test_benchmarks.py @@ -8,11 +8,13 @@ import os import random import string +from datetime import datetime from operator import attrgetter, itemgetter import numpy as np import pandas as pd import pytest +import pytz from packaging.version import parse as vparse from pytest import param @@ -914,3 +916,15 @@ def test_wide_drop_compile(benchmark, wide_table, cols_to_drop): benchmark( lambda expr: ibis.to_sql(expr, dialect="duckdb"), wide_table.drop(*cols_to_drop) ) + + +def test_duckdb_timestamp_conversion(benchmark): + pytest.importorskip("duckdb") + + start = datetime(2000, 1, 1, tzinfo=pytz.UTC) + stop = datetime(2000, 2, 1, tzinfo=pytz.UTC) + expr = ibis.range(start, stop, ibis.interval(seconds=1)).unnest() + + con = ibis.duckdb.connect() + series = benchmark(con.execute, expr) + assert series.size == (stop - start).total_seconds()