Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Document the types to which each spring.mvc.format and spring.webflux.format property applies #41482

Closed
relufi opened this issue Jul 13, 2024 · 5 comments
Assignees
Labels
type: documentation A documentation update
Milestone

Comments

@relufi
Copy link

relufi commented Jul 13, 2024

config:

format:
  date-time: yyyy-MM-dd HH:mm:ss
  date: yyyy-MM-dd
  time: HH:mm:ss

code:

public record TestParam(Date updateTime){
}
@GetMapping("/test")
public void list(TestParam bo) {
    System.out.println("rec: " + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(bo.updateTime()));
}

request: url param updateTime: 2024-07-18 02:00:10

GET http://localhost/test?updateTime=2024-07-18%2002%3A00%3A10

Current Output:

rec: 2024-07-18 00:00:00

Expected Output:

rec: 2024-07-18 02:00:10

With the same configuration, using the LocalDateTime class to receive parameters results in successful conversion.

I took a quick look at the code, and it seems that the String to Date converter only utilizes the spring.mvc.format.date configuration and ignores the spring.mvc.format.time and spring.mvc.format.date-time configurations.

@relufi relufi changed the title url param java.util.Date Type Conversion Error After Configuring spring.mvc.format After configuring spring.mvc.format, there is a formatting error when using java.util.Date to receive URL parameters. Jul 13, 2024
@spring-projects-issues spring-projects-issues added the status: waiting-for-triage An issue we've not yet triaged label Jul 13, 2024
@relufi
Copy link
Author

relufi commented Jul 13, 2024

private void registerJavaDate(DateTimeFormatters dateTimeFormatters) {
DateFormatterRegistrar dateFormatterRegistrar = new DateFormatterRegistrar();
String datePattern = dateTimeFormatters.getDatePattern();
if (datePattern != null) {
DateFormatter dateFormatter = new DateFormatter(datePattern);
dateFormatterRegistrar.setFormatter(dateFormatter);
}
dateFormatterRegistrar.registerFormatters(this);
}

In the registerJavaDate method, the converter configuration only reads the spring.mvc.format.date setting, causing it to convert only the date portion and ignore the time portion when converting time strings.

@relufi
Copy link
Author

relufi commented Jul 13, 2024

public DateTimeFormatters dateFormat(String pattern) {
if (isIso(pattern)) {
this.dateFormatter = DateTimeFormatter.ISO_LOCAL_DATE;
this.datePattern = "yyyy-MM-dd";
}
else {
this.dateFormatter = formatter(pattern);
this.datePattern = pattern;
}
return this;
}
/**
* Configures the time format using the given {@code pattern}.
* @param pattern the pattern for formatting times
* @return {@code this} for chained method invocation
*/
public DateTimeFormatters timeFormat(String pattern) {
this.timeFormatter = isIso(pattern) ? DateTimeFormatter.ISO_LOCAL_TIME
: (isIsoOffset(pattern) ? DateTimeFormatter.ISO_OFFSET_TIME : formatter(pattern));
return this;
}
/**
* Configures the date-time format using the given {@code pattern}.
* @param pattern the pattern for formatting date-times
* @return {@code this} for chained method invocation
*/
public DateTimeFormatters dateTimeFormat(String pattern) {
this.dateTimeFormatter = isIso(pattern) ? DateTimeFormatter.ISO_LOCAL_DATE_TIME
: (isIsoOffset(pattern) ? DateTimeFormatter.ISO_OFFSET_DATE_TIME : formatter(pattern));
return this;
}

Remove this.datePattern = pattern; from dateFormat method and put it into dateTimeFormat method. In this way, the converter can obtain the pattern configured in spring.mvc.format.date-time to fully parse the time.

@dstanwar17
Copy link

It seems the registerJavaDate method only uses spring.mvc.format.date, missing the time portion. Also, moving this.datePattern = pattern from dateFormat to dateTimeFormat in DateTimeFormatters might help the converter use the spring.mvc.format.date-time configuration properly. Can I give it a try?

@wilkinsona
Copy link
Member

Thanks for the report, @relufi.

I think the crux of the problem is that java.util.Date is being treated as something that only provides a date when it actually provides a date and a time. As such, we should be using a date-time pattern to create the DateFormatter that's registered in registerJavaDate.

Unfortunately, we may have users that are relying upon the current behavior and, as far as I can tell, changing it in a backwards compatible way is not straightforward. For example, if someone has set spring.mvc.format.date to yyyy-MM-dd and spring.mvc.format.date-time to iso and we start applying the latter to the java.lang.String -> java.util.Date conversion, an input of 2024-07-15 will no longer parse.

I'll discuss this with the team, but in the meantime I would use LocalDateTime rather than java.util.Date. That's generally recommended anyway as the java.time APIs address many of the limitations of java.util.Date.

@wilkinsona wilkinsona added the for: team-meeting An issue we'd like to discuss as a team to make progress label Jul 15, 2024
@wilkinsona
Copy link
Member

We discussed this today and concluded that the best we can do is to document to which types each property applies in its description. The spring.mvc.format.date property has existed for 7 years (since Spring Boot 2.0) making the risk of regression should we change it too high.

@wilkinsona wilkinsona changed the title After configuring spring.mvc.format, there is a formatting error when using java.util.Date to receive URL parameters. Document the types to which each spring.mvc.format and spring.webflux.format property applies Jul 15, 2024
@wilkinsona wilkinsona added type: documentation A documentation update and removed status: waiting-for-triage An issue we've not yet triaged for: team-meeting An issue we'd like to discuss as a team to make progress labels Jul 15, 2024
@wilkinsona wilkinsona added this to the 3.2.x milestone Jul 15, 2024
@wilkinsona wilkinsona self-assigned this Jul 16, 2024
@wilkinsona wilkinsona modified the milestones: 3.2.x, 3.2.8 Jul 16, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
type: documentation A documentation update
Projects
None yet
Development

No branches or pull requests

4 participants