Skip to content

fix(ag-grid): honor dataset hour offset in time range filters - #41391

Merged
EnxDev merged 6 commits into
masterfrom
fix/104810-date-filter-hour-offset
Jul 7, 2026
Merged

EnxDev merged 6 commits into
masterfrom
fix/104810-date-filter-hour-offset

Conversation

@amaannawab923

Copy link
Copy Markdown
Contributor

SUMMARY

When a dataset is configured with a non-zero Hour Offset, date filters were landing on the wrong calendar day — e.g. filtering for a given date could return the previous day's rows.

The root cause is an asymmetry: result timestamps are shifted by +offset hours for display (via normalize_df / DateColumn), but the time-range filter was still comparing against the raw stored values. So the data you saw was offset-adjusted while the filter wasn't, and the two disagreed by the offset.

The fix shifts the time-filter bounds by -offset hours in get_time_filter, so the filter is evaluated in the same offset-adjusted space that's displayed. This covers the dashboard/explore time-range filter path. (The AG Grid column-level date filter builds its own SQL and isn't part of this change — I've left a note to follow that up separately.)

TESTING INSTRUCTIONS

  1. Edit a dataset's Settings and set Hour Offset to a non-zero value (e.g. -4).
  2. Build a chart on that dataset with a visible date column and apply a date-range filter.
  3. The rows returned should match the selected calendar day after the offset is applied, instead of being shifted by a day.

Unit tests added (no offset → raw bounds; positive offset → bounds shifted back; negative offset → bounds shifted forward). Existing time-filter tests still pass.

ADDITIONAL INFORMATION

  • Changes UI

This affects any dataset configured with a non-zero hour offset.

Result timestamps are displayed shifted by +offset hours (normalize_df /
DateColumn), but get_time_filter compared the raw stored values against the
requested range. With a non-zero dataset Hour Offset this made a date selection
land on the wrong calendar day (e.g. selecting Mar 24 returned Mar 23 rows).

Shift the time-filter bounds by -offset hours so the filter is evaluated in the
same offset-adjusted space that is displayed. Covers the dashboard/explore
time-range filter path; the AG Grid column-level date filter builds its own raw
SQL and is tracked separately. Add unit tests.
@amaannawab923 amaannawab923 changed the title fix(sqla): honor dataset hour offset in time range filters fix(ag-grid): honor dataset hour offset in time range filters Jun 24, 2026
@codecov

codecov Bot commented Jun 24, 2026 •

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 20.00000% with 4 lines in your changes missing coverage. Please review.
✅ Project coverage is 64.79%. Comparing base (53c3b1c) to head (61c4335).

Files with missing lines Patch % Lines
superset/models/helpers.py 20.00% 2 Missing and 2 partials ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##           master   #41391      +/-   ##
==========================================
- Coverage   64.79%   64.79%   -0.01%     
==========================================
  Files        2692     2692              
  Lines      149038   149043       +5     
  Branches    34398    34401       +3     
==========================================
+ Hits        96573    96574       +1     
- Misses      50696    50698       +2     
- Partials     1769     1771       +2     
Flag Coverage Δ
hive 39.19% <0.00%> (-0.01%) ⬇️
mysql 57.85% <20.00%> (-0.01%) ⬇️
postgres 57.91% <20.00%> (-0.01%) ⬇️
presto 40.72% <0.00%> (-0.01%) ⬇️
python 59.32% <20.00%> (-0.01%) ⬇️
sqlite 57.49% <20.00%> (-0.01%) ⬇️
unit 100.00% <ø> (ø)

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@EnxDev

EnxDev commented Jun 29, 2026

Copy link
Copy Markdown
Contributor

EnxDev's Review Agent — #41391 · HEAD ebcc990

comment — The fix is correct and well-targeted with good tests, but it's still a Draft and CI is red on auto-fixable formatting.

This is a fix PR. I verified the core logic: normalize_df shifts displayed timestamps by +offset (superset/utils/core.py:2041, df[...] += timedelta(hours=_col.offset)), while the time filter compares against raw stored values. So shifting the filter bounds by -offset is the right direction, and the math matches the tests (offset +4 → start 2024-01-01 00:00 becomes 2023-12-31 20:00). offset resolves on both concrete subclasses (SqlaTable column default 0, Query.offset returns 0), so datasets without an offset are unaffected — no regression for the default path.

🟡 Should-fix

  • CI red — pre-commit. auto-walrus and ruff-format both rewrote helpers.py and the new test file (2 files reformatted). Run pre-commit run --all-files and commit the auto-fixes — auto-walrus will likely collapse offset_hours = getattr(...) + if offset_hours: into a walrus. mypy/ruff already pass.
  • CI red — Python-Integration (test-postgres, test-mysql, test-sqlite, test-postgres-required). Since offset defaults to 0 everywhere, this change shouldn't alter existing-test behavior, so these are most likely infra/flake — but confirm they go green on a re-run rather than assuming.
  • Title scope is misleading. fix(ag-grid): … — the fix lives in the generic SQLA time-range filter (get_time_filter) and, by the author's own note, explicitly does not touch the AG Grid column-level date filter. Retitle to fix(sqla) / fix(explore) so the scope is accurate.

🔵 Nits

  • superset/models/helpers.py:2807 — getattr(self, "offset", 0) default 0 is dead: every concrete subclass defines offset (the ExploreMixin base raises NotImplementedError, which getattr would not swallow anyway). self.offset or 0 conveys the intent. Harmless either way.

🙌 Praise

  • tests/unit_tests/models/test_time_filter_hour_offset.py — covers zero / positive / negative offset and asserts the exact shifted boundary in the generated SQL (and that the unshifted bound is absent). Real regression guard, not a smoke test.

