Skip to content

fix: standardize date/time formats across app#84

Merged
bd73-com merged 2 commits intomainfrom
claude/standardize-date-formats-YiPDV
Mar 6, 2026
Merged

fix: standardize date/time formats across app#84
bd73-com merged 2 commits intomainfrom
claude/standardize-date-formats-YiPDV

Conversation

@bd73-com
Copy link
Owner

@bd73-com bd73-com commented Mar 6, 2026

Summary

  • Create shared client/src/lib/date-format.ts utility with formatDate ("Mar 6, 2026"), formatTime ("1557"), and formatDateTime ("Mar 6, 2026 1557") functions using date-fns
  • Update all 12 client-side files and 3 server-side files to use the standard formats instead of the previous mix of toLocaleString(), toLocaleDateString(), long month names, and 12h time
  • Relative times ("2 hours ago") in MonitorCard are preserved as-is
  • Internal timezone logic in notification.ts left unchanged

Test plan

  • npm run check passes (pre-existing TS errors in scraper.ts only)
  • npm run test — all 1037 tests pass
  • npm run build — production build succeeds

https://claude.ai/code/session_01DCoGwAQxjxC5LvJTjtrbSL

Summary by CodeRabbit

  • New
    • Added a shared date/time formatting utility used app-wide.
  • Refactor
    • Standardized date and timestamp display across UI pages, delivery logs, emails, and backend reports for consistent, human-friendly formatting.

Create shared date formatting utility (client/src/lib/date-format.ts)
with formatDate ("Mar 6, 2026"), formatTime ("1557"), and
formatDateTime ("Mar 6, 2026 1557") functions. Update all 15 files
across client and server to use consistent formats instead of the
previous mix of locale strings, long month names, and 12h time.

https://claude.ai/code/session_01DCoGwAQxjxC5LvJTjtrbSL
@github-actions github-actions bot added the fix label Mar 6, 2026
@coderabbitai
Copy link

coderabbitai bot commented Mar 6, 2026

Caution

Review failed

Pull request was closed or merged during review

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: 195c3155-05b8-4068-a375-043d8a78f48a

📥 Commits

Reviewing files that changed from the base of the PR and between c3a34c7 and f303cab.

📒 Files selected for processing (1)
  • server/services/resendTracker.ts

📝 Walkthrough

Walkthrough

Adds a centralized date-formatting utility and replaces scattered inline Date/toLocale* formatting with calls to the new helpers across multiple client and server files (blog pages, admin UI, components, monitor pages, and server services). No function signatures changed.

Changes

Cohort / File(s) Summary
Date formatting utility
client/src/lib/date-format.ts
New module exporting formatDate, formatTime, formatDateTime that accept `Date
Client — blog pages
client/src/pages/Blog.tsx, client/src/pages/BlogComparison.tsx, client/src/pages/BlogPriceMonitoring.tsx, client/src/pages/BlogSelectorBreakage.tsx, client/src/pages/BlogWhyMonitorsFail.tsx
Replaced inline new Date(...).toLocaleDateString() with formatDate(...) for published/post dates.
Client — admin & errors
client/src/pages/AdminCampaignDetail.tsx, client/src/pages/AdminCampaigns.tsx, client/src/pages/AdminErrors.tsx
Replaced local inline date formatting with shared helpers (formatDate / formatDateTime) while preserving null/undefined fallbacks.
Client — components & monitor
client/src/components/ApiKeysPanel.tsx, client/src/components/DeliveryLog.tsx, client/src/pages/MonitorDetails.tsx
Switched toLocaleDateString/toLocaleString/date-fns inline calls to formatDate / formatDateTime for key last-used, delivery entries, last-checked/changed, and history timestamps.
Server — services
server/services/browserlessTracker.ts, server/services/email.ts, server/services/resendTracker.ts
Replaced toLocaleDateString / toLocaleString with date-fns format (and parseISO where applicable) using "MMM d, yyyy" or "MMM d, yyyy HHmm" patterns for email digests, reset dates, and recent-history rows. Note: parseISO used when parsing ISO strings.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~12 minutes

Suggested labels

fix, refactor, low-risk

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 15.79% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately describes the main objective of the changeset: standardizing date/time formats across the application by introducing shared formatting utilities and updating 15 files to use consistent formatting patterns.

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

✨ Finishing Touches
  • 📝 Generate docstrings (stacked PR)
  • 📝 Generate docstrings (commit on current branch)
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch claude/standardize-date-formats-YiPDV

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.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 3

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@client/src/lib/date-format.ts`:
- Around line 4-6: The formatDate function currently calls new Date(date) which
yields epoch or Invalid Date for null/undefined; update formatDate to accept
Date | string | null | undefined (or keep signature and add runtime guards) and
return a safe fallback like "—" when date is null/undefined or when new
Date(date) is invalid; specifically, in function formatDate check for date ==
null, parse to a Date object, verify !isNaN(parsed.getTime()), and only then
call format(parsed, "MMM d, yyyy"), otherwise return the fallback.

In `@server/services/email.ts`:
- Around line 262-267: The date format string "MMM d, yyyy HHmm" is duplicated;
extract it into a shared constant (e.g., DATE_TIME_FORMAT) in a shared module
(for example `@shared/constants.ts`) and replace the literal in
server/services/email.ts where dateStr is created (the format(...) calls that
assign dateStr for plain-text and HTML lists) and in the client utility
(client/src/lib/date-format.ts) to import and use DATE_TIME_FORMAT instead so
future changes only require updating one constant.

