Skip to content

feat(date-filter): add sub-hour time range presets (needs review)#41527

Open
imddevaraj wants to merge 14 commits into
apache:masterfrom
imddevaraj:feat/sub-hour-time-range-presets
Open

feat(date-filter): add sub-hour time range presets (needs review)#41527
imddevaraj wants to merge 14 commits into
apache:masterfrom
imddevaraj:feat/sub-hour-time-range-presets

Conversation

@imddevaraj

@imddevaraj imddevaraj commented Jun 29, 2026

Copy link
Copy Markdown

SUMMARY

Add four quick-select presets to the Last… (Common) frame of the date range filter — both in the Explore chart builder and in Dashboard native Time filters:

  • Last 5 minutes
  • Last 15 minutes
  • Last 30 minutes
  • Last 1 hour

The new options appear at the top of the radio group, grouped above the existing day/week/month presets, giving users a fast path for recent/real-time monitoring use cases.

Backend fix included: get_since_until() had a latent bug where hour was absent from the last/next/this time-unit regex despite being documented as supported. This PR adds hour to the pattern so Last 1 hour resolves correctly. The get_relative_base() function already classified hour as a granular unit (→ 'now' base), so no additional changes were needed there.

BEFORE/AFTER SCREENSHOTS OR ANIMATED GIF

Before: Common frame shows Last day / Last week / Last month / Last quarter / Last year

After: Common frame shows Last 5 minutes / Last 15 minutes / Last 30 minutes / Last 1 hour / Last day / Last week / Last month / Last quarter / Last year

TESTING INSTRUCTIONS

  1. Open any dashboard → Filters+ Add filterTime range
  2. Open the time control; the frame selector defaults to Last
  3. Verify the four new options appear above Last day
  4. Select Last 15 minutes, click Apply — charts in scope re-query for the last 15 minutes of data

Unit tests:

# Frontend
cd superset-frontend
npx jest --testPathPatterns="DateFilterControl/tests/utils" --no-coverage --forceExit

# Backend
pytest tests/unit_tests/utils/date_parser_tests.py::test_get_since_until_sub_hour_presets -v

ADDITIONAL INFORMATION

  • Changes UI
  • Introduces new feature or API
  • Has associated issue:
  • Required feature flags:
  • Includes DB Migration

… Last 1 hour)

Add four new preset options to the DateFilterControl Common (Last...) frame:
- Last 5 minutes
- Last 15 minutes
- Last 30 minutes
- Last 1 hour

These presets appear in both the Explore chart builder and the Dashboard
native Time filter, grouped above the existing day/week/month presets.

Backend: fix a latent bug where 'hour' was missing from the time-unit regex
in get_since_until(), causing 'Last 1 hour' to fail to parse despite being
documented as supported. The regex now covers
second|minute|hour|day|week|month|quarter|year.

Frontend:
- Extend CommonRangeType union with the four new string literals
- Add entries to COMMON_RANGE_OPTIONS and COMMON_RANGE_SET in constants.ts
- COMMON_RANGE_VALUES_SET and guessFrame() update automatically

Tests:
- Frontend: two new test() blocks asserting guessFrame() returns 'Common'
  for all four new presets and that existing presets are unaffected
- Backend: test_get_since_until_sub_hour_presets covers all four presets
  with relative_end='now' and asserts correct datetime pairs
@dosubot dosubot Bot added change:backend Requires changing the backend change:frontend Requires changing the frontend dashboard:native-filters Related to the native filters of the Dashboard explore:time Related to the time filters in Explore labels Jun 29, 2026
Comment thread tests/unit_tests/utils/date_parser_tests.py Outdated
@bito-code-review

Copy link
Copy Markdown
Contributor

The suggestion to add a type annotation to the local variable is valid, as it improves code readability and maintains consistency with the existing codebase. To resolve this, you should explicitly declare the type of the variable when it is initialized.

Since the provided context does not include the specific lines in tests/unit_tests/utils/date_parser_tests.py where the variable is defined, I cannot provide the exact code snippet for the fix. Please ensure the variable is annotated with its appropriate type (e.g., variable: Type = value).

Regarding other comments on this PR, the current review data is empty, so there are no additional comments to address at this time.

@netlify

netlify Bot commented Jun 29, 2026

Copy link
Copy Markdown

Deploy Preview for superset-docs-preview ready!

Name Link
🔨 Latest commit 7c556bd
🔍 Latest deploy log https://app.netlify.com/projects/superset-docs-preview/deploys/6a473f5aa25f0d0008b408bf
😎 Deploy Preview https://deploy-preview-41527--superset-docs-preview.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.
🤖 Make changes Run an agent on this branch

To edit notification comments on pull requests, go to your Netlify project configuration.

@bito-code-review bito-code-review Bot 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.

Code Review Agent Run #f83bec

Actionable Suggestions - 1
  • superset-frontend/src/explore/components/controls/DateFilterControl/tests/utils.test.ts - 1
