Skip to content

Commit 66e8968

Browse files
committed
Merge pull request #21136 from Grubhart
* pr/21136: Polish 'Add Period converter support' Add Period converter support Closes gh-21136
2 parents a8f56b5 + 5ae623c commit 66e8968

File tree

16 files changed

+1149
-4
lines changed

16 files changed

+1149
-4
lines changed

spring-boot-project/spring-boot-docs/src/docs/asciidoc/spring-boot-features.adoc

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1450,6 +1450,26 @@ Doing so gives a transparent upgrade path while supporting a much richer format.
14501450

14511451

14521452

1453+
[[boot-features-external-config-conversion-period]]
1454+
===== Converting periods
1455+
In addition to durations, Spring Boot can also work with `java.time.Period` type.
1456+
The following formats can be used in application properties:
1457+
1458+
* An regular `int` representation (using days as the default unit unless a `@PeriodUnit` has been specified)
1459+
* The standard ISO-8601 format {java-api}/java/time/Period.html#parse-java.lang.CharSequence-[used by `java.time.Period`]
1460+
* A simpler format where the value and the unit pairs are coupled (e.g. `1y3d` means 1 year and 3 days)
1461+
1462+
The following units are supported with the simple format:
1463+
1464+
* `y` for years
1465+
* `m` for months
1466+
* `w` for weeks
1467+
* `d` for days
1468+
1469+
NOTE: The `java.time.Period` type never actually stores the number of weeks, it is simply a shortcut that means "`7 days`".
1470+
1471+
1472+
14531473
[[boot-features-external-config-conversion-datasize]]
14541474
===== Converting Data Sizes
14551475
Spring Framework has a `DataSize` value type that expresses a size in bytes.

spring-boot-project/spring-boot-tools/spring-boot-configuration-processor/src/main/java/org/springframework/boot/configurationprocessor/fieldvalues/javac/JavaCompilerFieldValuesParser.java

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2012-2019 the original author or authors.
2+
* Copyright 2012-2020 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -116,6 +116,19 @@ private static class FieldCollector implements TreeVisitor {
116116
DURATION_SUFFIX = Collections.unmodifiableMap(values);
117117
}
118118

119+
private static final String PERIOD_OF = "Period.of";
120+
121+
private static final Map<String, String> PERIOD_SUFFIX;
122+
123+
static {
124+
Map<String, String> values = new HashMap<>();
125+
values.put("Days", "d");
126+
values.put("Weeks", "w");
127+
values.put("Months", "m");
128+
values.put("Years", "y");
129+
PERIOD_SUFFIX = Collections.unmodifiableMap(values);
130+
}
131+
119132
private static final String DATA_SIZE_OF = "DataSize.of";
120133

121134
private static final Map<String, String> DATA_SIZE_SUFFIX;
@@ -194,6 +207,10 @@ private Object getFactoryValue(ExpressionTree expression, Object factoryValue) {
194207
if (dataSizeValue != null) {
195208
return dataSizeValue;
196209
}
210+
Object periodValue = getFactoryValue(expression, factoryValue, PERIOD_OF, PERIOD_SUFFIX);
211+
if (periodValue != null) {
212+
return periodValue;
213+
}
197214
return factoryValue;
198215
}
199216

spring-boot-project/spring-boot-tools/spring-boot-configuration-processor/src/test/java/org/springframework/boot/configurationprocessor/fieldvalues/AbstractFieldValuesProcessorTests.java

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2012-2019 the original author or authors.
2+
* Copyright 2012-2020 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -100,6 +100,11 @@ void getFieldValues() throws Exception {
100100
assertThat(values.get("dataSizeMegabytes")).isEqualTo("20MB");
101101
assertThat(values.get("dataSizeGigabytes")).isEqualTo("30GB");
102102
assertThat(values.get("dataSizeTerabytes")).isEqualTo("40TB");
103+
assertThat(values.get("periodNone")).isNull();
104+
assertThat(values.get("periodDays")).isEqualTo("3d");
105+
assertThat(values.get("periodWeeks")).isEqualTo("2w");
106+
assertThat(values.get("periodMonths")).isEqualTo("10m");
107+
assertThat(values.get("periodYears")).isEqualTo("15y");
103108
}
104109

105110
@SupportedAnnotationTypes({ "org.springframework.boot.configurationsample.ConfigurationProperties" })

spring-boot-project/spring-boot-tools/spring-boot-configuration-processor/src/test/java/org/springframework/boot/configurationsample/fieldvalues/FieldValues.java

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2012-2019 the original author or authors.
2+
* Copyright 2012-2020 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -19,6 +19,7 @@
1919
import java.nio.charset.Charset;
2020
import java.nio.charset.StandardCharsets;
2121
import java.time.Duration;
22+
import java.time.Period;
2223

2324
import org.springframework.boot.configurationsample.ConfigurationProperties;
2425
import org.springframework.util.MimeType;
@@ -136,4 +137,14 @@ public class FieldValues {
136137

137138
private DataSize dataSizeTerabytes = DataSize.ofTerabytes(40);
138139

140+
private Period periodNone;
141+
142+
private Period periodDays = Period.ofDays(3);
143+
144+
private Period periodWeeks = Period.ofWeeks(2);
145+
146+
private Period periodMonths = Period.ofMonths(10);
147+
148+
private Period periodYears = Period.ofYears(15);
149+
139150
}

spring-boot-project/spring-boot/src/main/java/org/springframework/boot/convert/ApplicationConversionService.java

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2012-2019 the original author or authors.
2+
* Copyright 2012-2020 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -113,6 +113,9 @@ public static void addApplicationConverters(ConverterRegistry registry) {
113113
registry.addConverter(new DurationToStringConverter());
114114
registry.addConverter(new NumberToDurationConverter());
115115
registry.addConverter(new DurationToNumberConverter());
116+
registry.addConverter(new StringToPeriodConverter());
117+
registry.addConverter(new PeriodToStringConverter());
118+
registry.addConverter(new NumberToPeriodConverter());
116119
registry.addConverter(new StringToDataSizeConverter());
117120
registry.addConverter(new NumberToDataSizeConverter());
118121
registry.addConverter(new StringToFileConverter());
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
/*
2+
* Copyright 2012-2020 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package org.springframework.boot.convert;
18+
19+
import java.time.Period;
20+
import java.util.Collections;
21+
import java.util.Set;
22+
23+
import org.springframework.core.convert.TypeDescriptor;
24+
import org.springframework.core.convert.converter.Converter;
25+
import org.springframework.core.convert.converter.GenericConverter;
26+
27+
/**
28+
* {@link Converter} to convert from a {@link Number} to a {@link Period}. Supports
29+
* {@link Period#parse(CharSequence)} as well a more readable {@code 10m} form.
30+
*
31+
* @author Eddú Meléndez
32+
* @author Edson Chávez
33+
* @see PeriodFormat
34+
* @see PeriodUnit
35+
*/
36+
final class NumberToPeriodConverter implements GenericConverter {
37+
38+
private final StringToPeriodConverter delegate = new StringToPeriodConverter();
39+
40+
@Override
41+
public Set<ConvertiblePair> getConvertibleTypes() {
42+
return Collections.singleton(new ConvertiblePair(Number.class, Period.class));
43+
}
44+
45+
@Override
46+
public Object convert(Object source, TypeDescriptor sourceType, TypeDescriptor targetType) {
47+
return this.delegate.convert((source != null) ? source.toString() : null, TypeDescriptor.valueOf(String.class),
48+
targetType);
49+
}
50+
51+
}
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
/*
2+
* Copyright 2012-2020 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package org.springframework.boot.convert;
18+
19+
import java.lang.annotation.Documented;
20+
import java.lang.annotation.ElementType;
21+
import java.lang.annotation.Retention;
22+
import java.lang.annotation.RetentionPolicy;
23+
import java.lang.annotation.Target;
24+
import java.time.Period;
25+
26+
/**
27+
* Annotation that can be used to indicate the format to use when converting a
28+
* {@link Period}.
29+
*
30+
* @author Eddú Meléndez
31+
* @author Edson Chávez
32+
* @since 2.3.0
33+
*/
34+
@Target(ElementType.FIELD)
35+
@Retention(RetentionPolicy.RUNTIME)
36+
@Documented
37+
public @interface PeriodFormat {
38+
39+
/**
40+
* The {@link Period} format style.
41+
* @return the period format style.
42+
*/
43+
PeriodStyle value();
44+
45+
}

0 commit comments

Comments
 (0)