Skip to content

Conversation

@ymc9
Copy link
Member

@ymc9 ymc9 commented Nov 28, 2025

Summary by CodeRabbit

  • Bug Fixes
    • Fixed handling of date/time strings for PostgreSQL so string timestamps without a timezone are treated as UTC, preventing local-time misinterpretation and ensuring consistent Date values across environments.

✏️ Tip: You can customize this high-level summary in your review settings.

Copilot AI review requested due to automatic review settings November 28, 2025 21:59
@coderabbitai
Copy link

coderabbitai bot commented Nov 28, 2025

Note

Other AI code review bot(s) detected

CodeRabbit has detected other AI code review bot(s) in this pull request and will avoid duplicating their findings in the review comments. This may lead to a less comprehensive review.

Walkthrough

Changed transformOutputDate in the PostgreSQL dialect: when input is a string that does not end with Z, append Z before constructing a Date to force UTC interpretation; non-string inputs follow the existing code path.

Changes

Cohort / File(s) Summary
PostgreSQL dialect date transformation
packages/orm/src/client/crud/dialects/postgresql.ts
Modify transformOutputDate to append a Z to timezone‑naive date strings (strings not ending with Z) before calling new Date(...), preserving existing behavior for non-string inputs.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

  • Verify string detection and the check for trailing Z are correct (including edge cases like empty strings).
  • Confirm non-string (e.g., Date) branch remains unchanged.
  • Ensure no unintended double-Z or malformed timestamp results; add/verify tests for ISO strings with and without timezone.

Poem

A rabbit nudges timestamps right,
Adds a little Z by lantern light,
UTC tucked in every line,
Dates march steady, neat, and fine,
Hop on—time's now polite. 🐰⏰

Pre-merge checks and finishing touches