Additional Suggestions - 1
  • superset-frontend/src/explore/components/controls/DateFilterControl/tests/utils.test.ts - 1
    • Misleading test name · Line 199-205
      Test name uses 'still returns' implying a regression scenario, but no prior behavior is documented in the diff. If these test existing behavior (not a regression), consider a more accurate name like 'guessFrame returns Common for day/week/month presets'.
Filtered by Review Rules

Bito filtered these suggestions based on rules created automatically for your feedback. Manage rules.

  • superset-frontend/src/explore/components/controls/DateFilterControl/types.ts - 1
Review Details
  • Files reviewed - 6 · Commit Range: 50873ec..50873ec
    • superset-frontend/.gitignore
    • superset-frontend/src/explore/components/controls/DateFilterControl/tests/utils.test.ts
    • superset-frontend/src/explore/components/controls/DateFilterControl/types.ts
    • superset-frontend/src/explore/components/controls/DateFilterControl/utils/constants.ts
    • superset/utils/date_parser.py
    • tests/unit_tests/utils/date_parser_tests.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
    • Eslint (Linter) - ✔︎ 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

@sadpandajoe

Copy link
Copy Markdown
Member

@yousoph @kasiazjc thoughts on this feature?

@imddevaraj wondering if we can make this more generic? Like right now we are adding some defaults but the list gets bigger as others may want more like, what if i wanted last 4 hours, 24 hours, 8 hours, etc?

@imddevaraj

Copy link
Copy Markdown
Author

/review

@bito-code-review

bito-code-review Bot commented Jun 30, 2026

Copy link
Copy Markdown
Contributor

Code Review Agent Run #6a52b5

Actionable Suggestions - 0
Filtered by Review Rules

Bito filtered these suggestions based on rules created automatically for your feedback. Manage rules.

  • superset-frontend/src/explore/components/controls/DateFilterControl/tests/utils.test.ts - 1
Review Details
  • Files reviewed - 6 · Commit Range: 50873ec..a876ae0
    • superset-frontend/.gitignore
    • superset-frontend/src/explore/components/controls/DateFilterControl/tests/utils.test.ts
    • superset-frontend/src/explore/components/controls/DateFilterControl/types.ts
    • superset-frontend/src/explore/components/controls/DateFilterControl/utils/constants.ts
    • superset/utils/date_parser.py
    • tests/unit_tests/utils/date_parser_tests.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
    • Eslint (Linter) - ✔︎ 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

…icker

- Backend: Last/Next N second/minute/hour now appends 'now' as the
  until/since bound instead of 'today' (midnight), preventing the
  'From date cannot be larger than to date' error that fired at any
  time of day when DEFAULT_RELATIVE_END_TIME='today'.

- Frontend: Replace the fixed radio list in CommonFrame with an 'Other'
  row that exposes a number input and unit select, enabling arbitrary
  ranges like 'Last 4 hours' or 'Last 24 hours' without hard-coding
  every possible preset.

- Tests: new Python test test_get_since_until_granular_units_use_now_by_default
  and new Jest suite CommonFrame.test.tsx (10 tests).
@pull-request-size pull-request-size Bot added size/L and removed size/M labels Jun 30, 2026
@imddevaraj

Copy link
Copy Markdown
Author

/review

@imddevaraj

Copy link
Copy Markdown
Author

@yousoph @kasiazjc thoughts on this feature?

@imddevaraj wondering if we can make this more generic? Like right now we are adding some defaults but the list gets bigger as others may want more like, what if i wanted last 4 hours, 24 hours, 8 hours, etc?

@sadpandajoe
Good suggestion. I've updated the implementation to make it more generic. Instead of supporting only the initial default ranges, the quick-range list is now configurable, making it easy to add additional options such as Last 4 Hours, Last 8 Hours, Last 24 Hours, or any other commonly requested time ranges in the future without further code changes.

@bito-code-review bito-code-review Bot 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.

Code Review Agent Run #14bd76

Actionable Suggestions - 2
  • superset-frontend/src/explore/components/controls/DateFilterControl/components/CommonFrame.tsx - 1
    • Missing useEffect for side-effect in render · Line 77-79
  • superset-frontend/src/explore/components/controls/DateFilterControl/utils/constants.ts - 1
Additional Suggestions - 3
  • superset-frontend/src/explore/components/controls/DateFilterControl/tests/CommonFrame.test.tsx - 2
    • Flaky onChange assertion · Line 50-54
      The test 'defaults to Last week when value does not match any known range' asserts `onChange` was called with 'Last week' but doesn't verify call count. Since `CommonFrame` calls `props.onChange('Last week')` during render (line 77-79), React StrictMode or future concurrent-render changes could cause multiple calls, making this assertion pass incorrectly. Add `expect(onChange).toHaveBeenCalledTimes(1)` to enforce exactly one call.
    • Flaky onChange assertion · Line 92-103
      The test 'changing the number input emits an updated Last N unit string' extracts the last onChange call without verifying call count. If React StrictMode causes an extra render-time call, the last call might not be the expected input-change emission. Add `expect(onChange).toHaveBeenCalledTimes(1)` to guarantee the test captures only the user-interaction emission.
  • superset-frontend/src/explore/components/controls/DateFilterControl/types.ts - 1
    • Type narrowing lost on union-to-string · Line 80-80
      The change from a literal union type to `string` loses compile-time type safety. While the JSDoc explains the runtime validation via `COMMON_RANGE_REGEX`, the type cannot guide callers toward valid values at compile time. A branded type would restore some safety while supporting the flexible pattern.
Filtered by Review Rules

Bito filtered these suggestions based on rules created automatically for your feedback. Manage rules.

  • superset-frontend/src/explore/components/controls/DateFilterControl/components/CommonFrame.tsx - 1
    • Duplicate regex not using imported constant · Line 51-56
Review Details
  • Files reviewed - 9 · Commit Range: 50873ec..41c45d5
    • superset-frontend/.gitignore
    • superset-frontend/src/explore/components/controls/DateFilterControl/components/CommonFrame.tsx
    • superset-frontend/src/explore/components/controls/DateFilterControl/tests/CommonFrame.test.tsx
    • superset-frontend/src/explore/components/controls/DateFilterControl/tests/utils.test.ts
    • superset-frontend/src/explore/components/controls/DateFilterControl/types.ts
    • superset-frontend/src/explore/components/controls/DateFilterControl/utils/constants.ts
    • superset-frontend/src/explore/components/controls/DateFilterControl/utils/dateFilterUtils.ts
    • superset/utils/date_parser.py
    • tests/unit_tests/utils/date_parser_tests.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
    • Eslint (Linter) - ✔︎ 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

@bito-code-review

bito-code-review Bot commented Jun 30, 2026

Copy link
Copy Markdown
Contributor

Code Review Agent Run #6dc29a

Actionable Suggestions - 0
Review Details
  • Files reviewed - 9 · Commit Range: 50873ec..41c45d5
    • superset-frontend/.gitignore
    • superset-frontend/src/explore/components/controls/DateFilterControl/components/CommonFrame.tsx
    • superset-frontend/src/explore/components/controls/DateFilterControl/tests/CommonFrame.test.tsx
    • superset-frontend/src/explore/components/controls/DateFilterControl/tests/utils.test.ts
    • superset-frontend/src/explore/components/controls/DateFilterControl/types.ts
    • superset-frontend/src/explore/components/controls/DateFilterControl/utils/constants.ts
    • superset-frontend/src/explore/components/controls/DateFilterControl/utils/dateFilterUtils.ts
    • superset/utils/date_parser.py
    • tests/unit_tests/utils/date_parser_tests.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
    • Eslint (Linter) - ✔︎ 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

@imddevaraj

Copy link
Copy Markdown
Author

/review

@bito-code-review

bito-code-review Bot commented Jun 30, 2026

Copy link
Copy Markdown
Contributor

Code Review Agent Run #4a179e

Actionable Suggestions - 0
Additional Suggestions - 2
  • superset-frontend/src/explore/components/controls/DateFilterControl/components/CommonFrame.tsx - 1
    • Vague eslint-disable masks warning · Line 84-84
      The eslint-disable-line comment on line 84 ('// eslint-disable-line react-hooks/exhaustive-deps') uses generic rationale ('to avoid calling onChange synchronously during render') that does not specifically justify omitting `props.onChange`. This disables a valid linter warning for a real stale-closure risk, making future maintainers unaware of the dependency gap.
  • superset/utils/date_parser.py - 1
    • Missing test coverage for hour unit · Line 434-434
      The tests at line 772-858 cover "Last 1 hour", "Last 30 minutes" etc. with explicit numbers, but there are no tests for "Last hour" or "Next hour" (singular without numbers) that would exercise the handle_scope_and_unit path added at line 567.
Review Details
  • Files reviewed - 9 · Commit Range: 50873ec..a148e80
    • superset-frontend/.gitignore
    • superset-frontend/src/explore/components/controls/DateFilterControl/components/CommonFrame.tsx
    • superset-frontend/src/explore/components/controls/DateFilterControl/tests/CommonFrame.test.tsx
    • superset-frontend/src/explore/components/controls/DateFilterControl/tests/utils.test.ts
    • superset-frontend/src/explore/components/controls/DateFilterControl/types.ts
    • superset-frontend/src/explore/components/controls/DateFilterControl/utils/constants.ts
    • superset-frontend/src/explore/components/controls/DateFilterControl/utils/dateFilterUtils.ts
    • superset/utils/date_parser.py
    • tests/unit_tests/utils/date_parser_tests.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
    • Eslint (Linter) - ✔︎ 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

@bito-code-review

