Skip to content

Commit 8ddb228

Browse files
committed
Add support for java.util.Duration in @value
1 parent 63b129a commit 8ddb228

File tree

4 files changed

+80
-0
lines changed

4 files changed

+80
-0
lines changed

spring-beans/src/main/java/org/springframework/beans/PropertyEditorRegistrySupport.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
import java.net.URL;
2727
import java.nio.charset.Charset;
2828
import java.nio.file.Path;
29+
import java.time.Duration;
2930
import java.time.ZoneId;
3031
import java.util.ArrayList;
3132
import java.util.Collection;
@@ -57,6 +58,7 @@
5758
import org.springframework.beans.propertyeditors.CustomCollectionEditor;
5859
import org.springframework.beans.propertyeditors.CustomMapEditor;
5960
import org.springframework.beans.propertyeditors.CustomNumberEditor;
61+
import org.springframework.beans.propertyeditors.DurationEditor;
6062
import org.springframework.beans.propertyeditors.FileEditor;
6163
import org.springframework.beans.propertyeditors.InputSourceEditor;
6264
import org.springframework.beans.propertyeditors.InputStreamEditor;
@@ -216,6 +218,7 @@ private void createDefaultEditors() {
216218
this.defaultEditors.put(Class.class, new ClassEditor());
217219
this.defaultEditors.put(Class[].class, new ClassArrayEditor());
218220
this.defaultEditors.put(Currency.class, new CurrencyEditor());
221+
this.defaultEditors.put(Duration.class, new DurationEditor());
219222
this.defaultEditors.put(File.class, new FileEditor());
220223
this.defaultEditors.put(InputStream.class, new InputStreamEditor());
221224
if (!shouldIgnoreXml) {
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
/*
2+
* Copyright 2002-2013 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.beans.propertyeditors;
18+
19+
import java.beans.PropertyEditorSupport;
20+
import java.time.Duration;
21+
import java.util.Objects;
22+
23+
import org.springframework.util.StringUtils;
24+
25+
/**
26+
* Editor for {@code java.time.Duration}, translating durations into
27+
* {@code Duration} objects. Exposes the {@code Duration} ISO as a text
28+
* representation.
29+
*
30+
* @author Davide Angelocola
31+
* @since 3.0
32+
* @see Duration
33+
*/
34+
public class DurationEditor extends PropertyEditorSupport {
35+
36+
@Override
37+
public void setAsText(String text) throws IllegalArgumentException {
38+
setValue(StringUtils.parseDuration(text));
39+
}
40+
41+
@Override
42+
public String getAsText() {
43+
Duration value = (Duration) getValue();
44+
return Objects.toString(value, "");
45+
}
46+
47+
}

spring-core/src/main/java/org/springframework/util/StringUtils.java

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@
1818

1919
import java.io.ByteArrayOutputStream;
2020
import java.nio.charset.Charset;
21+
import java.time.Duration;
22+
import java.time.format.DateTimeParseException;
2123
import java.util.ArrayDeque;
2224
import java.util.ArrayList;
2325
import java.util.Arrays;
@@ -37,6 +39,7 @@
3739

3840
import org.springframework.lang.Nullable;
3941

42+
4043
/**
4144
* Miscellaneous {@link String} utility methods.
4245
*
@@ -891,6 +894,25 @@ public static TimeZone parseTimeZoneString(String timeZoneString) {
891894
return timeZone;
892895
}
893896

897+
/**
898+
* Parse the given {@code durationString} value into a {@link Duration}.
899+
* @param durationString the duration {@code String}, following ISO 8601 format starting with "PT". It is
900+
* also possible to skip PT prefix (i.e. both "PT10s" and "10s" are accepted).
901+
* @return a corresponding {@link Duration} instance or null if @{code durationString} is null.
902+
* @throws DateTimeParseException in case of an invalid duration
903+
*/
904+
@Nullable
905+
public static Duration parseDuration(@Nullable String durationString) {
906+
if (durationString == null) {
907+
return null;
908+
}
909+
else if (durationString.startsWith("PT")) {
910+
return Duration.parse(durationString);
911+
}
912+
else {
913+
return Duration.parse("PT" + durationString);
914+
}
915+
}
894916

895917
//---------------------------------------------------------------------
896918
// Convenience methods for working with String arrays

spring-core/src/test/java/org/springframework/util/StringUtilsTests.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616

1717
package org.springframework.util;
1818

19+
import java.time.Duration;
1920
import java.util.Arrays;
2021
import java.util.Collections;
2122
import java.util.Locale;
@@ -773,4 +774,11 @@ void collectionToDelimitedStringWithNullValuesShouldNotFail() {
773774
assertThat(StringUtils.collectionToCommaDelimitedString(Collections.singletonList(null))).isEqualTo("null");
774775
}
775776

777+
@Test
778+
void parseDuration() {
779+
assertThat(StringUtils.parseDuration(null)).isNull();
780+
assertThat(StringUtils.parseDuration("PT1s")).isEqualTo(Duration.ofSeconds(1));
781+
assertThat(StringUtils.parseDuration("1s")).isEqualTo(Duration.ofSeconds(1));
782+
}
783+
776784
}

0 commit comments

Comments
 (0)