✅ Passed checks (3 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 change: fixing timezone handling for Date values returned in nested queries in the PostgreSQL dialect, which is the core focus of the code modification.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch fix/pg-tz

📜 Recent review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 777d874 and 136ee30.

📒 Files selected for processing (1)
  • packages/orm/src/client/crud/dialects/postgresql.ts (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • packages/orm/src/client/crud/dialects/postgresql.ts
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
  • GitHub Check: claude-review
  • GitHub Check: build-test (20.x, postgresql)
  • GitHub Check: build-test (20.x, sqlite)

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.

@claude
Copy link

claude bot commented Nov 28, 2025

Claude finished @ymc9's task —— View job


PR Review Analysis

Reviewing the timezone fix for nested queries in PostgreSQL dialect.

Todo List

  • Read and analyze the changed file
  • Examine context and related code patterns
  • Check for test coverage
  • Provide comprehensive review feedback

Code Review Summary

This PR addresses a timezone issue in PostgreSQL's transformOutputDate method. The change specifically affects how string-based Date values are interpreted in nested queries.

Analysis of Changes

File: packages/orm/src/client/crud/dialects/postgresql.ts:109-110

The change modifies string date parsing to ensure UTC interpretation:

- return new Date(value);
+ // force interpret as UTC  
+ return new Date(value.endsWith('Z') ? value : `${value}Z`);

Review Findings

Strengths

  • Targeted Fix: Addresses the specific case where PostgreSQL returns date strings without timezone indicators in nested queries
  • Preserves Existing Logic: Maintains the existing Date object handling path (lines 111-116) which already handles the node-pg timezone quirk
  • Defensive Programming: Checks for existing 'Z' suffix before appending to avoid malformed ISO strings
  • Clear Documentation: Comment explains the intent of the change

⚠️ Potential Issues

  1. Inconsistent Behavior:

    • The change only affects string dates, but not Date objects
    • This creates a discrepancy where identical timestamps may be handled differently based on how node-pg returns them
    • Consider: should the fixPostgresTimezone !== false condition also apply to string dates?
  2. Limited String Format Support:

    • The fix assumes ISO 8601 format strings
    • Non-ISO strings like '2024-01-01 12:00:00' will become '2024-01-01 12:00:00Z' which may not parse correctly
    • PostgreSQL can return dates in various formats depending on configuration
  3. No Edge Case Handling:

    • No validation that the string is a valid date format before appending 'Z'
    • Malformed date strings will still fail, but with potentially confusing error messages

🔍 Code Quality Observations

  • Consistent with Codebase: Follows existing patterns in the PostgreSQL dialect
  • Minimal Change: Small, focused fix reduces risk of regression
  • Readable: Code intent is clear with appropriate commenting

🧪 Test Coverage Concerns

  • No Direct Tests: No specific tests found for transformOutputDate method
  • Limited Coverage: Existing tests don't appear to cover the nested query timezone scenario
  • Missing Edge Cases: No tests for various string date formats or the timezone fix behavior

Recommendations

  1. Consider String Format Validation: Add basic validation before appending 'Z':

    if (typeof value === 'string') {
        // Only append Z to ISO-like strings
        const iso8601Pattern = /^\d{4}-\d{2}-\d{2}(T\d{2}:\d{2}:\d{2}(\.\d{3})?)?$/;
        if (iso8601Pattern.test(value)) {
            return new Date(value.endsWith('Z') ? value : `${value}Z`);
        }
        return new Date(value); // fallback for non-ISO strings
    }
  2. Add Test Coverage: Create tests for:

    • String dates without timezone suffixes
    • String dates with timezone suffixes
    • Various PostgreSQL date string formats
    • Nested query scenarios with dates
  3. Documentation: Update the method's JSDoc to clarify the string handling behavior

Security Assessment

No Security Issues: The change doesn't introduce any security vulnerabilities.

Performance Assessment

Minimal Impact: The string manipulation has negligible performance overhead.

Overall Assessment

This is a good, targeted fix for a specific PostgreSQL timezone issue in nested queries. While there are minor concerns about edge cases and test coverage, the change is low-risk and addresses the core problem effectively.

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: 0

🧹 Nitpick comments (1)
packages/orm/src/client/crud/dialects/postgresql.ts (1)

107-111: Make UTC coercion robust to existing timezone offsets and clarify assumptions

The new logic correctly forces bare timestamp strings to be interpreted as UTC, which should fix the nested JSON case. However:

  • If transformOutputDate ever receives a string with an explicit numeric offset (e.g. 2025-01-01T12:00:00+02:00), endsWith('Z') is false and you’ll append Z, producing something like ...+02:00Z, which is invalid for new Date.
  • You’re also not trimming potential whitespace, so a value like '2025-01-01T00:00:00Z ' would not match endsWith('Z').

If you expect only bare timestamps or ...Z right now, this is fine, but it’s easy to future‑proof with a small tweak:

-    private transformOutputDate(value: unknown) {
-        if (typeof value === 'string') {
-            // force interpret as UTC
-            return new Date(value.endsWith('Z') ? value : `${value}Z`);
+    private transformOutputDate(value: unknown) {
+        if (typeof value === 'string') {
+            const trimmed = value.trim();
+            // If there is already a timezone designator (Z or ±HH:MM), use as-is;
+            // otherwise, treat the timestamp as UTC by appending 'Z'.
+            const hasTimezone =
+                /[zZ]$/.test(trimmed) || /[+-]\d{2}:\d{2}$/.test(trimmed);
+            const dateString = hasTimezone ? trimmed : `${trimmed}Z`;
+            return new Date(dateString);

You might also want to add tests that cover:

  • JSON‑returned timestamp without timezone (no suffix) → interpreted as UTC.
  • JSON‑returned values with Z and with +HH:MM / -HH:MM offsets (if those can occur) → parsed without modification.
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between a9ff7e4 and 777d874.

📒 Files selected for processing (1)
  • packages/orm/src/client/crud/dialects/postgresql.ts (1 hunks)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (4)
  • GitHub Check: Agent
  • GitHub Check: claude-review
  • GitHub Check: build-test (20.x, sqlite)
  • GitHub Check: build-test (20.x, postgresql)

Copilot finished reviewing on behalf of ymc9 November 28, 2025 22:03
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR fixes a timezone handling issue for DateTime fields returned in nested queries when using the PostgreSQL dialect. The issue occurs because PostgreSQL's jsonb_build_object function serializes timestamptz values as ISO 8601 strings in UTC format but without the 'Z' timezone indicator, causing JavaScript's Date constructor to incorrectly interpret them as local time.

Key Changes:

  • Modified transformOutputDate to append 'Z' suffix to datetime strings that don't already have one, ensuring they're interpreted as UTC
  • Added comment explaining the rationale for forcing UTC interpretation

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

You can also share your feedback on Copilot code review for a chance to win a $100 gift card. Take the survey.

@claude
Copy link

claude bot commented Nov 28, 2025

Claude finished @ymc9's task —— View job


Code Review Summary

This PR addresses a timezone issue in PostgreSQL's transformOutputDate method. The change specifically affects how string-based Date values are interpreted in nested queries.

Analysis of Changes

File: packages/orm/src/client/crud/dialects/postgresql.ts:109-112

The change modifies string date parsing to ensure UTC interpretation:

- return new Date(value);
+ // PostgreSQL's jsonb_build_object serializes timestamptz as ISO 8601 strings
+ // in UTC but without the 'Z' suffix (e.g., "2023-01-01T12:00:00.123456").
+ // We add 'Z' to explicitly mark them as UTC for correct Date object creation.
+ return new Date(value.endsWith('Z') ? value : `${value}Z`);

Review Findings

Strengths

  • Targeted Fix: Addresses the specific case where PostgreSQL returns date strings without timezone indicators in nested queries
  • Preserves Existing Logic: Maintains the existing Date object handling path (lines 113-118) which already handles the node-pg timezone quirk
  • Defensive Programming: Checks for existing 'Z' suffix before appending to avoid malformed ISO strings
  • Clear Documentation: Comment explains the intent of the change

⚠️ Potential Issues

  1. Inconsistent Behavior:

    • The change only affects string dates, but not Date objects
    • This creates a discrepancy where identical timestamps may be handled differently based on how node-pg returns them
    • Consider: should the fixPostgresTimezone !== false condition also apply to string dates?
  2. Limited String Format Support:

    • The fix assumes ISO 8601 format strings
    • Non-ISO strings like '2024-01-01 12:00:00' will become '2024-01-01 12:00:00Z' which may not parse correctly
    • PostgreSQL can return dates in various formats depending on configuration
  3. No Edge Case Handling:

    • No validation that the string is a valid date format before appending 'Z'
    • Malformed date strings will still fail, but with potentially confusing error messages

🔍 Code Quality Observations

  • Consistent with Codebase: Follows existing patterns in the PostgreSQL dialect
  • Minimal Change: Small, focused fix reduces risk of regression
  • Readable: Code intent is clear with appropriate commenting

🧪 Test Coverage Concerns

  • No Direct Tests: No specific tests found for transformOutputDate method
  • Limited Coverage: Existing tests don't appear to cover the nested query timezone scenario
  • Missing Edge Cases: No tests for various string date formats or the timezone fix behavior

Recommendations

  1. Consider String Format Validation: Add basic validation before appending 'Z':

    if (typeof value === 'string') {
        // Only append Z to ISO-like strings
        const iso8601Pattern = /^\d{4}-\d{2}-\d{2}(T\d{2}:\d{2}:\d{2}(\.\d{3})?)?$/;
        if (iso8601Pattern.test(value)) {
            return new Date(value.endsWith('Z') ? value : `${value}Z`);
        }
        return new Date(value); // fallback for non-ISO strings
    }
  2. Add Test Coverage: Create tests for:

    • String dates without timezone suffixes
    • String dates with timezone suffixes
    • Various PostgreSQL date string formats
    • Nested query scenarios with dates
  3. Documentation: Update the method's JSDoc to clarify the string handling behavior

Security Assessment

No Security Issues: The change doesn't introduce any security vulnerabilities.

Performance Assessment

Minimal Impact: The string manipulation has negligible performance overhead.

Overall Assessment

This is a good, targeted fix for a specific PostgreSQL timezone issue in nested queries. While there are minor concerns about edge cases and test coverage, the change is low-risk and addresses the core problem effectively.

@ymc9 ymc9 merged commit 97a03d4 into dev Nov 28, 2025
5 checks passed
@ymc9 ymc9 deleted the fix/pg-tz branch November 28, 2025 22:48
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.

2 participants