bito-code-review Bot commented Jun 30, 2026

Copy link
Copy Markdown
Contributor

Code Review Agent Run #8efc47

Actionable Suggestions - 0
Additional Suggestions - 2
  • superset-frontend/src/explore/components/controls/DateFilterControl/utils/constants.ts - 1
    • Inconsistent regex with backend · Line 63-64
      The docstring says the regex 'mirrors the backend regex in superset/utils/date_parser.py', but the backend uses `r"^Last\s+[0-9]+\s+(second|minute|hour)s?$"` for sub-day units (requiring a number) while this regex makes the number optional via `(\d+\s+)?`. This creates a semantic mismatch where the frontend accepts 'Last day' but the backend only handles 'Last 1 day' for sub-day units.
  • superset-frontend/src/explore/components/controls/DateFilterControl/components/CommonFrame.tsx - 1
    • Missing type annotation · Line 88-88
      The `handleRadioChange` handler uses `e: any` for its event parameter. Use the `RadioChangeEvent` type from antd (imported through the existing Radio import or directly) and access `e.target.value` via `target.value` per the antd RadioChangeEvent definition. This aligns with the project's TypeScript typing standards per AGENTS.md.
Review Details
  • Files reviewed - 9 · Commit Range: 50873ec..a148e80
    • superset-frontend/.gitignore
    • superset-frontend/src/explore/components/controls/DateFilterControl/components/CommonFrame.tsx
    • superset-frontend/src/explore/components/controls/DateFilterControl/tests/CommonFrame.test.tsx
    • superset-frontend/src/explore/components/controls/DateFilterControl/tests/utils.test.ts
    • superset-frontend/src/explore/components/controls/DateFilterControl/types.ts
    • superset-frontend/src/explore/components/controls/DateFilterControl/utils/constants.ts
    • superset-frontend/src/explore/components/controls/DateFilterControl/utils/dateFilterUtils.ts
    • superset/utils/date_parser.py
    • tests/unit_tests/utils/date_parser_tests.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
    • Eslint (Linter) - ✔︎ 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/utils/date_parser.py Outdated
Comment thread tests/unit_tests/utils/date_parser_tests.py
Comment thread tests/unit_tests/utils/date_parser_tests.py Outdated
Comment thread superset/utils/date_parser.py Outdated
@codecov

codecov Bot commented Jul 1, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 75.00000% with 12 lines in your changes missing coverage. Please review.
✅ Project coverage is 64.61%. Comparing base (46a153d) to head (7c556bd).
⚠️ Report is 328 commits behind head on master.

Files with missing lines Patch % Lines
superset/utils/date_parser.py 0.00% 8 Missing ⚠️
...trols/DateFilterControl/components/CommonFrame.tsx 88.88% 4 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##           master   #41527      +/-   ##
==========================================
- Coverage   64.61%   64.61%   -0.01%     
==========================================
  Files        2684     2684              
  Lines      148514   148550      +36     
  Branches    34263    34274      +11     
==========================================
+ Hits        95969    95989      +20     
- Misses      50786    50799      +13     
- Partials     1759     1762       +3     
Flag Coverage Δ
hive 39.18% <0.00%> (-0.01%) ⬇️
javascript 69.41% <90.00%> (+<0.01%) ⬆️
mysql 57.81% <0.00%> (-0.01%) ⬇️
postgres 57.87% <0.00%> (-0.02%) ⬇️
presto 40.72% <0.00%> (-0.01%) ⬇️
python 59.26% <0.00%> (-0.02%) ⬇️
sqlite 57.45% <0.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.

devaraj-durairaj_aaglobal and others added 2 commits July 1, 2026 13:49
- Replace any with RadioChangeEvent in CommonFrame handleRadioChange
- Add str annotations to granular regex pattern variables in date_parser
- Make numeric count optional in granular patterns to match Last/Next hour forms
- Fix customN/customUnit init to use defaults when current value is a preset,
  preventing Other click from emitting a preset string and snapping radio back
- Add explicit type annotations to expected, expected_until, expected_since
  in date_parser unit tests
@imddevaraj

Copy link
Copy Markdown
Author

/resolve

@bito-code-review bito-code-review Bot 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.

Code Review Agent Run #4b128a

Actionable Suggestions - 2
  • superset/utils/date_parser.py - 2
Review Details
  • Files reviewed - 3 · Commit Range: a148e80..77b3792
    • superset-frontend/src/explore/components/controls/DateFilterControl/components/CommonFrame.tsx
    • superset/utils/date_parser.py
    • tests/unit_tests/utils/date_parser_tests.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/utils/date_parser.py Outdated
Comment thread superset/utils/date_parser.py Outdated
…erns

Replace (second|minute|hour)s? with (?:seconds?|minutes?|hours?) in both
_granular_last_pattern and _granular_next_pattern so each unit owns its own
optional plural suffix, removes the unused capturing group, and eliminates
any alternation-precedence ambiguity (CWE-20).
@bito-code-review

