Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: NpgsqlRest/NpgsqlRest
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: 3.15.2
Choose a base ref
...
head repository: NpgsqlRest/NpgsqlRest
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: 3.16.0
Choose a head ref
Checking mergeability… Don’t worry, you can still create the pull request.
  • 5 commits
  • 24 files changed
  • 2 contributors

Commits on May 20, 2026

  1. feat: v3.16.0 — datetime parsers are now host-TZ-independent

    The four JSON-to-parameter parsers for timestamp / timestamptz / time /
    timetz used the bare DateTime.TryParse(value) overload, which converts
    offset-bearing strings to host-local time and tags Kind=Local. The two
    *Tz parsers then called SpecifyKind(v, Utc) on the local-shifted value —
    SpecifyKind only relabels Kind, it does not convert — so a host-local
    wall-clock value got sent to Postgres labelled UTC. The timestamp/time
    parsers sent the local-shifted value directly to Npgsql, which transmits
    the wall-clock verbatim for `without time zone` columns. Net effect on
    any non-UTC host: stored values silently shifted by the host's UTC
    offset.
    
    All four parsers now use
    DateTimeStyles.AssumeUniversal | DateTimeStyles.AdjustToUniversal:
    naive ISO strings are assumed UTC, Z- and offset-bearing strings are
    converted to UTC. TryParseTimestamp strips Kind to Unspecified so Npgsql
    ships UTC clock-time as the naive wall-clock value.
    
    TryParseDate is unchanged — DateOnly.TryParse rejects Z/offset strings
    outright and does not silently shift.
    
    Breaking (minor bump, not patch): naive JSON timestamps (no Z, no
    offset) are now treated as UTC rather than host-local. Callers on UTC
    hosts see no change. Callers who sent Z strings expecting UTC were
    broken on non-UTC hosts and are now correct.
    
    New NpgsqlRestTests/HostTimeZoneIndependenceTests covers all four
    parsers via echo-function round-trips. Verified passing under both
    TZ=UTC and TZ=America/Los_Angeles. Existing MultiParamsTests2 /
    MultiParamsQueryStringTests2 had Should().Match(...) workarounds for
    exactly this bug — now tightened to single-value Should().Be(...).
    
    Also bumps NuGet references (FluentAssertions, WireMock.Net,
    Microsoft.AspNetCore.Mvc.Testing, Microsoft.NET.Test.Sdk,
    coverlet.collector, Microsoft.SourceLink.GitHub) across test + plugin
    projects.
    
    Co-Authored-By: Claude Opus 4.7 <[email protected]>
    vbilopav and claude committed May 20, 2026
    Configuration menu
    Copy the full SHA
    8d3f834 View commit details
    Browse the repository at this point in the history
  2. bump version strings to 3.16.0

    The previous squash committed the staged (3.15.3) version of these
    files but left the 3.16.0 working-tree edits unstaged. This commit
    catches them up.
    
    Co-Authored-By: Claude Opus 4.7 <[email protected]>
    vbilopav and claude committed May 20, 2026
    Configuration menu
    Copy the full SHA
    ccbab12 View commit details
    Browse the repository at this point in the history
  3. feat: add JsonTimestampsAreUtc opt-out for legacy host-local behavior

    Adds a compatibility escape hatch for the breaking change introduced by
    the v3.16.0 datetime-parser fix. When set to false, the four parsers
    revert to the bare DateTime.TryParse(value) overload — restoring the
    pre-3.16.0 code path verbatim (Z/offset strings get host-local-shifted,
    naive strings get Kind=Unspecified, *Tz parsers apply SpecifyKind(Utc)
    on top). Default is true (the new, correct behavior).
    
    - NpgsqlRestOptions.JsonTimestampsAreUtc (bool, default true) — new
      top-level option on the library.
    - ParameterParsers.JsonTimestampsAreUtc static field — process-wide
      toggle, set from options in NpgsqlRestBuilder. Matches the existing
      static-class pattern of ParameterParsers.
    - Client config wiring: ConfigDefaults / ConfigTemplate /
      ConfigSchemaGenerator entries plus Program.cs reads via
      GetConfigBool("JsonTimestampsAreUtc", ..., true).
    
    Six new unit tests verify the plumbing: flag defaults to true, can be
    toggled, parsers still produce valid results for all four type variants
    in legacy mode, and invalid input still returns false. Tests are placed
    in the TestFixture collection so static-state mutations are serialized
    against the integration suite. (Real behavioral coverage of legacy mode
    requires a non-UTC TZ environment; on UTC hosts both modes produce the
    same wire-level output.)
    
    Changelog v3.16.0 gains an "Opt-out" section documenting the flag and
    explaining why it is not recommended for new deployments.
    
    Co-Authored-By: Claude Opus 4.7 <[email protected]>
    vbilopav and claude committed May 20, 2026
    Configuration menu
    Copy the full SHA
    4cb5cd4 View commit details
    Browse the repository at this point in the history
  4. sync appsettings.json with JsonTimestampsAreUtc opt-out

    appsettings.json is the source of truth; ConfigTemplate.cs mirrors it.
    The previous commit added the entry to ConfigTemplate.cs but missed
    appsettings.json itself.
    
    Co-Authored-By: Claude Opus 4.7 <[email protected]>
    vbilopav and claude committed May 20, 2026
    Configuration menu
    Copy the full SHA
    0158fb9 View commit details
    Browse the repository at this point in the history
  5. feat: TryParseDate accepts Z- and offset-bearing strings

    DateOnly.TryParse rejects any ISO string carrying a Z suffix or numeric
    offset (e.g. "2026-05-20T03:00:00Z") outright, returning false. That
    left callers who send full ISO timestamps to a date parameter with a
    flat parse failure — they had to strip the time portion client-side or
    the request died before reaching Postgres.
    
    TryParseDate now keeps DateOnly.TryParse as the fast path (unchanged
    behavior for naked dates and naive date-time strings) and falls back to
    DateTime.TryParse + DateOnly.FromDateTime for Z- and offset-bearing
    inputs. The fallback honors JsonTimestampsAreUtc: when true it uses
    AssumeUniversal | AdjustToUniversal so the extracted date is the UTC
    calendar day; when false it uses bare DateTime.TryParse so the date
    matches the host's local calendar day. Strictly broader accepted-input
    set, zero change for inputs that already worked.
    
    Five new tests in HostTimeZoneIndependenceTests cover: bare date, naive
    date-time, Z-suffix early UTC, +02:00 offset crossing midnight, and a
    Z-suffix late-evening case that the legacy parser would have rejected
    entirely. Companion echo function host_tz_echo_date added to Database
    setup.
    
    Co-Authored-By: Claude Opus 4.7 <[email protected]>
    vbilopav and claude committed May 20, 2026
    Configuration menu
    Copy the full SHA
    f350c7e View commit details
    Browse the repository at this point in the history
Loading