From 7e402ba4fe4dd91eac97786cb2598cd7097f9782 Mon Sep 17 00:00:00 2001 From: Rossen Stoyanchev Date: Mon, 24 Feb 2020 19:04:54 +0000 Subject: [PATCH] Improve docs on date and time formatting Closes gh-24370 --- src/docs/asciidoc/core/core-validation.adoc | 48 +++++++++++---------- src/docs/asciidoc/web/webflux.adoc | 42 ++++++++++++++++-- src/docs/asciidoc/web/webmvc.adoc | 45 ++++++++++++++++--- 3 files changed, 103 insertions(+), 32 deletions(-) diff --git a/src/docs/asciidoc/core/core-validation.adoc b/src/docs/asciidoc/core/core-validation.adoc index 05eda69536f..14d0905fdba 100644 --- a/src/docs/asciidoc/core/core-validation.adoc +++ b/src/docs/asciidoc/core/core-validation.adoc @@ -1693,18 +1693,18 @@ See <> in the Spring [[format-configuring-formatting-globaldatetimeformat]] == Configuring a Global Date and Time Format -By default, date and time fields that are not annotated with `@DateTimeFormat` are -converted from strings by using the `DateFormat.SHORT` style. If you prefer, you can -change this by defining your own global format. +By default, date and time fields not annotated with `@DateTimeFormat` are converted from +strings by using the `DateFormat.SHORT` style. If you prefer, you can change this by +defining your own global format. -To do so, you need to ensure that Spring does not register default formatters. Instead, -you should register all formatters manually. Use the -`org.springframework.format.datetime.joda.JodaTimeFormatterRegistrar` or -`org.springframework.format.datetime.DateFormatterRegistrar` class, depending on whether -you use the Joda-Time library. +To do that, ensure that Spring does not register default formatters. Instead, register +formatters manually with the help of: -For example, the following Java configuration registers a global `yyyyMMdd` -format (this example does not depend on the Joda-Time library): +* `org.springframework.format.datetime.standard.DateTimeFormatterRegistrar` +* `org.springframework.format.datetime.DateFormatterRegistrar`, or +`org.springframework.format.datetime.joda.JodaTimeFormatterRegistrar` for Joda-Time. + +For example, the following Java configuration registers a global `yyyyMMdd` format: [source,java,indent=0,subs="verbatim,quotes",role="primary"] .Java @@ -1721,6 +1721,11 @@ format (this example does not depend on the Joda-Time library): // Ensure @NumberFormat is still supported conversionService.addFormatterForFieldAnnotation(new NumberFormatAnnotationFormatterFactory()); + // Register JSR-310 date conversion with a specific global format + DateTimeFormatterRegistrar registrar = new DateTimeFormatterRegistrar(); + registrar.setDateFormatter(DateTimeFormatter.ofPattern("yyyyMMdd")); + registrar.registerFormatters(conversionService); + // Register date conversion with a specific global format DateFormatterRegistrar registrar = new DateFormatterRegistrar(); registrar.setFormatter(new DateFormatter("yyyyMMdd")); @@ -1740,8 +1745,15 @@ format (this example does not depend on the Joda-Time library): fun conversionService(): FormattingConversionService { // Use the DefaultFormattingConversionService but do not register defaults return DefaultFormattingConversionService(false).apply { + // Ensure @NumberFormat is still supported addFormatterForFieldAnnotation(NumberFormatAnnotationFormatterFactory()) + + // Register JSR-310 date conversion with a specific global format + val registrar = DateTimeFormatterRegistrar() + registrar.setDateFormatter(DateTimeFormatter.ofPattern("yyyyMMdd")) + registrar.registerFormatters(this) + // Register date conversion with a specific global format val registrar = DateFormatterRegistrar() registrar.setFormatter(DateFormatter("yyyyMMdd")) @@ -1786,18 +1798,10 @@ Time): ---- -NOTE: Joda-Time provides separate distinct types to represent `date`, `time`, and `date-time` -values. The `dateFormatter`, `timeFormatter`, and `dateTimeFormatter` properties of the -`JodaTimeFormatterRegistrar` should be used to configure the different formats for each -type. The `DateTimeFormatterFactoryBean` provides a convenient way to create formatters. - -NOTE: If you use Spring MVC, remember to explicitly configure the conversion service that -is used. For Java-based `@Configuration`, this means extending the -`WebMvcConfigurationSupport` class and overriding the `mvcConversionService()` method. -For XML, you should use the `conversion-service` attribute of the -`mvc:annotation-driven` element. -See <> for details. - +Note there are extra considerations when configuring date and time formats in web +applications. Please see +<> or +<>. diff --git a/src/docs/asciidoc/web/webflux.adoc b/src/docs/asciidoc/web/webflux.adoc index 7094f135754..546c49393cd 100644 --- a/src/docs/asciidoc/web/webflux.adoc +++ b/src/docs/asciidoc/web/webflux.adoc @@ -3691,11 +3691,10 @@ class WebConfig : WebFluxConfigurer { === Conversion, formatting [.small]#<># -By default, formatters for `Number` and `Date` types are installed, including support for -the `@NumberFormat` and `@DateTimeFormat` annotations. Full support for the Joda-Time -formatting library is also installed if Joda-Time is present on the classpath. +By default, formatters for various number and date types are installed, along with support +for customization via `@NumberFormat` and `@DateTimeFormat` on fields. -The following example shows how to register custom formatters and converters: +To register custom formatters and converters in Java config, use the following: [source,java,indent=0,subs="verbatim,quotes",role="primary"] .Java @@ -3724,6 +3723,41 @@ The following example shows how to register custom formatters and converters: } ---- +By default Spring WebFlux considers the request Locale when parsing and formatting date +values. This works for forms where dates are represented as Strings with "input" form +fields. For "date" and "time" form fields, however, browsers use a fixed format defined +in the HTML spec. For such cases date and time formatting can be customized as follows: + +[source,java,indent=0,subs="verbatim,quotes",role="primary"] +.Java +---- + @Configuration + @EnableWebFlux + public class WebConfig implements WebFluxConfigurer { + + @Override + public void addFormatters(FormatterRegistry registry) { + DateTimeFormatterRegistrar registrar = new DateTimeFormatterRegistrar(); + registrar.setUseIsoFormat(true); + registrar.registerFormatters(registry); + } + } +---- +[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"] +.Kotlin +---- + @Configuration + @EnableWebFlux + class WebConfig : WebFluxConfigurer { + + override fun addFormatters(registry: FormatterRegistry) { + val registrar = DateTimeFormatterRegistrar() + registrar.setUseIsoFormat(true) + registrar.registerFormatters(registry) + } + } +---- + NOTE: See <> and the `FormattingConversionServiceFactoryBean` for more information on when to use `FormatterRegistrar` implementations. diff --git a/src/docs/asciidoc/web/webmvc.adoc b/src/docs/asciidoc/web/webmvc.adoc index 99adbce18c8..d492c2524fd 100644 --- a/src/docs/asciidoc/web/webmvc.adoc +++ b/src/docs/asciidoc/web/webmvc.adoc @@ -4977,12 +4977,10 @@ sub-elements are available. === Type Conversion [.small]#<># -By default formatters, for `Number` and `Date` types are installed, including support for -the `@NumberFormat` and `@DateTimeFormat` annotations. Full support for the Joda-Time -formatting library is also installed if Joda-Time is present on the classpath. +By default, formatters for various number and date types are installed, along with support +for customization via `@NumberFormat` and `@DateTimeFormat` on fields. -In Java configuration, you can register custom formatters and converters, as the -following example shows: +To register custom formatters and converters in Java config, use the following: [source,java,indent=0,subs="verbatim,quotes",role="primary"] .Java @@ -5010,7 +5008,7 @@ following example shows: } ---- -The following example shows how to achieve the same configuration in XML: +To do the same in XML config, use the following: [source,xml,indent=0,subs="verbatim,quotes"] ---- @@ -5049,6 +5047,41 @@ The following example shows how to achieve the same configuration in XML: ---- +By default Spring MVC considers the request Locale when parsing and formatting date +values. This works for forms where dates are represented as Strings with "input" form +fields. For "date" and "time" form fields, however, browsers use a fixed format defined +in the HTML spec. For such cases date and time formatting can be customized as follows: + +[source,java,indent=0,subs="verbatim,quotes",role="primary"] +.Java +---- + @Configuration + @EnableWebMvc + public class WebConfig implements WebMvcConfigurer { + + @Override + public void addFormatters(FormatterRegistry registry) { + DateTimeFormatterRegistrar registrar = new DateTimeFormatterRegistrar(); + registrar.setUseIsoFormat(true); + registrar.registerFormatters(registry); + } + } +---- +[source,kotlin,indent=0,subs="verbatim,quotes",role="secondary"] +.Kotlin +---- + @Configuration + @EnableWebMvc + class WebConfig : WebMvcConfigurer { + + override fun addFormatters(registry: FormatterRegistry) { + val registrar = DateTimeFormatterRegistrar() + registrar.setUseIsoFormat(true) + registrar.registerFormatters(registry) + } + } +---- + NOTE: See <> and the `FormattingConversionServiceFactoryBean` for more information on when to use FormatterRegistrar implementations.