In `@server/services/resendTracker.ts`:
- Line 1: The code re-parses SQL DATE strings with new Date(r.date) (see
variable r.date in server/services/resendTracker.ts) which treats "YYYY-MM-DD"
as UTC and can shift the displayed calendar date; replace that usage with
parseISO(r.date) from date-fns and update the import to include parseISO so
date-only values are treated as local calendar dates before passing into format
or other display logic (locate the code that does new Date(r.date) around the
Resend usage history/format call and swap it to parseISO(r.date)).

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: e3340e84-6bb3-421f-9623-b91cdc5d8c6c

📥 Commits

Reviewing files that changed from the base of the PR and between 254cdaf and c3a34c7.

📒 Files selected for processing (15)
  • client/src/components/ApiKeysPanel.tsx
  • client/src/components/DeliveryLog.tsx
  • client/src/lib/date-format.ts
  • client/src/pages/AdminCampaignDetail.tsx
  • client/src/pages/AdminCampaigns.tsx
  • client/src/pages/AdminErrors.tsx
  • client/src/pages/Blog.tsx
  • client/src/pages/BlogComparison.tsx
  • client/src/pages/BlogPriceMonitoring.tsx
  • client/src/pages/BlogSelectorBreakage.tsx
  • client/src/pages/BlogWhyMonitorsFail.tsx
  • client/src/pages/MonitorDetails.tsx
  • server/services/browserlessTracker.ts
  • server/services/email.ts
  • server/services/resendTracker.ts

Comment on lines +4 to +6
export function formatDate(date: Date | string): string {
return format(new Date(date), "MMM d, yyyy");
}
Copy link

Choose a reason for hiding this comment

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

🧹 Nitpick | 🔵 Trivial

Consider adding null/undefined guard to prevent silent failures.

new Date(null) returns Unix epoch (Jan 1, 1970), and new Date(undefined) returns Invalid Date. Since callers may pass nullable timestamps (e.g., lastUsedAt in ApiKeysPanel), a defensive check would prevent unexpected output if the null guard is accidentally removed at call sites.

 export function formatDate(date: Date | string): string {
+  if (date == null) {
+    throw new Error("formatDate received null or undefined");
+  }
   return format(new Date(date), "MMM d, yyyy");
 }

Alternatively, update the type signature to Date | string | null | undefined and return a fallback like "—".

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@client/src/lib/date-format.ts` around lines 4 - 6, The formatDate function
currently calls new Date(date) which yields epoch or Invalid Date for
null/undefined; update formatDate to accept Date | string | null | undefined (or
keep signature and add runtime guards) and return a safe fallback like "—" when
date is null/undefined or when new Date(date) is invalid; specifically, in
function formatDate check for date == null, parse to a Date object, verify
!isNaN(parsed.getTime()), and only then call format(parsed, "MMM d, yyyy"),
otherwise return the fallback.

Comment on lines +262 to +267
const dateStr = format(new Date(c.detectedAt), "MMM d, yyyy HHmm");
return ` ${i + 1}. [${dateStr}]\n Old: ${sanitizePlainText(c.oldValue)}\n New: ${sanitizePlainText(c.newValue)}`;
}).join("\n\n");

const changesHtmlList = changes.map((c) => {
const dateStr = new Date(c.detectedAt).toLocaleString("en-US");
const dateStr = format(new Date(c.detectedAt), "MMM d, yyyy HHmm");
Copy link

Choose a reason for hiding this comment

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

🧹 Nitpick | 🔵 Trivial

Date formatting changes are safe and preserve XSS protections.

The dateStr values flow correctly through sanitizePlainText (line 263) and escapeHtml (line 270) respectively, maintaining the existing security posture.

Minor maintainability note: The format string "MMM d, yyyy HHmm" is duplicated between this server file and the new client/src/lib/date-format.ts utility. If the format ever needs to change, both locations must be updated. Consider extracting a shared constant to a @shared/ module that both client and server can import.
,

♻️ Optional: Extract shared format constant

Create a shared constant (e.g., in @shared/constants.ts):

export const DATE_TIME_FORMAT = "MMM d, yyyy HHmm";

Then import and use in both locations:

-import { format } from "date-fns";
+import { format } from "date-fns";
+import { DATE_TIME_FORMAT } from "@shared/constants";
-const dateStr = format(new Date(c.detectedAt), "MMM d, yyyy HHmm");
+const dateStr = format(new Date(c.detectedAt), DATE_TIME_FORMAT);
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@server/services/email.ts` around lines 262 - 267, The date format string "MMM
d, yyyy HHmm" is duplicated; extract it into a shared constant (e.g.,
DATE_TIME_FORMAT) in a shared module (for example `@shared/constants.ts`) and
replace the literal in server/services/email.ts where dateStr is created (the
format(...) calls that assign dateStr for plain-text and HTML lists) and in the
client utility (client/src/lib/date-format.ts) to import and use
DATE_TIME_FORMAT instead so future changes only require updating one constant.

new Date("YYYY-MM-DD") parses as UTC midnight per ECMAScript spec,
which can render as the previous calendar day in negative-offset
timezones (US). parseISO treats date-only strings as local midnight.

https://claude.ai/code/session_01DCoGwAQxjxC5LvJTjtrbSL
@bd73-com bd73-com merged commit ea0319f into main Mar 6, 2026
2 of 3 checks passed
@bd73-com bd73-com deleted the claude/standardize-date-formats-YiPDV branch March 6, 2026 16:18
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants