This behavior occured to me whilst working with an Swagger OpenAPI Endpoint ...
The OpenAPI definition looked alike:
paths:
  /endpoint:
    get:
      summary: short summary
      operationId: endpointFunction
      parameters:
        - name: timestamp
          in: query
          description: 'Given timestamp'
          required: false
          schema:
            type: string
            format: date-time
            example: "2023-01-05T13:11:40.020747+01:00"
      responses:
        200:
          description: 'Ok'
        404:
          description: 'Not Ok'
          content: {}
        500:
          description: 'Failure'
          content: { }
After compiling the definition using Maven, it looks like this:
public interface EndpointApiDelegate {
    default Optional<NativeWebRequest> getRequest() {
        return Optional.empty();
    }
    /**
     * GET /endpoint : short summary
     *
     * @param timestamp Given timestamp (optional)
     * @return Ok (status code 200)
     *         or Not ok (status code 404)
     *         or Interner Fehler (status code 500)
     * @see EndpointApi#endpointFunction
     */
    default ResponseEntity<Void> endpointFunction(OffsetDateTime timestamp) {
        return new ResponseEntity<>(HttpStatus.NOT_IMPLEMENTED);
    }
}
Now, trying to send data directly via ..
- a browser's URL
 
- a http-file (.http)
 
- postman and others
 
### Sample FAILING call in .http-file
GET http://localhost:{{port}}/endpoint?timestamp=22023-01-05T13:11:40.020747+01:00
.. using the given example (2023-01-05T13:11:40.020747+01:00), it fails.
"Failed to convert value of type [java.lang.String] to required type [java.time.LocalDateTime]; nested exception is org.springframework.core.convert.ConversionFailedException: Failed to convert from type [java.lang.String] to type [@org.springframework.web.bind.annotation.RequestParam @org.springframework.format.annotation.DateTimeFormat java.time.LocalDateTime] for value ... .. .
Reasoning
Query parameters are parsed with a different charset (not sure these are the right words, but it fits the behaviour)
Therefore the parsing fails reading the '+'-character.
Resolution
### Sample WORKING call in .http-file
GET http://localhost:{{port}}/endpoint?timestamp=2023-01-03T11%3A29%3A47.526612%2B01%3A00
Attention
In case the solution hopefully feels impractical ... .. .
. .. ... if it does: YOU ARE RIGHT !!!
Passing Date-Time (in this case) is a 'bad endpoint design'-decision
Swagger OpenApi offers checks for int (minimum and maximum) and string (regex-pattern) directly in the OpenApi definition.
Still Date-Time offers special pitfalls as min/max values may be dependent on relative 'everyday passing time'.
I imagine automated min/max values are therefore not yet implemented.
Is there a better solution? Sure!   :)
Use a POST request instead and define APPLICATION JSON in the RequestBody instead of an URL-RequestParameter.
components:
  schemas:
    TimestampEntity:
      type: object
      properties:
        timestamp:
          description: 'timestamp'
          type: string
          format: date-time
          example: "2023-01-05T13:11:40.020747+01:00"
paths:
  /endpoint:
    post:
      summary: short summary
      operationId: endpointFunction
      # parameters:
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/TimestampEntity'
      responses:
        200:
          description: 'Ok'
        404:
          description: 'Not Ok'
          content: {}
        500:
          description: 'Failure'
          content: { }
That compiles to:
    default Optional<NativeWebRequest> getRequest() {
        return Optional.empty();
    }
    /**
     * POST /endpoint : short summary
     *
     * @param timestampEntity
 (optional)
     * @return Ok (status code 200)
     *         or Not Ok (status code 404)
     *         or Failure (status code 500)
     * @see EndpointApi#endpointFunction
     */
    default ResponseEntity<Void> endpointFunction(TimestampEntity timestampEntity) {
        return new ResponseEntity<>(HttpStatus.NOT_IMPLEMENTED);
    }
Using a generated Timestamp.class:
public class TimestampEntity   {
  @JsonProperty("timestamp")
  private OffsetDateTime timestamp;
  public TimestampEntity timestamp(OffsetDateTime timestamp) {
    this.timestamp = timestamp;
    return this;
  }
... .. .
Now the value (2023-01-05T13:11:40.020747+01:00) will be parsed appropriately.
This is the end of being entangled in an URL charset-scuffle   ;-)