Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 25 additions & 0 deletions pandas/core/frame.py
Original file line number Diff line number Diff line change
Expand Up @@ -205,6 +205,8 @@
)
import pandas.plotting

from pandas.core.tools.datetimes import to_datetime

if TYPE_CHECKING:
import datetime

Expand Down Expand Up @@ -11632,6 +11634,27 @@ def all(
result = result.__finalize__(self, method="all")
return result

def convert_date_na_columns(self):
"""
Convert all columns containing only dates and nulls in a DataFrame to datetime objects.
"""
for col in self.columns:
if self.is_date_or_null_column(self[col]):
try:
self[col] = to_datetime(self[col])
except (ValueError, TypeError):
continue
else:
continue

def is_date_or_null_column(self, column: Series) -> bool:
"""Check if a pandas Series contains only datetime.date objects or nulls."""
for value in column:
from datetime import date
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

imports at the top of the file

if not (isna(value) or isinstance(value, date)):
return False
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lib.is_date_array

return True

@doc(make_doc("min", ndim=2))
def min(
self,
Expand All @@ -11640,6 +11663,7 @@ def min(
numeric_only: bool = False,
**kwargs,
):
self.convert_date_na_columns()
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

don't modify the dataframe.

result = super().min(axis, skipna, numeric_only, **kwargs)
if isinstance(result, Series):
result = result.__finalize__(self, method="min")
Expand All @@ -11653,6 +11677,7 @@ def max(
numeric_only: bool = False,
**kwargs,
):
self.convert_date_na_columns()
result = super().max(axis, skipna, numeric_only, **kwargs)
if isinstance(result, Series):
result = result.__finalize__(self, method="max")
Expand Down
64 changes: 64 additions & 0 deletions pandas/tests/frame/methods/test_minmax.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
import pytest
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

there is already a test_reductions.py file

import pandas as pd
import numpy as np
import datetime


def test_min_with_mixed_nan_and_dates():
"""Test min() with mix of NaN and datetime.date objects"""
data = {
"dates": [
np.nan,
np.nan,
datetime.date(2025, 1, 3),
datetime.date(2025, 1, 4),
],
}
df = pd.DataFrame(data)
result = df.min()
expected = pd.Series({"dates": datetime.date(2025, 1, 3)}, dtype="datetime64[ns]")
pd.testing.assert_series_equal(result, expected)


def test_min_with_all_nan():
"""Test min() with all NaN values (should return NaN)"""
data = {
"dates": [
np.nan,
np.nan,
np.nan,
],
}
df = pd.DataFrame(data)
result = df.min()
expected = pd.Series({"dates": np.nan}, dtype="datetime64[ns]")
pd.testing.assert_series_equal(result, expected)


def test_min_with_only_dates():
"""Test min() with only datetime.date objects (no NaN)"""
data = {
"dates": [
datetime.date(2025, 1, 3),
datetime.date(2025, 1, 4),
datetime.date(2025, 1, 1),
],
}
df = pd.DataFrame(data)
result = df.min()
expected = pd.Series({"dates": datetime.date(2025, 1, 1)}, dtype="datetime64[ns]")
pd.testing.assert_series_equal(result, expected)


def test_min_with_mixed_types_error():
"""Test min() with incompatible types (should raise TypeError)"""
data = {
"mixed": [
np.nan,
"string",
datetime.date(2025, 1, 3),
],
}
df = pd.DataFrame(data)
with pytest.raises(TypeError):
df.max()
Loading