This is an automated email from the ASF dual-hosted git repository.
rusackas pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/superset.git
The following commit(s) were added to refs/heads/master by this push:
new 1d4c3a2adb5 fix(core): don't blank a datetime column when its format
coerces every value to NaT (#42405)
1d4c3a2adb5 is described below
commit 1d4c3a2adb5f4115c890fbfcbc39c3a98ce27a5d
Author: Evan Rusackas <[email protected]>
AuthorDate: Tue Jul 28 15:18:53 2026 -0700
fix(core): don't blank a datetime column when its format coerces every
value to NaT (#42405)
Co-authored-by: Claude Code <[email protected]>
---
superset/utils/core.py | 15 ++++++++++++++-
tests/unit_tests/utils/test_core.py | 16 ++++++++++++++++
2 files changed, 30 insertions(+), 1 deletion(-)
diff --git a/superset/utils/core.py b/superset/utils/core.py
index 5810beba34a..09129c64eed 100644
--- a/superset/utils/core.py
+++ b/superset/utils/core.py
@@ -2017,13 +2017,26 @@ def _process_datetime_column(
# Parse with or without format (suppress warning if no format)
if format_to_use:
- df[col.col_label] = pd.to_datetime(
+ converted = pd.to_datetime(
df[col.col_label],
utc=False,
format=format_to_use,
errors="coerce",
exact=False,
)
+ # A format that coerces every non-null value to NaT is a mismatch
+ # (e.g. an epoch-millis column that inherited a '%Y' string format
+ # when used as a chart's granularity). Assigning it would silently
+ # blank the whole column, so keep the original values instead.
+ if df[col.col_label].notna().any() and not converted.notna().any():
+ logger.warning(
+ "Datetime format %s coerced every value of column %s to
NaT; "
+ "keeping the original values",
+ format_to_use,
+ col.col_label,
+ )
+ else:
+ df[col.col_label] = converted
else:
with warnings.catch_warnings():
warnings.filterwarnings("ignore", message=".*Could not infer
format.*")
diff --git a/tests/unit_tests/utils/test_core.py
b/tests/unit_tests/utils/test_core.py
index 9a33ee55ed4..7fe3eee7eff 100644
--- a/tests/unit_tests/utils/test_core.py
+++ b/tests/unit_tests/utils/test_core.py
@@ -273,6 +273,22 @@ def test_normalize_dttm_col() -> None:
assert df["__time"].astype(str).tolist() == ["2017-07-01"]
+def test_normalize_dttm_col_mismatched_format_keeps_values() -> None:
+ """A datetime format that coerces every value to NaT is a mismatch (e.g. an
+ epoch-millis column that inherited a ``%Y`` string format when used as a
+ chart's granularity); applying it would silently blank the whole column, so
+ the original values are kept instead of being nulled. Regression for the
+ Samples pane showing N/A for such columns."""
+ df = pd.DataFrame({"year": [1136073600000, 473385600000]}) # epoch ms
+ before = df["year"].tolist()
+
+ normalize_dttm_col(df, (DateColumn(col_label="year",
timestamp_format="%Y"),))
+
+ # not blanked to NaT/None
+ assert df["year"].notna().all()
+ assert df["year"].tolist() == before
+
+
def test_normalize_dttm_col_epoch_seconds() -> None:
"""Test conversion of epoch seconds."""
df = pd.DataFrame(