Twiink commented on code in PR #45671:
URL: https://github.com/apache/superset/pull/45671#discussion_r4434209960


##########
superset/models/helpers.py:
##########
@@ -3409,12 +3414,18 @@ def get_offset_custom_or_inherit(
             # the range against itself, and a 36-hour range would shift by a
             # single day and overlap it. Whole-day ranges resolve to the same
             # instant either way.
-            duration = outer_to_dttm - outer_from_dttm
+            from_comparison, to_comparison = get_comparable_bounds(
+                outer_from_dttm, outer_to_dttm
+            )
+            duration = to_comparison - from_comparison

Review Comment:
   Fixed in c10d3fe7. For inherited periods containing an explicit-offset 
boundary, both the duration and the shifted comparison endpoints now use the 
destination column's adjusted SQL bounds. The endpoints retain explicit UTC 
tags to prevent a second dataset timezone/Hour Offset adjustment. The matching 
temporal filter uses those same endpoints for categorical axes as well. Fully 
naive ranges retain their existing behavior.
   
   Added regressions through processing_time_offsets that capture the 
comparison request, render the real SQL predicates, and execute them against 
SQLite boundary rows. They assert equal period durations, comparison_end == 
main_start, consistent temporal-filter bounds, and zero overlapping rows. 
Coverage includes both mixed-bound directions, Europe/Berlin across DST, Hour 
Offset 8, DATE columns, and datetime/categorical axes. The reported 8h/6h 
overlap is eliminated.
   
   Local validation: 771 passed, 1 skipped; the same two previously verified 
Windows baseline failures were deselected. Ruff/formatting passed, Linux-target 
mypy passed for all 12 changed Python files, and direct project-configured 
Pylint scored 10/10. New remote CI has not yet been confirmed.



##########
superset/common/query_object.py:
##########
@@ -782,11 +785,56 @@ def exec_post_processing(self, df: DataFrame) -> 
DataFrame:
                     func = extra_ops[operation]
                 options = post_process.get("options", {})
                 if operation == "resample":
-                    options = self._resolve_resample_options(options)
+                    options = self._resolve_resample_options(options, df)
                 df = func(df, **options)
             return df
 
-    def _resolve_resample_options(self, options: dict[str, Any]) -> dict[str, 
Any]:
+    def _is_resample_calendar_column(self) -> bool:
+        """Resolve physical temporal metadata for legacy and base-axis 
charts."""
+        if self.datasource is None:
+            return False
+        names = [self.granularity or get_x_axis_label(self.columns)]
+        if not self.granularity:
+            names.extend(
+                col.get("sqlExpression")
+                for col in get_base_axis_columns(self.columns)[:1]
+                if isinstance(col, dict)
+            )
+        time_col = next(
+            (col for col in self.datasource.columns if col.column_name in 
names), None
+        )
+        is_calendar = getattr(self.datasource, "is_calendar_date_column", None)
+        return bool(callable(is_calendar) and is_calendar(time_col))
+
+    def _resample_display_bound(
+        self, bound: datetime | None, df: DataFrame
+    ) -> datetime | None:
+        """Align explicit instants with a datasource's normalized display 
frame."""
+        if bound is None or bound.utcoffset() is None or self.datasource is 
None:
+            return bound
+        if self._is_resample_calendar_column():
+            return bound.replace(tzinfo=None)
+        get_timezone = getattr(self.datasource, "get_dataset_timezone", None)
+        dataset_timezone = get_timezone() if callable(get_timezone) else None
+        if isinstance(dataset_timezone, str):
+            try:
+                return 
bound.astimezone(ZoneInfo(dataset_timezone)).replace(tzinfo=None)
+            except ZoneInfoNotFoundError:

Review Comment:
   Fixed in c10d3fe7 with the nonempty-string guard you suggested. An empty 
dataset timezone now follows the same unset-timezone path as adjust_time_bounds 
and normalize_dttm_col. Added end-to-end post-processing regressions for 
explicit-offset ranges with an empty timezone, both without Hour Offset and 
with Hour Offset 8; they verify the padded endpoints and preservation of the 
normalized data point.



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to