@@ -287,8 +287,13 @@ py::dict DuckDBPyResult::FetchNumpyInternal(bool stream, idx_t vectors_per_chunk
287287return res;
288288}
289289
290+ static void ReplaceDFColumn (PandasDataFrame &df,const char *col_name,idx_t idx,const py::handle &new_value) {
291+ df.attr (" drop" )(" columns" _a = col_name," inplace" _a =true );
292+ df.attr (" insert" )(idx, col_name, new_value," allow_duplicates" _a =false );
293+ }
294+
290295// TODO: unify these with an enum/flag to indicate which conversions to do
291- void DuckDBPyResult::ChangeToTZType (PandasDataFrame &df) {
296+ void DuckDBPyResult::ConvertDateTimeTypes (PandasDataFrame &df, bool date_as_object) const {
292297auto names = df.attr (" columns" ).cast <vector<string>>();
293298
294299for (idx_t i =0 ; i < result->ColumnCount (); i++) {
@@ -297,8 +302,10 @@ void DuckDBPyResult::ChangeToTZType(PandasDataFrame &df) {
297302auto utc_local = df[names[i].c_str ()].attr (" dt" ).attr (" tz_localize" )(" UTC" );
298303auto new_value = utc_local.attr (" dt" ).attr (" tz_convert" )(result->client_properties .time_zone );
299304// We need to create the column anew because the exact dt changed to a new timezone
300- df.attr (" drop" )(" columns" _a = names[i].c_str ()," inplace" _a =true );
301- df.attr (" __setitem__" )(names[i].c_str (), new_value);
305+ ReplaceDFColumn (df, names[i].c_str (), i, new_value);
306+ }else if (date_as_object && result->types [i] == LogicalType::DATE) {
307+ auto new_value = df[names[i].c_str ()].attr (" dt" ).attr (" date" );
308+ ReplaceDFColumn (df, names[i].c_str (), i, new_value);
302309}
303310}
304311}
@@ -374,20 +381,11 @@ PandasDataFrame DuckDBPyResult::FrameFromNumpy(bool date_as_object, const py::ha
374381}
375382
376383PandasDataFrame df = py::cast<PandasDataFrame>(pandas.attr (" DataFrame" ).attr (" from_dict" )(o));
377- // Unfortunately we have to do a type change here for timezones since these types are not supported by numpy
378- ChangeToTZType (df);
384+ // Convert TZ and (optionally) Date types
385+ ConvertDateTimeTypes (df, date_as_object );
379386
380387auto names = df.attr (" columns" ).cast <vector<string>>();
381388D_ASSERT (result->ColumnCount () == names.size ());
382- if (date_as_object) {
383- for (idx_t i =0 ; i < result->ColumnCount (); i++) {
384- if (result->types [i] == LogicalType::DATE) {
385- auto new_value = df[names[i].c_str ()].attr (" dt" ).attr (" date" );
386- df.attr (" drop" )(" columns" _a = names[i].c_str ()," inplace" _a =true );
387- df.attr (" __setitem__" )(names[i].c_str (), new_value);
388- }
389- }
390- }
391389return df;
392390}
393391