bito-code-review Bot commented Jul 1, 2026

Copy link
Copy Markdown
Contributor

Code Review Agent Run #c7ceae

Actionable Suggestions - 0
Review Details
  • Files reviewed - 1 · Commit Range: 77b3792..08c6834
    • superset/utils/date_parser.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

@imddevaraj

Copy link
Copy Markdown
Author

/resolve

Comment on lines +56 to +57
if (!m || m[1] === undefined) return null;
return { n: parseInt(m[1], 10), unit: m[2].toLowerCase() };

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.

Suggestion: The custom parser rejects valid shorthand ranges like Last hour/Last minute because it requires the numeric capture group to be present, and those values then get treated as invalid and reset to Last week. Treat missing numbers for non-preset units as 1 (or tighten the regex so such forms are never considered valid) to avoid silently overwriting valid user ranges. [incorrect condition logic]

Severity Level: Major ⚠️
- ❌ "Last hour" defaults revert to "Last week" silently.
- ⚠️ Custom granular Last ranges misparsed and overwritten in CommonFrame.
Steps of Reproduction ✅
1. In backend config at `superset/config.py:211`, set `DEFAULT_TIME_FILTER = "Last hour"`
so new charts and filters default to the shorthand granular range instead of the shipped
`NO_TIME_RANGE`.

2. Load an Explore view or dashboard with a native time filter; the frontend hydrates
`time_range` from `DEFAULT_TIME_FILTER` via `hydrateExplore.ts:93`, and `DateFilterLabel`
initializes `value` to `"Last hour"` at `DateFilterLabel.tsx:14`.

3. `DateFilterLabel` calls `guessFrame(value)` at `DateFilterLabel.tsx:18`, which uses
`COMMON_RANGE_REGEX.test(timeRange)` in `dateFilterUtils.ts:32-33`; `"Last hour"` matches
the regex, so `guessFrame` returns `'Common'` and the Common frame is rendered at
`DateFilterLabel.tsx:35-37` with `props.value === "Last hour"`.

4. Inside `CommonFrame` (`CommonFrame.tsx:65`), `isPreset` is computed from
`PRESET_VALUES` (built from `COMMON_RANGE_OPTIONS` at `constants.ts:46-55`), which does
not include `"Last hour"` (only `"Last 1 hour"`), so `isPreset` is false;
`parseLastN(props.value)` at `CommonFrame.tsx:52-57` matches `COMMON_RANGE_REGEX` but has
`m[1] === undefined` for `"Last hour"`, causing `parseLastN` to return `null`. As a result
`isCustom = !isPreset && parsedCustom !== null` evaluates to false, and the `useEffect` at
`CommonFrame.tsx:78-84` treats the value as invalid and calls `props.onChange('Last
week')`, silently overwriting the user’s intended `"Last hour"` range with `"Last week"`
whenever the Common frame is mounted.

Fix in Cursor Fix in VSCode Claude

(Use Cmd/Ctrl + Click for best experience)

Prompt for AI Agent 🤖
This is a comment left during a code review.

**Path:** superset-frontend/src/explore/components/controls/DateFilterControl/components/CommonFrame.tsx
**Line:** 56:57
**Comment:**
	*Incorrect Condition Logic: The custom parser rejects valid shorthand ranges like `Last hour`/`Last minute` because it requires the numeric capture group to be present, and those values then get treated as invalid and reset to `Last week`. Treat missing numbers for non-preset units as `1` (or tighten the regex so such forms are never considered valid) to avoid silently overwriting valid user ranges.

Validate the correctness of the flagged issue. If correct, How can I resolve this? If you propose a fix, implement it and please make it concise.
Once fix is implemented, also check other comments on the same PR, and ask user if the user wants to fix the rest of the comments as well. if said yes, then fetch all the comments validate the correctness and implement a minimal fix
👍 | 👎

Comment on lines +63 to +64
export const COMMON_RANGE_REGEX =
/^[Ll]ast\s+(\d+\s+)?(second|minute|hour|day|week|month|quarter|year)s?$/

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.

Suggestion: This regex now accepts lowercase last ..., but the backend shorthand handling is case-sensitive on startswith("Last"), so values like last 15 minutes can be classified as Common in the UI but fail to resolve correctly server-side. Align casing expectations (either require Last here or make backend prefix checks case-insensitive) to prevent frontend/backend contract mismatch. [api mismatch]

Severity Level: Major ⚠️
- ❌ Lowercase Common ranges ignored by backend time_range shorthand.
- ⚠️ Frontend shows valid label while backend uses midnight.
Steps of Reproduction ✅
1. Configure a lowercase shorthand Common range by setting `DEFAULT_TIME_FILTER = "last 15
minutes"` in `superset/config.py:211`, which is allowed by the config comment (“values may
be "Last day", "Last week", <ISO date> : now, etc.”) and will be propagated to the
frontend as the default time range.

2. Open any chart or dashboard that uses the time range control; `DateFilterLabel` reads
`defaultTimeFilter` from Redux via `useDefaultTimeFilter()` (`dateFilterUtils.ts:51-56`)
and initializes its local `value` to `"last 15 minutes"` at `DateFilterLabel.tsx:14`.

3. `DateFilterLabel` computes `guessedFrame = guessFrame(value)` at
`DateFilterLabel.tsx:18`; `guessFrame` in `dateFilterUtils.ts:32-35` calls
`COMMON_RANGE_REGEX.test(timeRange)`, and because the regex explicitly allows both `Last`
and `last` (`constants.ts:63-64`), `"last 15 minutes"` is classified as `'Common'`. The
overlay renders `CommonFrame` at `DateFilterLabel.tsx:35-37` with `timeRangeValue ===
"last 15 minutes"`, and clicking Apply calls `onSave()` at `DateFilterLabel.tsx:100-104`,
forwarding the unchanged lowercase string to `onChange(timeRangeValue)` and the backend.

4. On the server side, chart queries and time range evaluation call
`get_since_until(time_range=value, ...)` in `superset/utils/date_parser.py:388-396`. The
granular-unit shorthand logic at `date_parser.py:49-58` checks `if time_range and
time_range.startswith("Last") and separator not in time_range:`; for `"last 15 minutes"`
this prefix check fails because it is case-sensitive, so `_granular_last_pattern` is never
applied and `time_range` is not rewritten to `"last 15 minutes : now"`. Because the string
lacks the `" : "` separator, the later branch at `date_parser.py:8-79` is skipped and the
function falls back to the else clause at `date_parser.py:80-89`, which ignores
`time_range` entirely and returns `_since = None` and `_until =
parse_human_datetime(_relative_end)` (defaulting to `"today"`). The backend thus executes
queries using a generic “until today midnight” window instead of the intended “last 15
minutes” range, creating a frontend/backend contract mismatch for lowercase Common ranges.

Fix in Cursor Fix in VSCode Claude

(Use Cmd/Ctrl + Click for best experience)

Prompt for AI Agent 🤖
This is a comment left during a code review.

**Path:** superset-frontend/src/explore/components/controls/DateFilterControl/utils/constants.ts
**Line:** 63:64
**Comment:**
	*Api Mismatch: This regex now accepts lowercase `last ...`, but the backend shorthand handling is case-sensitive on `startswith("Last")`, so values like `last 15 minutes` can be classified as Common in the UI but fail to resolve correctly server-side. Align casing expectations (either require `Last` here or make backend prefix checks case-insensitive) to prevent frontend/backend contract mismatch.

Validate the correctness of the flagged issue. If correct, How can I resolve this? If you propose a fix, implement it and please make it concise.
Once fix is implemented, also check other comments on the same PR, and ask user if the user wants to fix the rest of the comments as well. if said yes, then fetch all the comments validate the correctness and implement a minimal fix
👍 | 👎

@imddevaraj imddevaraj left a comment

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Requesting for review

@imddevaraj imddevaraj left a comment

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Reviewed

@imddevaraj imddevaraj changed the title feat(date-filter): add sub-hour time range presets (Last 5/15/30 min, Last 1 hour) feat(date-filter): add sub-hour time range presets (needs review) Jul 2, 2026
@github-actions

github-actions Bot commented Jul 2, 2026

Copy link
Copy Markdown
Contributor

⚠️ Translation Regression Detected

A source change in this PR renamed or reworded strings, invalidating existing translations (they are now #, fuzzy) in ar, it, ko, pt. Please resolve the affected .po files before merging.

Note: intentionally deleting a translatable string is not a regression and is not flagged here — only translations invalidated by a renamed/reworded source string are.

Language Fuzzy before Fuzzy after New
ar 1130 1133 +3
it 1660 1662 +2
ko 1514 1516 +2
pt 1835 1837 +2

How to fix

1. Install dependencies (if not already set up):

pip install -r superset/translations/requirements.txt
sudo apt-get install gettext   # or: brew install gettext

2. Re-extract strings and sync .po files:

./scripts/translations/babel_update.sh

This rewrites superset/translations/messages.pot from the current source files and merges the changes into every .po file. Strings whose msgid changed will be marked #, fuzzy.

3. Resolve the fuzzy entries in the affected language files (ar, it, ko, pt):

grep -n '#, fuzzy' superset/translations/<lang>/LC_MESSAGES/messages.po

For each fuzzy entry, either rewrite the msgstr to match the new string and remove the #, fuzzy line, or clear the msgstr to "" if you cannot provide a translation.

4. Commit your changes to the .po files.

Comment on lines +57 to +64
/**
* Matches any "Last <N> <unit>(s)" time range string.
* Mirrors the backend regex in superset/utils/date_parser.py, so arbitrary
* values like "Last 4 hours" or "Last 24 hours" are recognised without
* needing to enumerate every possibility in a hardcoded list.
*/
export const COMMON_RANGE_REGEX =
/^[Ll]ast\s+(\d+\s+)?(second|minute|hour|day|week|month|quarter|year)s?$/

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.

Suggestion: The comment states this regex matches Last <N> <unit>, but the implementation makes the number optional, so it also matches forms without N (for example Last hour). Update the comment (or the regex) so documentation and behavior are aligned; the current mismatch is misleading for future maintenance. [comment mismatch]

Severity Level: Minor 🧹
⚠️ Comment slightly misleading about optional numeric component.
⚠️ Future maintainers may misinterpret regex numeric requirement.
Steps of Reproduction ✅
1. Inspect `COMMON_RANGE_REGEX` in
`superset-frontend/src/explore/components/controls/DateFilterControl/utils/constants.ts`
at lines 57–64; the comment states it "Matches any 'Last <N> <unit>(s)' time range string"
while the regex implementation uses an optional numeric group `(\d+\s+)?`.

2. Observe that `COMMON_RANGE_REGEX` is used by `guessFrame()` in
`superset-frontend/src/explore/components/controls/DateFilterControl/utils/dateFilterUtils.ts:32-49`,
which calls `COMMON_RANGE_REGEX.test(timeRange)`; this successfully classifies numberless
forms like "Last hour" as "Common", matching backend support shown in `get_since_until()`
(date_parser.py lines 169–181) and its tests.

3. Note that type-level documentation in `types.ts:75-82` also describes "Any 'Last <N>
<unit>(s)' time range string" even though both frontend and backend explicitly support
numberless single-unit forms (e.g., "Last hour"), meaning the comments slightly
under-document the actual behavior but do not cause runtime misclassification.

4. Because the code paths (guessFrame, CommonFrame, backend parsing) already rely on the
optional numeric group and tests cover numberless variants, this suggestion concerns
documentation clarity only; existing behavior is intentional and correct, so updating the
comment would be a minor maintenance improvement rather than a functional bug fix.

Fix in Cursor Fix in VSCode Claude

(Use Cmd/Ctrl + Click for best experience)

Prompt for AI Agent 🤖
This is a comment left during a code review.

**Path:** superset-frontend/src/explore/components/controls/DateFilterControl/utils/constants.ts
**Line:** 57:64
**Comment:**
	*Comment Mismatch: The comment states this regex matches `Last <N> <unit>`, but the implementation makes the number optional, so it also matches forms without `N` (for example `Last hour`). Update the comment (or the regex) so documentation and behavior are aligned; the current mismatch is misleading for future maintenance.

Validate the correctness of the flagged issue. If correct, How can I resolve this? If you propose a fix, implement it and please make it concise.
Once fix is implemented, also check other comments on the same PR, and ask user if the user wants to fix the rest of the comments as well. if said yes, then fetch all the comments validate the correctness and implement a minimal fix
👍 | 👎

Comment on lines +436 to +437
if re.search(_granular_last_pattern, time_range, re.IGNORECASE):
time_range = time_range + separator + "now"

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.

Suggestion: The new granular Last branch always appends now for seconds/minutes/hours, which overrides a caller-provided relative_end (for example relative_end="today" from extras/config). That breaks the existing contract where relative_end controls the end anchor; only default/unset cases should be forced to now. [api mismatch]

Severity Level: Major ⚠️
- ⚠️ Caller-provided relative_end ignored for sub-day “Last” ranges.
- ⚠️ Chart extras.relative_end no longer affects granular “Last”.
- ⚠️ /v1/time_range endpoint can’t honor end anchor overrides.
Steps of Reproduction ✅
1. Note that callers can explicitly control the end anchor via the `relative_end`
argument. For chart requests, `BaseViz.query_obj` in `superset/viz.py:394–401` calls
`get_since_until(relative_end=current_app.config["DEFAULT_RELATIVE_END_TIME"], ...)`, and
`get_since_until_from_time_range` in `superset/common/utils/time_range_utils.py:29–46`
passes `relative_end=(extras or {}).get("relative_end",
current_app.config["DEFAULT_RELATIVE_END_TIME"])` into `get_since_until()`.

2. Configure or use a chart that supplies a specific `relative_end` (for example via the
`relative_end` field in `ChartDataExtrasSchema` at `superset/charts/schemas.py:14–20`,
which documents this as “End time for relative time deltas” and allows values `"today"` or
`"now"`). This value flows into `extras["relative_end"]`, then into `get_since_until()`
through `get_since_until_from_time_range()`.

3. From the Explore UI or a dashboard native time filter, choose a granular “Last” range
such as “Last 5 minutes”. This sets `time_range="Last 5 minutes"` on the backend, which
reaches `get_since_until()` in `superset/utils/date_parser.py:9–17` with the
caller-provided `relative_end` already resolved into `_relative_end` at lines 42–44.

4. Inside `get_since_until()`, the new block at `superset/utils/date_parser.py:49–60`
matches `"Last 5 minutes"` against `_granular_last_pattern` and executes:

   `if re.search(_granular_last_pattern, time_range, re.IGNORECASE): time_range =
   time_range + separator + "now"`.

   This unconditionally appends `"now"` (lines 55–58), bypassing `_relative_end` (line
   44). As a result, any explicit `relative_end` supplied by the caller or via config is
   ignored for granular “Last” ranges, changing the previous contract where `relative_end`
   determined the end anchor.

Fix in Cursor Fix in VSCode Claude

(Use Cmd/Ctrl + Click for best experience)

Prompt for AI Agent 🤖
This is a comment left during a code review.

**Path:** superset/utils/date_parser.py
**Line:** 436:437
**Comment:**
	*Api Mismatch: The new granular `Last` branch always appends `now` for seconds/minutes/hours, which overrides a caller-provided `relative_end` (for example `relative_end="today"` from extras/config). That breaks the existing contract where `relative_end` controls the end anchor; only default/unset cases should be forced to `now`.

Validate the correctness of the flagged issue. If correct, How can I resolve this? If you propose a fix, implement it and please make it concise.
Once fix is implemented, also check other comments on the same PR, and ask user if the user wants to fix the rest of the comments as well. if said yes, then fetch all the comments validate the correctness and implement a minimal fix
👍 | 👎

Comment on lines +447 to +448
time_range = "now" + separator + time_range
else:

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.

Suggestion: The new granular Next branch always prepends now, so an explicit relative_start from callers is ignored for seconds/minutes/hours. This changes behavior for clients that intentionally set relative_start and should only happen when no explicit start anchor is provided. [api mismatch]

Severity Level: Major ⚠️
- ⚠️ Caller-provided relative_start ignored for sub-day “Next”.
- ⚠️ Chart extras.relative_start ineffective for granular future windows.
- ⚠️ /v1/time_range future ranges can’t respect start anchor.
Steps of Reproduction ✅
1. Observe that callers can control the start anchor via the `relative_start` argument.
`BaseViz.query_obj` in `superset/viz.py:394–401` passes
`relative_start=current_app.config["DEFAULT_RELATIVE_START_TIME"]`, and
`get_since_until_from_time_range` in `superset/common/utils/time_range_utils.py:29–46`
passes `relative_start=(extras or {}).get("relative_start",
current_app.config["DEFAULT_RELATIVE_START_TIME"])` into `get_since_until()`.

2. Configure or use a chart that sets `relative_start` (either via global config
`DEFAULT_RELATIVE_START_TIME` in `superset/config.py:2328–2337` or per-chart
`relative_start` in `ChartDataExtrasSchema` at `superset/charts/schemas.py:6–13`). This
value is propagated into `get_since_until()` as the `relative_start` parameter.

3. Supply a granular “Next” time range, such as `"Next 5 minutes"`, either by calling the
`/v1/time_range/` endpoint (`superset/views/api.py:105–132`) with `timeRange="Next 5
minutes"` or by setting the chart’s `time_range` to that string. This reaches
`get_since_until()` in `superset/utils/date_parser.py:9–17`, where `_relative_start` is
derived from `relative_start` at line 43.

4. In `get_since_until()`, the new “Next” block at `superset/utils/date_parser.py:62–70`
builds `_granular_next_pattern` and, for `"Next 5 minutes"`, executes:

   `if re.search(_granular_next_pattern, time_range, re.IGNORECASE): time_range = "now" +
   separator + time_range`.

   This prepends `"now"` as the start expression (lines 65–68), instead of using
   `_relative_start` (line 70). Thus, for granular “Next” ranges, any caller-specified
   `relative_start` is ignored and the start anchor is forced to `"now"`, diverging from
   the documented contract that `relative_start` controls the base for relative time
   deltas.

Fix in Cursor Fix in VSCode Claude

(Use Cmd/Ctrl + Click for best experience)

Prompt for AI Agent 🤖
This is a comment left during a code review.

**Path:** superset/utils/date_parser.py
**Line:** 447:448
**Comment:**
	*Api Mismatch: The new granular `Next` branch always prepends `now`, so an explicit `relative_start` from callers is ignored for seconds/minutes/hours. This changes behavior for clients that intentionally set `relative_start` and should only happen when no explicit start anchor is provided.

Validate the correctness of the flagged issue. If correct, How can I resolve this? If you propose a fix, implement it and please make it concise.
Once fix is implemented, also check other comments on the same PR, and ask user if the user wants to fix the rest of the comments as well. if said yes, then fetch all the comments validate the correctness and implement a minimal fix
👍 | 👎

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

change:backend Requires changing the backend change:frontend Requires changing the frontend dashboard:native-filters Related to the native filters of the Dashboard 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