Update Date/Time formatting tests for pre/post JDK 20
This commit updates our Date/Time formatting/printing tests to demonstrate that the use of fallback patterns can help mitigate locale-based parsing/formatting issues beginning with JDK 20. The documentation within the tests is intentionally rather thorough for two reasons: 1. We need to understand exactly what it is we are testing and why the tests are written that way. 2. We may re-use parts of the documentation and examples in forthcoming documentation that we will provide to users. See gh-33151
This commit is contained in:
parent
d72c8b32b7
commit
bbbb7c396e
|
@ -339,6 +339,70 @@ class DateFormattingTests {
|
|||
assertThat(bindingResult.getFieldValue(propertyName)).isEqualTo("2021-03-02");
|
||||
}
|
||||
|
||||
/**
|
||||
* {@link SimpleDateBean#styleDateTimeWithFallbackPatternsForPreAndPostJdk20}
|
||||
* configures "SS" as the date/time style to use. Thus, we have to be aware
|
||||
* of the following if we do not configure fallback patterns for parsing.
|
||||
*
|
||||
* <ul>
|
||||
* <li>JDK ≤ 19 requires a standard space before the "PM".
|
||||
* <li>JDK ≥ 20 requires a narrow non-breaking space (NNBSP) before the "PM".
|
||||
* </ul>
|
||||
*
|
||||
* <p>To avoid compatibility issues between JDK versions, we have configured
|
||||
* two fallback patterns which emulate the "SS" style: <code>"MM/dd/yy h:mm a"</code>
|
||||
* matches against a standard space before the "PM", and <code>"MM/dd/yy h:mm\u202Fa"</code>
|
||||
* matches against a narrow non-breaking space (NNBSP) before the "PM".
|
||||
*
|
||||
* <p>Thus, the following should theoretically be supported on any JDK (or at least
|
||||
* JDK 17 - 23, where we have tested it).
|
||||
*
|
||||
* @see #patternDateTime(String)
|
||||
*/
|
||||
@ParameterizedTest(name = "input date: {0}") // gh-33151
|
||||
@ValueSource(strings = {"10/31/09, 12:00 PM", "10/31/09, 12:00\u202FPM"})
|
||||
void styleDateTime_PreAndPostJdk20(String propertyValue) {
|
||||
String propertyName = "styleDateTimeWithFallbackPatternsForPreAndPostJdk20";
|
||||
MutablePropertyValues propertyValues = new MutablePropertyValues();
|
||||
propertyValues.add(propertyName, propertyValue);
|
||||
binder.bind(propertyValues);
|
||||
BindingResult bindingResult = binder.getBindingResult();
|
||||
assertThat(bindingResult.getErrorCount()).isEqualTo(0);
|
||||
String value = binder.getBindingResult().getFieldValue(propertyName).toString();
|
||||
// Since the "SS" style is always used for printing and the underlying format
|
||||
// changes depending on the JDK version, we cannot be certain that a normal
|
||||
// space is used before the "PM". Consequently we have to use a regular
|
||||
// expression to match against any Unicode space character (\p{Zs}).
|
||||
assertThat(value).startsWith("10/31/09").matches(".+?12:00\\p{Zs}PM");
|
||||
}
|
||||
|
||||
/**
|
||||
* To avoid the use of Locale-based styles (such as "MM") for
|
||||
* {@link SimpleDateBean#patternDateTimeWithFallbackPatternForPreAndPostJdk20}, we have configured a
|
||||
* primary pattern (<code>"MM/dd/yy h:mm a"</code>) that matches against a standard space
|
||||
* before the "PM" and a fallback pattern (<code>"MM/dd/yy h:mm\u202Fa"</code> that matches
|
||||
* against a narrow non-breaking space (NNBSP) before the "PM".
|
||||
*
|
||||
* <p>Thus, the following should theoretically be supported on any JDK (or at least
|
||||
* JDK 17 - 23, where we have tested it).
|
||||
*
|
||||
* @see #styleDateTime(String)
|
||||
*/
|
||||
@ParameterizedTest(name = "input date: {0}") // gh-33151
|
||||
@ValueSource(strings = {"10/31/09 3:45 PM", "10/31/09 3:45\u202FPM"})
|
||||
void patternDateTime_PreAndPostJdk20(String propertyValue) {
|
||||
String propertyName = "patternDateTimeWithFallbackPatternForPreAndPostJdk20";
|
||||
MutablePropertyValues propertyValues = new MutablePropertyValues();
|
||||
propertyValues.add(propertyName, propertyValue);
|
||||
binder.bind(propertyValues);
|
||||
BindingResult bindingResult = binder.getBindingResult();
|
||||
assertThat(bindingResult.getErrorCount()).isEqualTo(0);
|
||||
String value = binder.getBindingResult().getFieldValue(propertyName).toString();
|
||||
// Since the "MM/dd/yy h:mm a" primary pattern is always used for printing, we
|
||||
// can be certain that a normal space is used before the "PM".
|
||||
assertThat(value).matches("10/31/09 3:45 PM");
|
||||
}
|
||||
|
||||
@Test
|
||||
void patternDateWithUnsupportedPattern() {
|
||||
String propertyValue = "210302";
|
||||
|
@ -389,12 +453,23 @@ class DateFormattingTests {
|
|||
@DateTimeFormat(style = "S-", fallbackPatterns = { "yyyy-MM-dd", "yyyyMMdd", "yyyy.MM.dd" })
|
||||
private Date styleDateWithFallbackPatterns;
|
||||
|
||||
// "SS" style matches either a standard space or a narrow non-breaking space (NNBSP) before AM/PM,
|
||||
// depending on the version of the JDK.
|
||||
// Fallback patterns match a standard space OR a narrow non-breaking space (NNBSP) before AM/PM.
|
||||
@DateTimeFormat(style = "SS", fallbackPatterns = { "M/d/yy, h:mm a", "M/d/yy, h:mm\u202Fa" })
|
||||
private Date styleDateTimeWithFallbackPatternsForPreAndPostJdk20;
|
||||
|
||||
@DateTimeFormat(pattern = "M/d/yy h:mm")
|
||||
private Date patternDate;
|
||||
|
||||
@DateTimeFormat(pattern = "yyyy-MM-dd", fallbackPatterns = { "M/d/yy", "yyyyMMdd", "yyyy.MM.dd" })
|
||||
private Date patternDateWithFallbackPatterns;
|
||||
|
||||
// Primary pattern matches a standard space before AM/PM.
|
||||
// Fallback pattern matches a narrow non-breaking space (NNBSP) before AM/PM.
|
||||
@DateTimeFormat(pattern = "MM/dd/yy h:mm a", fallbackPatterns = "MM/dd/yy h:mm\u202Fa")
|
||||
private Date patternDateTimeWithFallbackPatternForPreAndPostJdk20;
|
||||
|
||||
@DateTimeFormat(iso = ISO.DATE)
|
||||
private Date isoDate;
|
||||
|
||||
|
@ -459,6 +534,14 @@ class DateFormattingTests {
|
|||
this.styleDateWithFallbackPatterns = styleDateWithFallbackPatterns;
|
||||
}
|
||||
|
||||
public Date getStyleDateTimeWithFallbackPatternsForPreAndPostJdk20() {
|
||||
return this.styleDateTimeWithFallbackPatternsForPreAndPostJdk20;
|
||||
}
|
||||
|
||||
public void setStyleDateTimeWithFallbackPatternsForPreAndPostJdk20(Date styleDateTimeWithFallbackPatternsForPreAndPostJdk20) {
|
||||
this.styleDateTimeWithFallbackPatternsForPreAndPostJdk20 = styleDateTimeWithFallbackPatternsForPreAndPostJdk20;
|
||||
}
|
||||
|
||||
public Date getPatternDate() {
|
||||
return this.patternDate;
|
||||
}
|
||||
|
@ -475,6 +558,14 @@ class DateFormattingTests {
|
|||
this.patternDateWithFallbackPatterns = patternDateWithFallbackPatterns;
|
||||
}
|
||||
|
||||
public Date getPatternDateTimeWithFallbackPatternForPreAndPostJdk20() {
|
||||
return this.patternDateTimeWithFallbackPatternForPreAndPostJdk20;
|
||||
}
|
||||
|
||||
public void setPatternDateTimeWithFallbackPatternForPreAndPostJdk20(Date patternDateTimeWithFallbackPatternForPreAndPostJdk20) {
|
||||
this.patternDateTimeWithFallbackPatternForPreAndPostJdk20 = patternDateTimeWithFallbackPatternForPreAndPostJdk20;
|
||||
}
|
||||
|
||||
public Date getIsoDate() {
|
||||
return this.isoDate;
|
||||
}
|
||||
|
|
|
@ -605,6 +605,41 @@ class DateTimeFormattingTests {
|
|||
assertThat(bindingResult.getFieldValue(propertyName)).asString().matches("12:00:00\\p{Zs}PM");
|
||||
}
|
||||
|
||||
/**
|
||||
* {@link DateTimeBean#styleLocalTimeWithFallbackPatternsForPreAndPostJdk20}
|
||||
* configures "-M" as the time style to use. Thus, we have to be aware
|
||||
* of the following if we do not configure fallback patterns for parsing.
|
||||
*
|
||||
* <ul>
|
||||
* <li>JDK ≤ 19 requires a standard space before the "PM".
|
||||
* <li>JDK ≥ 20 requires a narrow non-breaking space (NNBSP) before the "PM".
|
||||
* </ul>
|
||||
*
|
||||
* <p>To avoid compatibility issues between JDK versions, we have configured
|
||||
* two fallback patterns which emulate the "-M" style: <code>"HH:mm:ss a"</code>
|
||||
* matches against a standard space before the "PM", and <code>"HH:mm:ss\u202Fa"</code>
|
||||
* matches against a narrow non-breaking space (NNBSP) before the "PM".
|
||||
*
|
||||
* <p>Thus, the following should theoretically be supported on any JDK (or at least
|
||||
* JDK 17 - 23, where we have tested it).
|
||||
*/
|
||||
@ParameterizedTest(name = "input date: {0}") // gh-33151
|
||||
@ValueSource(strings = { "12:00:00 PM", "12:00:00\u202FPM" })
|
||||
void styleLocalTime_PreAndPostJdk20(String propertyValue) {
|
||||
String propertyName = "styleLocalTimeWithFallbackPatternsForPreAndPostJdk20";
|
||||
MutablePropertyValues propertyValues = new MutablePropertyValues();
|
||||
propertyValues.add(propertyName, propertyValue);
|
||||
binder.bind(propertyValues);
|
||||
BindingResult bindingResult = binder.getBindingResult();
|
||||
assertThat(bindingResult.getErrorCount()).isEqualTo(0);
|
||||
String value = binder.getBindingResult().getFieldValue(propertyName).toString();
|
||||
// Since the "-M" style is always used for printing and the underlying format
|
||||
// changes depending on the JDK version, we cannot be certain that a normal
|
||||
// space is used before the "PM". Consequently we have to use a regular
|
||||
// expression to match against any Unicode space character (\p{Zs}).
|
||||
assertThat(value).matches("12:00:00\\p{Zs}PM");
|
||||
}
|
||||
|
||||
@ParameterizedTest(name = "input date: {0}")
|
||||
@ValueSource(strings = {"2021-03-02T12:00:00", "2021-03-02 12:00:00", "3/2/21 12:00"})
|
||||
void isoLocalDateTime(String propertyValue) {
|
||||
|
@ -682,6 +717,12 @@ class DateTimeFormattingTests {
|
|||
@DateTimeFormat(style = "-M", fallbackPatterns = {"HH:mm:ss", "HH:mm"})
|
||||
private LocalTime styleLocalTimeWithFallbackPatterns;
|
||||
|
||||
// "-M" style matches either a standard space or a narrow non-breaking space (NNBSP) before AM/PM,
|
||||
// depending on the version of the JDK.
|
||||
// Fallback patterns match a standard space OR a narrow non-breaking space (NNBSP) before AM/PM.
|
||||
@DateTimeFormat(style = "-M", fallbackPatterns = {"HH:mm:ss a", "HH:mm:ss\u202Fa"})
|
||||
private LocalTime styleLocalTimeWithFallbackPatternsForPreAndPostJdk20;
|
||||
|
||||
private LocalDateTime localDateTime;
|
||||
|
||||
@DateTimeFormat(style = "MM")
|
||||
|
@ -782,6 +823,15 @@ class DateTimeFormattingTests {
|
|||
this.styleLocalTimeWithFallbackPatterns = styleLocalTimeWithFallbackPatterns;
|
||||
}
|
||||
|
||||
public LocalTime getStyleLocalTimeWithFallbackPatternsForPreAndPostJdk20() {
|
||||
return this.styleLocalTimeWithFallbackPatternsForPreAndPostJdk20;
|
||||
}
|
||||
|
||||
public void setStyleLocalTimeWithFallbackPatternsForPreAndPostJdk20(
|
||||
LocalTime styleLocalTimeWithFallbackPatternsForPreAndPostJdk20) {
|
||||
this.styleLocalTimeWithFallbackPatternsForPreAndPostJdk20 = styleLocalTimeWithFallbackPatternsForPreAndPostJdk20;
|
||||
}
|
||||
|
||||
public LocalDateTime getLocalDateTime() {
|
||||
return this.localDateTime;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue