From 129aca104ea2db2c37e4f780aa9684296fc5b4be Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Sat, 11 Jul 2026 03:29:21 +0000 Subject: [PATCH 1/4] improve: format DateOnly/TimeOnly properties with ISO 8601 in formatObject formatObject is emitted as the ToString() override body for generated API response types. Previously DateOnly and TimeOnly property values were rendered via obj.ToString() which uses locale-specific formatting (e.g. 7/11/2026 on en-US). Now they use the same ISO 8601 formats as toParam: yyyy-MM-dd for DateOnly and HH:mm:ss.FFFFFFF for TimeOnly. This makes the debug representation consistent with what is sent over the wire and independent of the ambient CultureInfo. Three new tests cover the new behaviour. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- src/SwaggerProvider.Runtime/RuntimeHelpers.fs | 4 ++++ .../RuntimeHelpersTests.fs | 21 +++++++++++++++++++ 2 files changed, 25 insertions(+) diff --git a/src/SwaggerProvider.Runtime/RuntimeHelpers.fs b/src/SwaggerProvider.Runtime/RuntimeHelpers.fs index c7f07e3a..0a1a6a27 100644 --- a/src/SwaggerProvider.Runtime/RuntimeHelpers.fs +++ b/src/SwaggerProvider.Runtime/RuntimeHelpers.fs @@ -376,6 +376,10 @@ module RuntimeHelpers = if vTy = typeof then sb.Append('"').Append(v.ToString()).Append('"') |> ignore + elif vTy.FullName = dateOnlyTypeName then + sb.Append(formatDateOrTimeValue "yyyy-MM-dd" vTy v) |> ignore + elif vTy.FullName = timeOnlyTypeName then + sb.Append(formatDateOrTimeValue "HH:mm:ss.FFFFFFF" vTy v) |> ignore elif vTy.IsArray then sb.Append('[') |> ignore let mutable firstEl = true diff --git a/tests/SwaggerProvider.Tests/RuntimeHelpersTests.fs b/tests/SwaggerProvider.Tests/RuntimeHelpersTests.fs index 14ed60c0..01a8eafa 100644 --- a/tests/SwaggerProvider.Tests/RuntimeHelpersTests.fs +++ b/tests/SwaggerProvider.Tests/RuntimeHelpersTests.fs @@ -1128,6 +1128,12 @@ type FmtMulti(age: int, name: string) = type FmtArray(tags: string[]) = member _.Tags = tags +type FmtDateOnly(date: DateOnly) = + member _.Date = date + +type FmtTimeOnly(time: TimeOnly) = + member _.Time = time + module FormatObjectTests = @@ -1177,6 +1183,21 @@ module FormatObjectTests = let obj = FmtMulti(30, "Bob") formatObject obj |> shouldEqual "{Age=30; Name=\"Bob\"}" + [] + let ``formatObject formats DateOnly property as ISO 8601``() = + let obj = FmtDateOnly(DateOnly(2025, 7, 4)) + formatObject obj |> shouldEqual "{Date=2025-07-04}" + + [] + let ``formatObject formats TimeOnly property using HH:mm:ss.FFFFFFF``() = + let obj = FmtTimeOnly(TimeOnly(14, 30, 0)) + formatObject obj |> shouldEqual "{Time=14:30:00}" + + [] + let ``formatObject formats TimeOnly property with sub-second precision``() = + let obj = FmtTimeOnly(TimeOnly(9, 5, 3, 123)) + formatObject obj |> shouldEqual "{Time=09:05:03.123}" + module ToFormUrlEncodedContentTests = From d18e6f3885fbed7a61124dd129c29903d313283e Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Sat, 11 Jul 2026 03:29:24 +0000 Subject: [PATCH 2/4] ci: trigger checks From c5c3ec187474f97b3d1a88a58df43da5c61aee29 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 11 Jul 2026 08:26:12 +0000 Subject: [PATCH 3/4] Fix invariant formatting for DateOnly/TimeOnly array elements in formatObject --- src/SwaggerProvider.Runtime/RuntimeHelpers.fs | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/SwaggerProvider.Runtime/RuntimeHelpers.fs b/src/SwaggerProvider.Runtime/RuntimeHelpers.fs index 0a1a6a27..26019ebb 100644 --- a/src/SwaggerProvider.Runtime/RuntimeHelpers.fs +++ b/src/SwaggerProvider.Runtime/RuntimeHelpers.fs @@ -393,7 +393,14 @@ module RuntimeHelpers = if isNull x then sb.Append("null") |> ignore else - sb.Append(x.ToString()) |> ignore + let xTy = x.GetType() + + if xTy.FullName = dateOnlyTypeName then + sb.Append(formatDateOrTimeValue "yyyy-MM-dd" xTy x) |> ignore + elif xTy.FullName = timeOnlyTypeName then + sb.Append(formatDateOrTimeValue "HH:mm:ss.FFFFFFF" xTy x) |> ignore + else + sb.Append(x.ToString()) |> ignore sb.Append(']') |> ignore else From 87158876c28c5e9a90811928badf687c1f4ab715 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 11 Jul 2026 08:28:30 +0000 Subject: [PATCH 4/4] Hoist array element type check outside loop; add DateOnly/TimeOnly array tests --- src/SwaggerProvider.Runtime/RuntimeHelpers.fs | 7 +++++-- .../SwaggerProvider.Tests/RuntimeHelpersTests.fs | 16 ++++++++++++++++ 2 files changed, 21 insertions(+), 2 deletions(-) diff --git a/src/SwaggerProvider.Runtime/RuntimeHelpers.fs b/src/SwaggerProvider.Runtime/RuntimeHelpers.fs index 26019ebb..bf709f98 100644 --- a/src/SwaggerProvider.Runtime/RuntimeHelpers.fs +++ b/src/SwaggerProvider.Runtime/RuntimeHelpers.fs @@ -383,6 +383,9 @@ module RuntimeHelpers = elif vTy.IsArray then sb.Append('[') |> ignore let mutable firstEl = true + let elTy = vTy.GetElementType() + let isDateOnly = not(isNull elTy) && elTy.FullName = dateOnlyTypeName + let isTimeOnly = not(isNull elTy) && elTy.FullName = timeOnlyTypeName for x in (v :?> Array) |> Seq.cast do if not firstEl then @@ -395,9 +398,9 @@ module RuntimeHelpers = else let xTy = x.GetType() - if xTy.FullName = dateOnlyTypeName then + if isDateOnly then sb.Append(formatDateOrTimeValue "yyyy-MM-dd" xTy x) |> ignore - elif xTy.FullName = timeOnlyTypeName then + elif isTimeOnly then sb.Append(formatDateOrTimeValue "HH:mm:ss.FFFFFFF" xTy x) |> ignore else sb.Append(x.ToString()) |> ignore diff --git a/tests/SwaggerProvider.Tests/RuntimeHelpersTests.fs b/tests/SwaggerProvider.Tests/RuntimeHelpersTests.fs index 01a8eafa..5dfa7057 100644 --- a/tests/SwaggerProvider.Tests/RuntimeHelpersTests.fs +++ b/tests/SwaggerProvider.Tests/RuntimeHelpersTests.fs @@ -1134,6 +1134,12 @@ type FmtDateOnly(date: DateOnly) = type FmtTimeOnly(time: TimeOnly) = member _.Time = time +type FmtDateOnlyArray(dates: DateOnly[]) = + member _.Dates = dates + +type FmtTimeOnlyArray(times: TimeOnly[]) = + member _.Times = times + module FormatObjectTests = @@ -1198,6 +1204,16 @@ module FormatObjectTests = let obj = FmtTimeOnly(TimeOnly(9, 5, 3, 123)) formatObject obj |> shouldEqual "{Time=09:05:03.123}" + [] + let ``formatObject formats DateOnly array elements as ISO 8601``() = + let obj = FmtDateOnlyArray([| DateOnly(2025, 1, 1); DateOnly(2025, 12, 31) |]) + formatObject obj |> shouldEqual "{Dates=[2025-01-01; 2025-12-31]}" + + [] + let ``formatObject formats TimeOnly array elements using HH:mm:ss.FFFFFFF``() = + let obj = FmtTimeOnlyArray([| TimeOnly(8, 0, 0); TimeOnly(14, 30, 45, 500) |]) + formatObject obj |> shouldEqual "{Times=[08:00:00; 14:30:45.5]}" + module ToFormUrlEncodedContentTests =