Merge pull request #21136 from Grubhart
* pr/21136: Polish 'Add Period converter support' Add Period converter support Closes gh-21136pull/21361/head
commit
66e8968b98
@ -0,0 +1,51 @@
|
||||
/*
|
||||
* Copyright 2012-2020 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.boot.convert;
|
||||
|
||||
import java.time.Period;
|
||||
import java.util.Collections;
|
||||
import java.util.Set;
|
||||
|
||||
import org.springframework.core.convert.TypeDescriptor;
|
||||
import org.springframework.core.convert.converter.Converter;
|
||||
import org.springframework.core.convert.converter.GenericConverter;
|
||||
|
||||
/**
|
||||
* {@link Converter} to convert from a {@link Number} to a {@link Period}. Supports
|
||||
* {@link Period#parse(CharSequence)} as well a more readable {@code 10m} form.
|
||||
*
|
||||
* @author Eddú Meléndez
|
||||
* @author Edson Chávez
|
||||
* @see PeriodFormat
|
||||
* @see PeriodUnit
|
||||
*/
|
||||
final class NumberToPeriodConverter implements GenericConverter {
|
||||
|
||||
private final StringToPeriodConverter delegate = new StringToPeriodConverter();
|
||||
|
||||
@Override
|
||||
public Set<ConvertiblePair> getConvertibleTypes() {
|
||||
return Collections.singleton(new ConvertiblePair(Number.class, Period.class));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object convert(Object source, TypeDescriptor sourceType, TypeDescriptor targetType) {
|
||||
return this.delegate.convert((source != null) ? source.toString() : null, TypeDescriptor.valueOf(String.class),
|
||||
targetType);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,45 @@
|
||||
/*
|
||||
* Copyright 2012-2020 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.boot.convert;
|
||||
|
||||
import java.lang.annotation.Documented;
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
import java.time.Period;
|
||||
|
||||
/**
|
||||
* Annotation that can be used to indicate the format to use when converting a
|
||||
* {@link Period}.
|
||||
*
|
||||
* @author Eddú Meléndez
|
||||
* @author Edson Chávez
|
||||
* @since 2.3.0
|
||||
*/
|
||||
@Target(ElementType.FIELD)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Documented
|
||||
public @interface PeriodFormat {
|
||||
|
||||
/**
|
||||
* The {@link Period} format style.
|
||||
* @return the period format style.
|
||||
*/
|
||||
PeriodStyle value();
|
||||
|
||||
}
|
@ -0,0 +1,276 @@
|
||||
/*
|
||||
* Copyright 2002-2020 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.boot.convert;
|
||||
|
||||
import java.time.Period;
|
||||
import java.time.temporal.ChronoUnit;
|
||||
import java.util.function.Function;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* A standard set of {@link Period} units.
|
||||
*
|
||||
* @author Eddú Meléndez
|
||||
* @author Edson Chávez
|
||||
* @since 2.3.0
|
||||
* @see Period
|
||||
*/
|
||||
public enum PeriodStyle {
|
||||
|
||||
/**
|
||||
* Simple formatting, for example '1d'.
|
||||
*/
|
||||
SIMPLE("^" + "(?:([-+]?[0-9]+)Y)?" + "(?:([-+]?[0-9]+)M)?" + "(?:([-+]?[0-9]+)W)?" + "(?:([-+]?[0-9]+)D)?" + "$",
|
||||
Pattern.CASE_INSENSITIVE) {
|
||||
|
||||
@Override
|
||||
public Period parse(String value, ChronoUnit unit) {
|
||||
try {
|
||||
if (NUMERIC.matcher(value).matches()) {
|
||||
return Unit.fromChronoUnit(unit).parse(value);
|
||||
}
|
||||
Matcher matcher = matcher(value);
|
||||
Assert.state(matcher.matches(), "Does not match simple period pattern");
|
||||
Assert.isTrue(hasAtLeastOneGroupValue(matcher), "'" + value + "' is not a valid simple period");
|
||||
int years = parseInt(matcher, 1);
|
||||
int months = parseInt(matcher, 2);
|
||||
int weeks = parseInt(matcher, 3);
|
||||
int days = parseInt(matcher, 4);
|
||||
return Period.of(years, months, Math.addExact(Math.multiplyExact(weeks, 7), days));
|
||||
}
|
||||
catch (Exception ex) {
|
||||
throw new IllegalArgumentException("'" + value + "' is not a valid simple period", ex);
|
||||
}
|
||||
}
|
||||
|
||||
boolean hasAtLeastOneGroupValue(Matcher matcher) {
|
||||
for (int i = 0; i < matcher.groupCount(); i++) {
|
||||
if (matcher.group(i + 1) != null) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private int parseInt(Matcher matcher, int group) {
|
||||
String value = matcher.group(group);
|
||||
return (value != null) ? Integer.parseInt(value) : 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean matches(String value) {
|
||||
return NUMERIC.matcher(value).matches() || matcher(value).matches();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String print(Period value, ChronoUnit unit) {
|
||||
if (value.isZero()) {
|
||||
return Unit.fromChronoUnit(unit).print(value);
|
||||
}
|
||||
StringBuilder result = new StringBuilder();
|
||||
append(result, value, Unit.YEARS);
|
||||
append(result, value, Unit.MONTHS);
|
||||
append(result, value, Unit.DAYS);
|
||||
return result.toString();
|
||||
}
|
||||
|
||||
private void append(StringBuilder result, Period value, Unit unit) {
|
||||
if (!unit.isZero(value)) {
|
||||
result.append(unit.print(value));
|
||||
}
|
||||
}
|
||||
|
||||
},
|
||||
|
||||
/**
|
||||
* ISO-8601 formatting.
|
||||
*/
|
||||
ISO8601("^[\\+\\-]?P.*$", 0) {
|
||||
|
||||
@Override
|
||||
public Period parse(String value, ChronoUnit unit) {
|
||||
try {
|
||||
return Period.parse(value);
|
||||
}
|
||||
catch (Exception ex) {
|
||||
throw new IllegalArgumentException("'" + value + "' is not a valid ISO-8601 period", ex);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String print(Period value, ChronoUnit unit) {
|
||||
return value.toString();
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
private static final Pattern NUMERIC = Pattern.compile("^[-+]?[0-9]+$");
|
||||
|
||||
private final Pattern pattern;
|
||||
|
||||
PeriodStyle(String pattern, int flags) {
|
||||
this.pattern = Pattern.compile(pattern, flags);
|
||||
}
|
||||
|
||||
protected boolean matches(String value) {
|
||||
return this.pattern.matcher(value).matches();
|
||||
}
|
||||
|
||||
protected final Matcher matcher(String value) {
|
||||
return this.pattern.matcher(value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse the given value to a Period.
|
||||
* @param value the value to parse
|
||||
* @return a period
|
||||
*/
|
||||
public Period parse(String value) {
|
||||
return parse(value, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse the given value to a period.
|
||||
* @param value the value to parse
|
||||
* @param unit the period unit to use if the value doesn't specify one ({@code null}
|
||||
* will default to d)
|
||||
* @return a period
|
||||
*/
|
||||
public abstract Period parse(String value, ChronoUnit unit);
|
||||
|
||||
/**
|
||||
* Print the specified period.
|
||||
* @param value the value to print
|
||||
* @return the printed result
|
||||
*/
|
||||
public String print(Period value) {
|
||||
return print(value, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Print the specified period using the given unit.
|
||||
* @param value the value to print
|
||||
* @param unit the value to use for printing
|
||||
* @return the printed result
|
||||
*/
|
||||
public abstract String print(Period value, ChronoUnit unit);
|
||||
|
||||
/**
|
||||
* Detect the style then parse the value to return a period.
|
||||
* @param value the value to parse
|
||||
* @return the parsed period
|
||||
* @throws IllegalStateException if the value is not a known style or cannot be parsed
|
||||
*/
|
||||
public static Period detectAndParse(String value) {
|
||||
return detectAndParse(value, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Detect the style then parse the value to return a period.
|
||||
* @param value the value to parse
|
||||
* @param unit the period unit to use if the value doesn't specify one ({@code null}
|
||||
* will default to ms)
|
||||
* @return the parsed period
|
||||
* @throws IllegalStateException if the value is not a known style or cannot be parsed
|
||||
*/
|
||||
public static Period detectAndParse(String value, ChronoUnit unit) {
|
||||
return detect(value).parse(value, unit);
|
||||
}
|
||||
|
||||
/**
|
||||
* Detect the style from the given source value.
|
||||
* @param value the source value
|
||||
* @return the period style
|
||||
* @throws IllegalStateException if the value is not a known style
|
||||
*/
|
||||
public static PeriodStyle detect(String value) {
|
||||
Assert.notNull(value, "Value must not be null");
|
||||
for (PeriodStyle candidate : values()) {
|
||||
if (candidate.matches(value)) {
|
||||
return candidate;
|
||||
}
|
||||
}
|
||||
throw new IllegalArgumentException("'" + value + "' is not a valid period");
|
||||
}
|
||||
|
||||
enum Unit {
|
||||
|
||||
/**
|
||||
* Days, represented by suffix {@code d}.
|
||||
*/
|
||||
DAYS(ChronoUnit.DAYS, "d", Period::getDays, Period::ofDays),
|
||||
|
||||
/**
|
||||
* Months, represented by suffix {@code m}.
|
||||
*/
|
||||
MONTHS(ChronoUnit.MONTHS, "m", Period::getMonths, Period::ofMonths),
|
||||
|
||||
/**
|
||||
* Years, represented by suffix {@code y}.
|
||||
*/
|
||||
YEARS(ChronoUnit.YEARS, "y", Period::getYears, Period::ofYears);
|
||||
|
||||
private final ChronoUnit chronoUnit;
|
||||
|
||||
private final String suffix;
|
||||
|
||||
private final Function<Period, Integer> intValue;
|
||||
|
||||
private final Function<Integer, Period> factory;
|
||||
|
||||
Unit(ChronoUnit chronoUnit, String suffix, Function<Period, Integer> intValue,
|
||||
Function<Integer, Period> factory) {
|
||||
this.chronoUnit = chronoUnit;
|
||||
this.suffix = suffix;
|
||||
this.intValue = intValue;
|
||||
this.factory = factory;
|
||||
}
|
||||
|
||||
private Period parse(String value) {
|
||||
return this.factory.apply(Integer.parseInt(value));
|
||||
}
|
||||
|
||||
private String print(Period value) {
|
||||
return intValue(value) + this.suffix;
|
||||
}
|
||||
|
||||
public boolean isZero(Period value) {
|
||||
return intValue(value) == 0;
|
||||
}
|
||||
|
||||
public int intValue(Period value) {
|
||||
return this.intValue.apply(value);
|
||||
}
|
||||
|
||||
public static Unit fromChronoUnit(ChronoUnit chronoUnit) {
|
||||
if (chronoUnit == null) {
|
||||
return Unit.DAYS;
|
||||
}
|
||||
for (Unit candidate : values()) {
|
||||
if (candidate.chronoUnit == chronoUnit) {
|
||||
return candidate;
|
||||
}
|
||||
}
|
||||
throw new IllegalArgumentException("Unsupported unit " + chronoUnit);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,67 @@
|
||||
/*
|
||||
* Copyright 2002-2020 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.boot.convert;
|
||||
|
||||
import java.time.Period;
|
||||
import java.time.temporal.ChronoUnit;
|
||||
import java.util.Collections;
|
||||
import java.util.Set;
|
||||
|
||||
import org.springframework.core.convert.TypeDescriptor;
|
||||
import org.springframework.core.convert.converter.Converter;
|
||||
import org.springframework.core.convert.converter.GenericConverter;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
|
||||
/**
|
||||
* {@link Converter} to convert from a {@link Period} to a {@link String}.
|
||||
*
|
||||
* @author Eddú Meléndez
|
||||
* @author Edson Chávez
|
||||
* @since 2.3.0
|
||||
* @see Period
|
||||
*/
|
||||
public class PeriodToStringConverter implements GenericConverter {
|
||||
|
||||
@Override
|
||||
public Set<ConvertiblePair> getConvertibleTypes() {
|
||||
return Collections.singleton(new ConvertiblePair(Period.class, String.class));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object convert(Object source, TypeDescriptor sourceType, TypeDescriptor targetType) {
|
||||
if (ObjectUtils.isEmpty(source)) {
|
||||
return null;
|
||||
}
|
||||
return convert((Period) source, getPeriodStyle(sourceType), getPeriodUnit(sourceType));
|
||||
}
|
||||
|
||||
private PeriodStyle getPeriodStyle(TypeDescriptor sourceType) {
|
||||
PeriodFormat annotation = sourceType.getAnnotation(PeriodFormat.class);
|
||||
return (annotation != null) ? annotation.value() : null;
|
||||
}
|
||||
|
||||
private String convert(Period source, PeriodStyle style, ChronoUnit unit) {
|
||||
style = (style != null) ? style : PeriodStyle.ISO8601;
|
||||
return style.print(source, unit);
|
||||
}
|
||||
|
||||
private ChronoUnit getPeriodUnit(TypeDescriptor sourceType) {
|
||||
PeriodUnit annotation = sourceType.getAnnotation(PeriodUnit.class);
|
||||
return (annotation != null) ? annotation.value() : null;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,46 @@
|
||||
/*
|
||||
* Copyright 2012-2020 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.boot.convert;
|
||||
|
||||
import java.lang.annotation.Documented;
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
import java.time.Period;
|
||||
import java.time.temporal.ChronoUnit;
|
||||
|
||||
/**
|
||||
* Annotation that can be used to change the default unit used when converting a
|
||||
* {@link Period}.
|
||||
*
|
||||
* @author Eddú Meléndez
|
||||
* @author Edson Chávez
|
||||
* @since 2.3.0
|
||||
*/
|
||||
@Target(ElementType.FIELD)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Documented
|
||||
public @interface PeriodUnit {
|
||||
|
||||
/**
|
||||
* The Period unit to use if one is not specified.
|
||||
* @return the Period unit
|
||||
*/
|
||||
ChronoUnit value();
|
||||
|
||||
}
|
@ -0,0 +1,68 @@
|
||||
/*
|
||||
* Copyright 2012-2020 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.boot.convert;
|
||||
|
||||
import java.time.Period;
|
||||
import java.time.temporal.ChronoUnit;
|
||||
import java.util.Collections;
|
||||
import java.util.Set;
|
||||
|
||||
import org.springframework.core.convert.TypeDescriptor;
|
||||
import org.springframework.core.convert.converter.Converter;
|
||||
import org.springframework.core.convert.converter.GenericConverter;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
|
||||
/**
|
||||
* {@link Converter} to convert from a {@link String} to a {@link Period}. Supports
|
||||
* {@link Period#parse(CharSequence)} as well a more readable form.
|
||||
*
|
||||
* @author Eddú Meléndez
|
||||
* @author Edson Chávez
|
||||
* @since 2.3.0
|
||||
* @see PeriodUnit
|
||||
*/
|
||||
public class StringToPeriodConverter implements GenericConverter {
|
||||
|
||||
@Override
|
||||
public Set<GenericConverter.ConvertiblePair> getConvertibleTypes() {
|
||||
return Collections.singleton(new GenericConverter.ConvertiblePair(String.class, Period.class));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object convert(Object source, TypeDescriptor sourceType, TypeDescriptor targetType) {
|
||||
if (ObjectUtils.isEmpty(source)) {
|
||||
return null;
|
||||
}
|
||||
return convert(source.toString(), getStyle(targetType), getPeriodUnit(targetType));
|
||||
}
|
||||
|
||||
private PeriodStyle getStyle(TypeDescriptor targetType) {
|
||||
PeriodFormat annotation = targetType.getAnnotation(PeriodFormat.class);
|
||||
return (annotation != null) ? annotation.value() : null;
|
||||
}
|
||||
|
||||
private ChronoUnit getPeriodUnit(TypeDescriptor targetType) {
|
||||
PeriodUnit annotation = targetType.getAnnotation(PeriodUnit.class);
|
||||
return (annotation != null) ? annotation.value() : null;
|
||||
}
|
||||
|
||||
private Period convert(String source, PeriodStyle style, ChronoUnit unit) {
|
||||
style = (style != null) ? style : PeriodStyle.detect(source);
|
||||
return style.parse(source, unit);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,59 @@
|
||||
/*
|
||||
* Copyright 2012-2020 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.boot.convert;
|
||||
|
||||
import java.time.Period;
|
||||
import java.time.temporal.ChronoUnit;
|
||||
import java.util.Collections;
|
||||
|
||||
import org.springframework.core.annotation.AnnotationUtils;
|
||||
import org.springframework.core.convert.TypeDescriptor;
|
||||
|
||||
import static org.mockito.BDDMockito.given;
|
||||
import static org.mockito.Mockito.mock;
|
||||
|
||||
/**
|
||||
* Create a mock {@link TypeDescriptor} with optional {@link PeriodUnit @PeriodUnit} and
|
||||
* {@link PeriodFormat @PeriodFormat} annotations.
|
||||
*
|
||||
* @author Eddú Meléndez
|
||||
* @author Edson Chávez
|
||||
*/
|
||||
public final class MockPeriodTypeDescriptor {
|
||||
|
||||
private MockPeriodTypeDescriptor() {
|
||||
}
|
||||
|
||||
@SuppressWarnings({ "rawtypes", "unchecked" })
|
||||
public static TypeDescriptor get(ChronoUnit unit, PeriodStyle style) {
|
||||
TypeDescriptor descriptor = mock(TypeDescriptor.class);
|
||||
if (unit != null) {
|
||||
PeriodUnit unitAnnotation = AnnotationUtils.synthesizeAnnotation(Collections.singletonMap("value", unit),
|
||||
PeriodUnit.class, null);
|
||||
given(descriptor.getAnnotation(PeriodUnit.class)).willReturn(unitAnnotation);
|
||||
}
|
||||
if (style != null) {
|
||||
PeriodFormat formatAnnotation = AnnotationUtils
|
||||
.synthesizeAnnotation(Collections.singletonMap("value", style), PeriodFormat.class, null);
|
||||
given(descriptor.getAnnotation(PeriodFormat.class)).willReturn(formatAnnotation);
|
||||
}
|
||||
given(descriptor.getType()).willReturn((Class) Period.class);
|
||||
given(descriptor.getObjectType()).willReturn((Class) Period.class);
|
||||
return descriptor;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,76 @@
|
||||
/*
|
||||
* Copyright 2012-2020 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.boot.convert;
|
||||
|
||||
import java.time.Period;
|
||||
import java.time.temporal.ChronoUnit;
|
||||
import java.util.Collections;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import org.junit.jupiter.params.provider.Arguments;
|
||||
|
||||
import org.springframework.core.annotation.AnnotationUtils;
|
||||
import org.springframework.core.convert.ConversionService;
|
||||
import org.springframework.core.convert.TypeDescriptor;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.mockito.BDDMockito.given;
|
||||
import static org.mockito.Mockito.mock;
|
||||
|
||||
/**
|
||||
* Tests for {@link NumberToPeriodConverter}.
|
||||
*
|
||||
* @author Eddú Meléndez
|
||||
* @author Edson Chávez
|
||||
*/
|
||||
class NumberToPeriodConverterTests {
|
||||
|
||||
@ConversionServiceTest
|
||||
void convertWhenSimpleWithoutSuffixShouldReturnPeriod(ConversionService conversionService) {
|
||||
assertThat(convert(conversionService, 10)).isEqualTo(Period.ofDays(10));
|
||||
assertThat(convert(conversionService, +10)).isEqualTo(Period.ofDays(10));
|
||||
assertThat(convert(conversionService, -10)).isEqualTo(Period.ofDays(-10));
|
||||
}
|
||||
|
||||
@ConversionServiceTest
|
||||
void convertWhenSimpleWithoutSuffixButWithAnnotationShouldReturnPeriod(ConversionService conversionService) {
|
||||
assertThat(convert(conversionService, 10, ChronoUnit.MONTHS)).isEqualTo(Period.ofMonths(10));
|
||||
assertThat(convert(conversionService, +10, ChronoUnit.MONTHS)).isEqualTo(Period.ofMonths(10));
|
||||
assertThat(convert(conversionService, -10, ChronoUnit.MONTHS)).isEqualTo(Period.ofMonths(-10));
|
||||
}
|
||||
|
||||
private Period convert(ConversionService conversionService, Integer source) {
|
||||
return conversionService.convert(source, Period.class);
|
||||
}
|
||||
|
||||
@SuppressWarnings({ "rawtypes", "unchecked" })
|
||||
private Period convert(ConversionService conversionService, Integer source, ChronoUnit defaultUnit) {
|
||||
TypeDescriptor targetType = mock(TypeDescriptor.class);
|
||||
if (defaultUnit != null) {
|
||||
PeriodUnit unitAnnotation = AnnotationUtils
|
||||
.synthesizeAnnotation(Collections.singletonMap("value", defaultUnit), PeriodUnit.class, null);
|
||||
given(targetType.getAnnotation(PeriodUnit.class)).willReturn(unitAnnotation);
|
||||
}
|
||||
given(targetType.getType()).willReturn((Class) Period.class);
|
||||
return (Period) conversionService.convert(source, TypeDescriptor.forObject(source), targetType);
|
||||
}
|
||||
|
||||
static Stream<? extends Arguments> conversionServices() {
|
||||
return ConversionServiceArguments.with(new NumberToPeriodConverter());
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,222 @@
|
||||
/*
|
||||
* Copyright 2012-2020 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.boot.convert;
|
||||
|
||||
import java.time.Period;
|
||||
import java.time.temporal.ChronoUnit;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException;
|
||||
|
||||
/**
|
||||
* Tests for {@link PeriodStyle}.
|
||||
*
|
||||
* @author Eddú Meléndez
|
||||
* @author Edson Chávez
|
||||
*/
|
||||
class PeriodStyleTests {
|
||||
|
||||
@Test
|
||||
void detectAndParseWhenValueIsNullShouldThrowException() {
|
||||
assertThatIllegalArgumentException().isThrownBy(() -> PeriodStyle.detectAndParse(null))
|
||||
.withMessageContaining("Value must not be null");
|
||||
}
|
||||
|
||||
@Test
|
||||
void detectAndParseWhenIso8601ShouldReturnPeriod() {
|
||||
assertThat(PeriodStyle.detectAndParse("P15M")).isEqualTo(Period.parse("P15M"));
|
||||
assertThat(PeriodStyle.detectAndParse("-P15M")).isEqualTo(Period.parse("P-15M"));
|
||||
assertThat(PeriodStyle.detectAndParse("+P15M")).isEqualTo(Period.parse("P15M"));
|
||||
assertThat(PeriodStyle.detectAndParse("P2D")).isEqualTo(Period.parse("P2D"));
|
||||
assertThat(PeriodStyle.detectAndParse("-P20Y")).isEqualTo(Period.parse("P-20Y"));
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
void detectAndParseWhenSimpleDaysShouldReturnPeriod() {
|
||||
assertThat(PeriodStyle.detectAndParse("10d")).isEqualTo(Period.ofDays(10));
|
||||
assertThat(PeriodStyle.detectAndParse("10D")).isEqualTo(Period.ofDays(10));
|
||||
assertThat(PeriodStyle.detectAndParse("+10d")).isEqualTo(Period.ofDays(10));
|
||||
assertThat(PeriodStyle.detectAndParse("-10D")).isEqualTo(Period.ofDays(-10));
|
||||
}
|
||||
|
||||
@Test
|
||||
void detectAndParseWhenSimpleWeeksShouldReturnPeriod() {
|
||||
assertThat(PeriodStyle.detectAndParse("10w")).isEqualTo(Period.ofWeeks(10));
|
||||
assertThat(PeriodStyle.detectAndParse("10W")).isEqualTo(Period.ofWeeks(10));
|
||||
assertThat(PeriodStyle.detectAndParse("+10w")).isEqualTo(Period.ofWeeks(10));
|
||||
assertThat(PeriodStyle.detectAndParse("-10W")).isEqualTo(Period.ofWeeks(-10));
|
||||
}
|
||||
|
||||
@Test
|
||||
void detectAndParseWhenSimpleMonthsShouldReturnPeriod() {
|
||||
assertThat(PeriodStyle.detectAndParse("10m")).isEqualTo(Period.ofMonths(10));
|
||||
assertThat(PeriodStyle.detectAndParse("10M")).isEqualTo(Period.ofMonths(10));
|
||||
assertThat(PeriodStyle.detectAndParse("+10m")).isEqualTo(Period.ofMonths(10));
|
||||
assertThat(PeriodStyle.detectAndParse("-10M")).isEqualTo(Period.ofMonths(-10));
|
||||
}
|
||||
|
||||
@Test
|
||||
void detectAndParseWhenSimpleYearsShouldReturnPeriod() {
|
||||
assertThat(PeriodStyle.detectAndParse("10y")).isEqualTo(Period.ofYears(10));
|
||||
assertThat(PeriodStyle.detectAndParse("10Y")).isEqualTo(Period.ofYears(10));
|
||||
assertThat(PeriodStyle.detectAndParse("+10y")).isEqualTo(Period.ofYears(10));
|
||||
assertThat(PeriodStyle.detectAndParse("-10Y")).isEqualTo(Period.ofYears(-10));
|
||||
}
|
||||
|
||||
@Test
|
||||
void detectAndParseWhenSimpleWithoutSuffixShouldReturnPeriod() {
|
||||
assertThat(PeriodStyle.detectAndParse("10")).isEqualTo(Period.ofDays(10));
|
||||
assertThat(PeriodStyle.detectAndParse("+10")).isEqualTo(Period.ofDays(10));
|
||||
assertThat(PeriodStyle.detectAndParse("-10")).isEqualTo(Period.ofDays(-10));
|
||||
}
|
||||
|
||||
@Test
|
||||
void detectAndParseWhenSimpleWithoutSuffixButWithChronoUnitShouldReturnPeriod() {
|
||||
assertThat(PeriodStyle.detectAndParse("10", ChronoUnit.MONTHS)).isEqualTo(Period.ofMonths(10));
|
||||
assertThat(PeriodStyle.detectAndParse("+10", ChronoUnit.MONTHS)).isEqualTo(Period.ofMonths(10));
|
||||
assertThat(PeriodStyle.detectAndParse("-10", ChronoUnit.MONTHS)).isEqualTo(Period.ofMonths(-10));
|
||||
}
|
||||
|
||||
@Test
|
||||
void detectAndParseWhenComplexShouldReturnPeriod() {
|
||||
assertThat(PeriodStyle.detectAndParse("1y2m")).isEqualTo(Period.of(1, 2, 0));
|
||||
assertThat(PeriodStyle.detectAndParse("1y2m3d")).isEqualTo(Period.of(1, 2, 3));
|
||||
assertThat(PeriodStyle.detectAndParse("2m3d")).isEqualTo(Period.of(0, 2, 3));
|
||||
assertThat(PeriodStyle.detectAndParse("1y3d")).isEqualTo(Period.of(1, 0, 3));
|
||||
assertThat(PeriodStyle.detectAndParse("-1y3d")).isEqualTo(Period.of(-1, 0, 3));
|
||||
assertThat(PeriodStyle.detectAndParse("-1y-3d")).isEqualTo(Period.of(-1, 0, -3));
|
||||
}
|
||||
|
||||
@Test
|
||||
void detectAndParseWhenBadFormatShouldThrowException() {
|
||||
assertThatIllegalArgumentException().isThrownBy(() -> PeriodStyle.detectAndParse("10foo"))
|
||||
.withMessageContaining("'10foo' is not a valid period");
|
||||
}
|
||||
|
||||
@Test
|
||||
void detectWhenSimpleShouldReturnSimple() {
|
||||
assertThat(PeriodStyle.detect("10")).isEqualTo(PeriodStyle.SIMPLE);
|
||||
assertThat(PeriodStyle.detect("+10")).isEqualTo(PeriodStyle.SIMPLE);
|
||||
assertThat(PeriodStyle.detect("-10")).isEqualTo(PeriodStyle.SIMPLE);
|
||||
assertThat(PeriodStyle.detect("10m")).isEqualTo(PeriodStyle.SIMPLE);
|
||||
assertThat(PeriodStyle.detect("10y")).isEqualTo(PeriodStyle.SIMPLE);
|
||||
assertThat(PeriodStyle.detect("10d")).isEqualTo(PeriodStyle.SIMPLE);
|
||||
assertThat(PeriodStyle.detect("10D")).isEqualTo(PeriodStyle.SIMPLE);
|
||||
}
|
||||
|
||||
@Test
|
||||
void detectWhenIso8601ShouldReturnIso8601() {
|
||||
assertThat(PeriodStyle.detect("P20")).isEqualTo(PeriodStyle.ISO8601);
|
||||
assertThat(PeriodStyle.detect("-P15M")).isEqualTo(PeriodStyle.ISO8601);
|
||||
assertThat(PeriodStyle.detect("+P15M")).isEqualTo(PeriodStyle.ISO8601);
|
||||
assertThat(PeriodStyle.detect("P10Y")).isEqualTo(PeriodStyle.ISO8601);
|
||||
assertThat(PeriodStyle.detect("P2D")).isEqualTo(PeriodStyle.ISO8601);
|
||||
assertThat(PeriodStyle.detect("-P6")).isEqualTo(PeriodStyle.ISO8601);
|
||||
assertThat(PeriodStyle.detect("-P-6M")).isEqualTo(PeriodStyle.ISO8601);
|
||||
}
|
||||
|
||||
@Test
|
||||
void detectWhenUnknownShouldThrowException() {
|
||||
assertThatIllegalArgumentException().isThrownBy(() -> PeriodStyle.detect("bad"))
|
||||
.withMessageContaining("'bad' is not a valid period");
|
||||
}
|
||||
|
||||
@Test
|
||||
void parseIso8601ShouldParse() {
|
||||
assertThat(PeriodStyle.ISO8601.parse("P20D")).isEqualTo(Period.parse("P20D"));
|
||||
assertThat(PeriodStyle.ISO8601.parse("P15M")).isEqualTo(Period.parse("P15M"));
|
||||
assertThat(PeriodStyle.ISO8601.parse("+P15M")).isEqualTo(Period.parse("P15M"));
|
||||
assertThat(PeriodStyle.ISO8601.parse("P10Y")).isEqualTo(Period.parse("P10Y"));
|
||||
assertThat(PeriodStyle.ISO8601.parse("P2D")).isEqualTo(Period.parse("P2D"));
|
||||
assertThat(PeriodStyle.ISO8601.parse("-P6D")).isEqualTo(Period.parse("-P6D"));
|
||||
assertThat(PeriodStyle.ISO8601.parse("-P-6Y+3M")).isEqualTo(Period.parse("-P-6Y+3M"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void parseIso8601WithUnitShouldIgnoreUnit() {
|
||||
assertThat(PeriodStyle.ISO8601.parse("P20D", ChronoUnit.SECONDS)).isEqualTo(Period.parse("P20D"));
|
||||
assertThat(PeriodStyle.ISO8601.parse("P15M", ChronoUnit.SECONDS)).isEqualTo(Period.parse("P15M"));
|
||||
assertThat(PeriodStyle.ISO8601.parse("+P15M", ChronoUnit.SECONDS)).isEqualTo(Period.parse("P15M"));
|
||||
assertThat(PeriodStyle.ISO8601.parse("P10Y", ChronoUnit.SECONDS)).isEqualTo(Period.parse("P10Y"));
|
||||
assertThat(PeriodStyle.ISO8601.parse("P2D", ChronoUnit.SECONDS)).isEqualTo(Period.parse("P2D"));
|
||||
assertThat(PeriodStyle.ISO8601.parse("-P6D", ChronoUnit.SECONDS)).isEqualTo(Period.parse("-P6D"));
|
||||
assertThat(PeriodStyle.ISO8601.parse("-P-6Y+3M", ChronoUnit.SECONDS)).isEqualTo(Period.parse("-P-6Y+3M"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void parseIso8601WhenSimpleShouldThrowException() {
|
||||
assertThatIllegalArgumentException().isThrownBy(() -> PeriodStyle.ISO8601.parse("10d"))
|
||||
.withMessageContaining("'10d' is not a valid ISO-8601 period");
|
||||
}
|
||||
|
||||
@Test
|
||||
void parseSimpleShouldParse() {
|
||||
assertThat(PeriodStyle.SIMPLE.parse("10m")).isEqualTo(Period.ofMonths(10));
|
||||
}
|
||||
|
||||
@Test
|
||||
void parseSimpleWithUnitShouldUseUnitAsFallback() {
|
||||
assertThat(PeriodStyle.SIMPLE.parse("10m", ChronoUnit.DAYS)).isEqualTo(Period.ofMonths(10));
|
||||
assertThat(PeriodStyle.SIMPLE.parse("10", ChronoUnit.MONTHS)).isEqualTo(Period.ofMonths(10));
|
||||
}
|
||||
|
||||
@Test
|
||||
void parseSimpleWhenUnknownUnitShouldThrowException() {
|
||||
assertThatIllegalArgumentException().isThrownBy(() -> PeriodStyle.SIMPLE.parse("10x")).satisfies(
|
||||
(ex) -> assertThat(ex.getCause().getMessage()).isEqualTo("Does not match simple period pattern"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void parseSimpleWhenIso8601ShouldThrowException() {
|
||||
assertThatIllegalArgumentException().isThrownBy(() -> PeriodStyle.SIMPLE.parse("PT10H"))
|
||||
.withMessageContaining("'PT10H' is not a valid simple period");
|
||||
}
|
||||
|
||||
@Test
|
||||
void printIso8601ShouldPrint() {
|
||||
Period period = Period.parse("-P-6M+3D");
|
||||
assertThat(PeriodStyle.ISO8601.print(period)).isEqualTo("P6M-3D");
|
||||
}
|
||||
|
||||
@Test
|
||||
void printIso8601ShouldIgnoreUnit() {
|
||||
Period period = Period.parse("-P3Y");
|
||||
assertThat(PeriodStyle.ISO8601.print(period, ChronoUnit.DAYS)).isEqualTo("P-3Y");
|
||||
}
|
||||
|
||||
@Test
|
||||
void printSimpleWhenZeroWithoutUnitShouldPrintInDays() {
|
||||
Period period = Period.ofMonths(0);
|
||||
assertThat(PeriodStyle.SIMPLE.print(period)).isEqualTo("0d");
|
||||
}
|
||||
|
||||
@Test
|
||||
void printSimpleWhenZeroWithUnitShouldPrintInUnit() {
|
||||
Period period = Period.ofYears(0);
|
||||
assertThat(PeriodStyle.SIMPLE.print(period, ChronoUnit.YEARS)).isEqualTo("0y");
|
||||
}
|
||||
|
||||
@Test
|
||||
void printSimpleWhenNonZeroShouldIgnoreUnit() {
|
||||
Period period = Period.of(1, 2, 3);
|
||||
assertThat(PeriodStyle.SIMPLE.print(period, ChronoUnit.YEARS)).isEqualTo("1y2m3d");
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,78 @@
|
||||
/*
|
||||
* Copyright 2012-2020 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.boot.convert;
|
||||
|
||||
import java.time.Period;
|
||||
import java.time.temporal.ChronoUnit;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import org.junit.jupiter.params.provider.Arguments;
|
||||
|
||||
import org.springframework.core.convert.ConversionService;
|
||||
import org.springframework.core.convert.TypeDescriptor;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
/**
|
||||
* Tests for {@link PeriodToStringConverter}.
|
||||
*
|
||||
* @author Eddú Melendez
|
||||
* @author Edson Chávez
|
||||
*/
|
||||
class PeriodToStringConverterTests {
|
||||
|
||||
@ConversionServiceTest
|
||||
void convertWithoutStyleShouldReturnIso8601(ConversionService conversionService) {
|
||||
String converted = conversionService.convert(Period.ofDays(1), String.class);
|
||||
assertThat(converted).isEqualTo(Period.ofDays(1).toString());
|
||||
}
|
||||
|
||||
@ConversionServiceTest
|
||||
void convertWithFormatWhenZeroShouldUseFormatAndDays(ConversionService conversionService) {
|
||||
String converted = (String) conversionService.convert(Period.ofMonths(0),
|
||||
MockPeriodTypeDescriptor.get(null, PeriodStyle.SIMPLE), TypeDescriptor.valueOf(String.class));
|
||||
assertThat(converted).isEqualTo("0d");
|
||||
}
|
||||
|
||||
@ConversionServiceTest
|
||||
void convertWithFormatShouldUseFormat(ConversionService conversionService) {
|
||||
String converted = (String) conversionService.convert(Period.of(1, 2, 3),
|
||||
MockPeriodTypeDescriptor.get(null, PeriodStyle.SIMPLE), TypeDescriptor.valueOf(String.class));
|
||||
assertThat(converted).isEqualTo("1y2m3d");
|
||||
}
|
||||
|
||||
@ConversionServiceTest
|
||||
void convertWithFormatAndUnitWhenZeroShouldUseFormatAndUnit(ConversionService conversionService) {
|
||||
String converted = (String) conversionService.convert(Period.ofYears(0),
|
||||
MockPeriodTypeDescriptor.get(ChronoUnit.YEARS, PeriodStyle.SIMPLE),
|
||||
TypeDescriptor.valueOf(String.class));
|
||||
assertThat(converted).isEqualTo("0y");
|
||||
}
|
||||
|
||||
@ConversionServiceTest
|
||||
void convertWithFormatAndUnitWhenNonZeroShouldUseFormatAndIgnoreUnit(ConversionService conversionService) {
|
||||
String converted = (String) conversionService.convert(Period.of(1, 0, 3),
|
||||
MockPeriodTypeDescriptor.get(ChronoUnit.YEARS, PeriodStyle.SIMPLE),
|
||||
TypeDescriptor.valueOf(String.class));
|
||||
assertThat(converted).isEqualTo("1y3d");
|
||||
}
|
||||
|
||||
static Stream<? extends Arguments> conversionServices() throws Exception {
|
||||
return ConversionServiceArguments.with(new PeriodToStringConverter());
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,101 @@
|
||||
/*
|
||||
* Copyright 2012-2020 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.boot.convert;
|
||||
|
||||
import java.time.Period;
|
||||
import java.time.temporal.ChronoUnit;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import org.junit.jupiter.params.provider.Arguments;
|
||||
|
||||
import org.springframework.core.convert.ConversionService;
|
||||
import org.springframework.core.convert.TypeDescriptor;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
/**
|
||||
* Tests for {@link StringToPeriodConverter}.
|
||||
*
|
||||
* @author Eddú Meléndez
|
||||
* @author Edson Chávez
|
||||
*/
|
||||
public class StringToPeriodConverterTest {
|
||||
|
||||
@ConversionServiceTest
|
||||
void convertWhenIso8601ShouldReturnPeriod(ConversionService conversionService) {
|
||||
assertThat(convert(conversionService, "P2Y")).isEqualTo(Period.parse("P2Y"));
|
||||
assertThat(convert(conversionService, "P3M")).isEqualTo(Period.parse("P3M"));
|
||||
assertThat(convert(conversionService, "P4W")).isEqualTo(Period.parse("P4W"));
|
||||
assertThat(convert(conversionService, "P5D")).isEqualTo(Period.parse("P5D"));
|
||||
assertThat(convert(conversionService, "P1Y2M3D")).isEqualTo(Period.parse("P1Y2M3D"));
|
||||
assertThat(convert(conversionService, "P1Y2M3W4D")).isEqualTo(Period.parse("P1Y2M3W4D"));
|
||||
assertThat(convert(conversionService, "P-1Y2M")).isEqualTo(Period.parse("P-1Y2M"));
|
||||
assertThat(convert(conversionService, "-P1Y2M")).isEqualTo(Period.parse("-P1Y2M"));
|
||||
}
|
||||
|
||||
@ConversionServiceTest
|
||||
void convertWhenSimpleDaysShouldReturnPeriod(ConversionService conversionService) {
|
||||
assertThat(convert(conversionService, "10d")).isEqualTo(Period.ofDays(10));
|
||||
assertThat(convert(conversionService, "10D")).isEqualTo(Period.ofDays(10));
|
||||
assertThat(convert(conversionService, "+10d")).isEqualTo(Period.ofDays(10));
|
||||
assertThat(convert(conversionService, "-10D")).isEqualTo(Period.ofDays(-10));
|
||||
}
|
||||
|
||||
@ConversionServiceTest
|
||||
void convertWhenSimpleMonthsShouldReturnPeriod(ConversionService conversionService) {
|
||||
assertThat(convert(conversionService, "10m")).isEqualTo(Period.ofMonths(10));
|
||||
assertThat(convert(conversionService, "10M")).isEqualTo(Period.ofMonths(10));
|
||||
assertThat(convert(conversionService, "+10m")).isEqualTo(Period.ofMonths(10));
|
||||
assertThat(convert(conversionService, "-10M")).isEqualTo(Period.ofMonths(-10));
|
||||
}
|
||||
|
||||
@ConversionServiceTest
|
||||
void convertWhenSimpleYearsShouldReturnPeriod(ConversionService conversionService) {
|
||||
assertThat(convert(conversionService, "10y")).isEqualTo(Period.ofYears(10));
|
||||
assertThat(convert(conversionService, "10Y")).isEqualTo(Period.ofYears(10));
|
||||
assertThat(convert(conversionService, "+10y")).isEqualTo(Period.ofYears(10));
|
||||
assertThat(convert(conversionService, "-10Y")).isEqualTo(Period.ofYears(-10));
|
||||
}
|
||||
|
||||
@ConversionServiceTest
|
||||
void convertWhenSimpleWithoutSuffixShouldReturnPeriod(ConversionService conversionService) {
|
||||
assertThat(convert(conversionService, "10")).isEqualTo(Period.ofDays(10));
|
||||
assertThat(convert(conversionService, "+10")).isEqualTo(Period.ofDays(10));
|
||||
assertThat(convert(conversionService, "-10")).isEqualTo(Period.ofDays(-10));
|
||||
}
|
||||
|
||||
@ConversionServiceTest
|
||||
void convertWhenSimpleWithoutSuffixButWithAnnotationShouldReturnPeriod(ConversionService conversionService) {
|
||||
assertThat(convert(conversionService, "10", ChronoUnit.MONTHS, null)).isEqualTo(Period.ofMonths(10));
|
||||
assertThat(convert(conversionService, "+10", ChronoUnit.MONTHS, null)).isEqualTo(Period.ofMonths(10));
|
||||
assertThat(convert(conversionService, "-10", ChronoUnit.MONTHS, null)).isEqualTo(Period.ofMonths(-10));
|
||||
}
|
||||
|
||||
private Period convert(ConversionService conversionService, String source) {
|
||||
return conversionService.convert(source, Period.class);
|
||||
}
|
||||
|
||||
private Period convert(ConversionService conversionService, String source, ChronoUnit unit, PeriodStyle style) {
|
||||
return (Period) conversionService.convert(source, TypeDescriptor.forObject(source),
|
||||
MockPeriodTypeDescriptor.get(unit, style));
|
||||
}
|
||||
|
||||
static Stream<? extends Arguments> conversionServices() {
|
||||
return ConversionServiceArguments.with(new StringToPeriodConverter());
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in New Issue