Reviewed by EnxDev's Review Agent — @EnxDev · HEAD ebcc990.

@EnxDev
EnxDev marked this pull request as ready for review July 7, 2026 09:08
@dosubot dosubot Bot added data:dataset Related to dataset configurations explore:filter Related to filters in Explore explore:time Related to the time filters in Explore labels Jul 7, 2026
@bito-code-review

bito-code-review Bot commented Jul 7, 2026 •

Copy link
Copy Markdown
Contributor

Code Review Agent Run #52b4dd

Actionable Suggestions - 0
Review Details
  • Files reviewed - 2 · Commit Range: ebcc990..879aefc
    • superset/models/helpers.py
    • tests/unit_tests/models/test_time_filter_hour_offset.py
  • Files skipped - 0
  • Tools
    • MyPy (Static Code Analysis) - ✔︎ Successful
    • Astral Ruff (Static Code Analysis) - ✔︎ Successful
    • Whispers (Secret Scanner) - ✔︎ Successful
    • Detect-secrets (Secret Scanner) - ✔︎ Successful

Bito Usage Guide

Commands

Type the following command in the pull request comment and save the comment.

  • /review - Manually triggers a full AI review.

  • /pause - Pauses automatic reviews on this pull request.

  • /resume - Resumes automatic reviews.

  • /resolve - Marks all Bito-posted review comments as resolved.

  • /abort - Cancels all in-progress reviews.

Refer to the documentation for additional commands.

Configuration

This repository uses Superset You can customize the agent settings here or contact your Bito workspace admin at evan@preset.io.

Documentation & Help

AI Code Review powered by Bito Logo

Comment thread superset/models/helpers.py Outdated
@bito-code-review

Copy link
Copy Markdown
Contributor

The flagged issue is correct. The local variable offset_hours is introduced without an explicit type annotation, which violates the project's type hint standards. You can resolve this by adding the : int type annotation to the variable declaration.

        offset_hours: int = getattr(self, "offset", 0) or 0

There are no other comments on this PR to address. Would you like me to check for any other potential type hint improvements in the modified file?

superset/models/helpers.py

offset_hours: int = getattr(self, "offset", 0) or 0

The #104810 fix makes get_time_filter honor the dataset Hour Offset, shifting
temporal filter bounds. Two pre-existing integration tests assert raw date
literals against the shared birth_names table, which other tests in the suite
can leave with a non-zero offset; the shift then broke their expected SQL.

Pin the dataset offset to 0 in test_where_operators (which tests filter
operators, not offset) and in test_time_offset_comparison_queries_use_chart_row_limit
(which asserts comparison-window date literals), keeping both deterministic.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@EnxDev
EnxDev force-pushed the fix/104810-date-filter-hour-offset branch from 87c851b to 76842c7 Compare July 7, 2026 14:24

@EnxDev EnxDev left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

From manual testing:

  • Before
Image
  • After
Image

EnxDev and others added 2 commits July 7, 2026 16:49
Pre-commit auto-fixes on the temporal-filter offset code: use the walrus
operator for the offset guard in get_time_filter and collapse a one-line
test helper signature. No behavior change.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@EnxDev
EnxDev merged commit 9b508eb into master Jul 7, 2026
59 checks passed
@EnxDev
EnxDev deleted the fix/104810-date-filter-hour-offset branch July 7, 2026 15:12
@bito-code-review

Copy link
Copy Markdown
Contributor

Bito Automatic Review Skipped – PR Already Merged

Bito scheduled an automatic review for this pull request, but the review was skipped because this PR was merged before the review could be run.
No action is needed if you didn't intend to review it. To get a review, you can type /review in a comment and save it

devin-ai-integration Bot added a commit to raymondtangsc/superset that referenced this pull request Jul 20, 2026
Rebase resolution for the dataset-timezone time filter against master's
dataset "Hour Offset" support (apache#41391). The timezone conversion takes
precedence and the hour-offset shift is kept as the fallback, matching the
precedence already used in normalize_dttm_col. Extracted the boundary
adjustment into _adjust_time_filter_boundaries so get_time_filter stays under
the mccabe complexity limit.

Co-Authored-By: bot_apk <apk@cognition.ai>
rusackas added a commit to jayakarkatika/superset that referenced this pull request Aug 4, 2026
…xtra values

Rebases the DST-aware timezone conversion onto master, which since merged
apache#41391's fixed Hour Offset shift for the same get_time_filter method. The
two mechanisms now layer instead of conflict: a configured extra.timezone
takes precedence (it is strictly more correct, since it handles DST), and
the legacy Hour Offset still applies exactly as before when no timezone is
configured.

Also addresses two outstanding review threads on get_time_filter:
- get_dataset_timezone now validates that extra["timezone"] is a string
  before returning it, since extra is arbitrary user-supplied JSON and a
  non-string value would otherwise reach ZoneInfo() and raise TypeError.
  get_time_filter also catches TypeError alongside ZoneInfoNotFoundError
  as defense in depth.
- Confirmed the epoch-rendering concern (naive datetime .timestamp() being
  interpreted in the server's local timezone) is already fixed on master
  via apache#39782's UTC-anchoring in dttm_sql_literal; added a regression test
  tying it to the dataset-timezone path specifically.

Adds test coverage for the reconciliation (offset-only fallback, timezone
taking precedence over a configured offset) and the non-string timezone
guard.

Co-Authored-By: Claude <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

data:dataset Related to dataset configurations explore:filter Related to filters in Explore explore:time Related to the time filters in Explore size/L

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants