Skip to content

Improve default date format of BitDatePicker (#8013)#12441

Open
msynk wants to merge 3 commits into
bitfoundation:developfrom
msynk:8013-blazorui-datepicker-default-format-improvements
Open

Improve default date format of BitDatePicker (#8013)#12441
msynk wants to merge 3 commits into
bitfoundation:developfrom
msynk:8013-blazorui-datepicker-default-format-improvements

Conversation

@msynk

@msynk msynk commented Jun 11, 2026

Copy link
Copy Markdown
Member

closes #8013

Summary by CodeRabbit

  • Refactor
    • Centralized date and time formatting and parsing pattern selection in DatePicker for improved consistency.
    • Enhanced time picker with better support for configurable time format options (12-hour and 24-hour).
    • Improved default date pattern handling to include time portion when time picker is enabled.

@coderabbitai

coderabbitai Bot commented Jun 11, 2026

Copy link
Copy Markdown

Review Change Stack

Important

Review skipped

Auto incremental reviews are disabled on this repository.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 4233df84-af1b-4e52-b8cd-c40236313177

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

Walkthrough

BitDatePicker refactors date/time format handling by introducing a centralized GetDefaultDateFormat() helper method. This helper encapsulates Mode-based date pattern selection and extends it to append time formatting when ShowTimePicker is enabled, supporting both 12-hour and 24-hour formats. Both parsing and formatting methods now delegate to this helper for consistency.

Changes

Date/Time Format Pattern Centralization

Layer / File(s) Summary
Date/time format pattern helper and integration
src/BlazorUI/Bit.BlazorUI/Components/Inputs/DatePicker/BitDatePicker.razor.cs
New GetDefaultDateFormat() helper centralizes the date format pattern selection logic previously scattered across TryParseValueFromString and FormatValueAsString. The helper computes the default pattern from Mode (month vs. short date) and appends a time component when ShowTimePicker is enabled (12h or 24h based on TimeFormat). Both parsing and formatting methods now use this helper, replacing the previous inline Mode-dependent ternary logic.

🎯 2 (Simple) | ⏱️ ~10 minutes

🐰 A format helper hops in,
No more scattered patterns to flip,
Dates dance with their time,
In a rhythm so prime,
One helper to rule them all—hop! ✨

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately reflects the main change: improving the default date format of BitDatePicker to include time display when ShowTimePicker is enabled.
Linked Issues check ✅ Passed The PR successfully addresses issue #8013 by implementing logic to display selected time in the input when ShowTimePicker is true, as demonstrated by the GetDefaultDateFormat() helper that extends patterns to include time.
Out of Scope Changes check ✅ Passed All changes are scoped to the BitDatePicker date formatting logic and directly support the objective of displaying time when ShowTimePicker is enabled.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (1)
src/BlazorUI/Bit.BlazorUI/Components/Inputs/DatePicker/BitDatePicker.razor.cs (1)

775-791: 💤 Low value

Consider using culture-specific time patterns for better internationalization.

The time patterns "hh:mm tt" and "HH:mm" are hardcoded and may not align with all culture preferences. While these patterns are standard and consistent with BitCircularTimePicker, consider using the culture's ShortTimePattern or constructing patterns based on the culture's time formatting conventions for better i18n support.

Example approach:

var timePattern = TimeFormat == BitTimeFormat.TwelveHours 
    ? _culture.DateTimeFormat.ShortTimePattern 
    : "HH:mm";
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@src/BlazorUI/Bit.BlazorUI/Components/Inputs/DatePicker/BitDatePicker.razor.cs`
around lines 775 - 791, GetDefaultDateFormat currently appends hardcoded time
patterns; change it to use the culture's time pattern(s) so the output respects
localization: when ShowTimePicker is true, use
_culture.DateTimeFormat.ShortTimePattern (or derive a 12/24-hour pattern from
it) instead of the literal "hh:mm tt"/"HH:mm", keeping the
Mode/BitDatePickerMode.MonthPicker branch and existing pattern composition logic
intact; reference GetDefaultDateFormat, _culture, ShowTimePicker, TimeFormat and
BitTimeFormat.TwelveHours when making the change.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In
`@src/BlazorUI/Bit.BlazorUI/Components/Inputs/DatePicker/BitDatePicker.razor.cs`:
- Around line 775-791: GetDefaultDateFormat currently appends hardcoded time
patterns; change it to use the culture's time pattern(s) so the output respects
localization: when ShowTimePicker is true, use
_culture.DateTimeFormat.ShortTimePattern (or derive a 12/24-hour pattern from
it) instead of the literal "hh:mm tt"/"HH:mm", keeping the
Mode/BitDatePickerMode.MonthPicker branch and existing pattern composition logic
intact; reference GetDefaultDateFormat, _culture, ShowTimePicker, TimeFormat and
BitTimeFormat.TwelveHours when making the change.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: cc5ea2c9-222b-4523-8474-54eca701bbe6

📥 Commits

Reviewing files that changed from the base of the PR and between f66f0fc and 1fa64f3.

📒 Files selected for processing (1)
  • src/BlazorUI/Bit.BlazorUI/Components/Inputs/DatePicker/BitDatePicker.razor.cs

@msynk

msynk commented Jun 11, 2026

Copy link
Copy Markdown
Member Author

@coderabbitai re-review

@coderabbitai

coderabbitai Bot commented Jun 11, 2026

Copy link
Copy Markdown

Tip

For best results, initiate chat on the files or code changes.

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Get the PR diff
gh pr diff 12441 --repo bitfoundation/bitplatform

echo "---FILE CONTENT---"
fd "BitDatePicker.razor.cs" --exec cat {}

Length of output: 56289



@msynk Thanks for the re-review request! The overall approach is clean and well-structured. Here are a few observations:


✅ Positives

  • GetDefaultDateFormat() is a clean extraction that eliminates duplication and makes both formatting and parsing consistent.
  • The 12h↔24h conversion logic is well-commented and handles the common cases correctly.

⚠️ Issues

1. Parsing regression when AllowTextInput + ShowTimePicker are both true

Before this PR, TryParseValueFromString used only ShortDatePattern regardless of ShowTimePicker. Now it uses GetDefaultDateFormat() which includes the time portion when ShowTimePicker is true. Users who rely on AllowTextInput to type a bare date (e.g. 6/12/2026) will now fail to parse because the pattern expects a full 6/12/2026 2:30 PM string.

Consider falling back to the date-only pattern when the time-including parse fails:

protected override bool TryParseValueFromString(string? value, [MaybeNullWhen(false)] out DateTimeOffset? result, [NotNullWhen(false)] out string? validationErrorMessage)
{
    if (value.HasNoValue()) { result = null; validationErrorMessage = null; return true; }

    var pattern = DateFormat ?? GetDefaultDateFormat();

    if (DateTime.TryParseExact(value, pattern, _culture, DateTimeStyles.None, out DateTime parsedValue) is false
        && ShowTimePicker
        && DateFormat is null)
    {
        // Fallback: try parsing without the time portion
        var dateOnlyPattern = Mode == BitDatePickerMode.MonthPicker
            ? _culture.DateTimeFormat.YearMonthPattern
            : _culture.DateTimeFormat.ShortDatePattern;
        DateTime.TryParseExact(value, dateOnlyPattern, _culture, DateTimeStyles.None, out parsedValue);
    }
    // ...
}

2. Replace("t", "") in AM/PM removal is fragile

return shortTimePattern.Replace('h', 'H').Replace("t", "").Trim();

This removes every occurrence of the character t. While ShortTimePattern in .NET cultures only uses t/tt for the AM/PM designator, this would silently corrupt patterns from any culture that includes a literal t (e.g. a hypothetical "HH't'mm" separator). A more targeted replacement is safer:

return Regex.Replace(shortTimePattern.Replace('h', 'H'), @"\s*t+\s*", "").Trim();
// or simpler:
return shortTimePattern.Replace('h', 'H').Replace("tt", "").Replace("t", "").Trim();

3. Contains('h') for 12-hour detection can be confused by quoted literals

var isCulture12Hours = shortTimePattern.Contains('h');

A pattern like "HH'h'mm" (used in some French locale variants as "14h30") would be misidentified as 12-hour. While this is rare in ShortTimePattern, it's worth noting. A more robust check would verify that h appears outside of single-quoted literals.


Minor nit

In GetTimePattern(), when converting 24h→12h, the AM/PM separator isn't adjusted to match the culture's conventions — it always appends " tt". For RTL cultures or cultures where AM/PM comes before the time, this may produce an awkward format. This is a low-priority concern since tt in .NET will use the culture's actual AM/PM strings.


Overall this is a solid improvement that addresses the core feature request. Item #1 (parsing regression) is the most impactful and worth addressing before merge.

@msynk

msynk commented Jun 11, 2026

Copy link
Copy Markdown
Member Author

@coderabbitai re-review

1 similar comment
@msynk

msynk commented Jun 11, 2026

Copy link
Copy Markdown
Member Author

@coderabbitai re-review

@coderabbitai

coderabbitai Bot commented Jun 11, 2026

Copy link
Copy Markdown

Tip

For best results, initiate chat on the files or code changes.

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
gh pr diff 12441 --repo bitfoundation/bitplatform

echo "---FILE CONTENT---"
fd "BitDatePicker.razor.cs" --exec cat {}

Length of output: 62224



@msynk All three issues raised in the previous review have been addressed — the implementation is clean and production-ready. Here's a quick summary of what changed:


✅ All Issues Resolved

# Issue Status
1 Parsing regression with AllowTextInput + ShowTimePicker ✅ Fixed — fallback to date-only pattern added with proper guard (parsed is false && DateFormat is null && ShowTimePicker)
2 Fragile Replace("t", "") could corrupt quoted literals ✅ Fixed — new RemoveSpecifier() iterates character-by-character, skipping single/double-quoted segments entirely
3 Contains('h') false positive on quoted literals like 'h' ✅ Fixed — new HasSpecifier() applies the same quote-aware traversal

Minor edge case (non-blocking)

The HasSpecifier / RemoveSpecifier helpers treat a pair of consecutive apostrophes '' (escaped literal apostrophe in .NET format strings) as an "open → immediately close" quote block, rather than a literal ' character. However, .NET's ShortTimePattern never uses '' in practice, so this has zero real-world impact and is not worth complicating the code over.


Overall this is a solid, well-structured improvement. LGTM 🚀

[approve]

@coderabbitai

coderabbitai Bot commented Jun 11, 2026

Copy link
Copy Markdown

Tip

For best results, initiate chat on the files or code changes.

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
gh pr diff 12441 --repo bitfoundation/bitplatform

echo "---FILE CONTENT---"
fd "BitDatePicker.razor.cs" --exec cat {}

Length of output: 62224



@msynk The code is unchanged from the last reviewed revision — all three previously raised issues remain properly resolved:

  1. Parsing fallback for AllowTextInput + ShowTimePicker is in place.
  2. Quote-aware RemoveSpecifier handles the t/tt removal safely.
  3. Quote-aware HasSpecifier prevents false positives on quoted literals like 'h'.

LGTM 🚀

[approve]

@msynk

msynk commented Jun 12, 2026

Copy link
Copy Markdown
Member Author

@coderabbitai re-review

@coderabbitai

coderabbitai Bot commented Jun 12, 2026

Copy link
Copy Markdown

Tip

For best results, initiate chat on the files or code changes.

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
gh pr diff 12441 --repo bitfoundation/bitplatform

echo "---FILE CONTENT---"
fd "BitDatePicker.razor.cs" --exec cat {}

Length of output: 62224



@msynk The code is identical to the previously reviewed and approved revision — no new changes detected. All three originally raised issues remain properly resolved:

  1. Parsing fallback for AllowTextInput + ShowTimePicker is in place.
  2. Quote-aware RemoveSpecifier handles t/tt removal safely.
  3. Quote-aware HasSpecifier prevents false positives on quoted literals.

LGTM 🚀

[approve]

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

BitDatePicker input should show the selected time

1 participant