-
Notifications
You must be signed in to change notification settings - Fork 34
ZonedDateTime Property #477
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
8a1a042
fae6745
611619b
05a3cb3
2fe08d5
274e55b
b47534a
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,91 @@ | ||
| package org.yarnandtail.andhow.property; | ||
|
|
||
| import org.yarnandtail.andhow.api.*; | ||
| import org.yarnandtail.andhow.valid.ZonedDateTimeValidator; | ||
| import org.yarnandtail.andhow.valuetype.ZonedDateTimeType; | ||
|
|
||
| import java.time.ZonedDateTime; | ||
| import java.util.List; | ||
|
|
||
| /** | ||
| * A Property that refers to a ZonedDateTime value. | ||
| * | ||
| * By default this uses the TrimToNullTrimmer, which removes all whitespace from | ||
| * the value and ultimately null if the value is all whitespace. The String | ||
| * constructor version is used when creating instances of BigDecimal. | ||
|
Owner
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The note about 'BigDecimal' can just be deleted. But, it would be nice to note how the string value is interpreted in this class. There is a note about string date format further down. |
||
| * | ||
| * @author chace86 | ||
| */ | ||
| public class ZonedDateTimeProp extends PropertyBase<ZonedDateTime> { | ||
|
Owner
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It looks like you started from BigDecimal as a template for this class, but LocalDateTime might be a better place to start. The builder methods in LocalDateTime use time related terms like before and after, rather that greater than or less than. |
||
|
|
||
| public ZonedDateTimeProp(ZonedDateTime defaultValue, boolean required, String shortDesc, List<Validator<ZonedDateTime>> validators, | ||
| List<Name> aliases, PropertyType paramType, ValueType<ZonedDateTime> valueType, Trimmer trimmer, String helpText) { | ||
| super(defaultValue, required, shortDesc, validators, aliases, paramType, valueType, trimmer, helpText); | ||
| } | ||
|
|
||
| /** | ||
| * Return an instance of ZonedDateTimeBuilder | ||
| */ | ||
| public static ZonedDateTimeBuilder builder() { return new ZonedDateTimeBuilder(); } | ||
|
|
||
| /** | ||
| * Build a ZonedDateTimeProp | ||
| */ | ||
| public static class ZonedDateTimeBuilder extends PropertyBuilderBase<ZonedDateTimeBuilder, ZonedDateTimeProp, ZonedDateTime> { | ||
|
|
||
| /** | ||
| * Construct an instance of ZonedDateTimeBuilder | ||
| */ | ||
| public ZonedDateTimeBuilder() { | ||
| instance = this; | ||
| valueType(ZonedDateTimeType.instance()); | ||
| trimmer(TrimToNullTrimmer.instance()); | ||
| } | ||
|
|
||
| @Override | ||
| public ZonedDateTimeProp build() { | ||
| return new ZonedDateTimeProp(_defaultValue, _nonNull, _desc, _validators, | ||
| _aliases, PropertyType.SINGLE_NAME_VALUE, _valueType, _trimmer, _helpText); | ||
| } | ||
|
|
||
| /** | ||
| * The property must be greater than the reference | ||
| * @param reference value the property must be greater than | ||
| * @return the builder instance | ||
| */ | ||
| public ZonedDateTimeBuilder mustBeGreaterThan(ZonedDateTime reference) { | ||
|
Owner
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. See naming in LocalDateTime for all. |
||
| validation(new ZonedDateTimeValidator.GreaterThan(reference)); | ||
| return instance; | ||
| } | ||
|
|
||
| /** | ||
| * The property must be greater than or equal to the reference | ||
| * @param reference value the property must be greater than or equal to | ||
| * @return the builder instance | ||
| */ | ||
| public ZonedDateTimeBuilder mustBeGreaterThanOrEqualTo(ZonedDateTime reference) { | ||
| validation(new ZonedDateTimeValidator.GreaterThanOrEqualTo(reference)); | ||
| return instance; | ||
| } | ||
|
|
||
| /** | ||
| * The property must be less than the reference | ||
| * @param reference value the property must be less than | ||
| * @return the builder instance | ||
| */ | ||
| public ZonedDateTimeBuilder mustBeLessThan(ZonedDateTime reference) { | ||
| validation(new ZonedDateTimeValidator.LessThan(reference)); | ||
| return instance; | ||
| } | ||
|
|
||
| /** | ||
| * The property must be less than or equal to the reference | ||
| * @param reference value the property must be less than or equal to | ||
| * @return the builder instance | ||
| */ | ||
| public ZonedDateTimeBuilder mustBeLessThanOrEqualTo(ZonedDateTime reference) { | ||
| validation(new ZonedDateTimeValidator.LessThanOrEqualTo(reference)); | ||
| return instance; | ||
| } | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,99 @@ | ||
| package org.yarnandtail.andhow.valid; | ||
|
|
||
| import org.yarnandtail.andhow.api.Validator; | ||
|
|
||
| import java.time.ZonedDateTime; | ||
|
|
||
| /** | ||
| * Abstract class implementing the Validator interface for ZonedDateTime. | ||
| * Extended by nested static classes. The nested classes implement | ||
| * constraints that may be used when building the property. | ||
| */ | ||
| public abstract class ZonedDateTimeValidator implements Validator<ZonedDateTime> { | ||
|
Owner
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Similar, refer to LocalDateTimeValidator.java for method names, ie before/after. |
||
|
|
||
| final ZonedDateTime ref; | ||
|
|
||
| /** | ||
| * Base constructor of ZonedDateTimeValidator constraints | ||
| * @param ref to be compared to property value | ||
| */ | ||
| ZonedDateTimeValidator(ZonedDateTime ref) { this.ref = ref; } | ||
|
|
||
| @Override | ||
| public boolean isSpecificationValid() { return ref != null; } | ||
|
|
||
| @Override | ||
| public String getInvalidSpecificationMessage() { return "The constraint may not be null"; } | ||
|
|
||
| /** | ||
| * Validate that a ZonedDateTime is greater than specified reference. | ||
| */ | ||
| public static class GreaterThan extends ZonedDateTimeValidator { | ||
|
|
||
| /** | ||
| * Construct a GreaterThan property constraint | ||
| * @param ref to be compared to property value | ||
| */ | ||
| public GreaterThan(ZonedDateTime ref) { super(ref); } | ||
|
|
||
| @Override | ||
| public boolean isValid(ZonedDateTime value) { return value != null && value.isAfter(ref); } | ||
|
|
||
| @Override | ||
| public String getTheValueMustDescription() { return "be greater than " + ref.toString(); } | ||
| } | ||
|
|
||
| /** | ||
| * Validate that a ZonedDateTime is greater than or equal to specified reference. | ||
| */ | ||
| public static class GreaterThanOrEqualTo extends ZonedDateTimeValidator { | ||
|
|
||
| /** | ||
| * Construct a GreaterThanOrEqualTo property constraint | ||
| * @param ref to be compared to property value | ||
| */ | ||
| public GreaterThanOrEqualTo(ZonedDateTime ref) { super(ref); } | ||
|
|
||
| @Override | ||
| public boolean isValid(ZonedDateTime value) { return value != null && (value.isEqual(ref) || value.isAfter(ref)); } | ||
|
|
||
| @Override | ||
| public String getTheValueMustDescription() { return "be greater than or equal to " + ref; } | ||
| } | ||
|
|
||
| /** | ||
| * Validate that a ZonedDateTime is less than to specified reference. | ||
| */ | ||
| public static class LessThan extends ZonedDateTimeValidator { | ||
|
|
||
| /** | ||
| * Construct a LessThan property constraint | ||
| * @param ref to be compared to property value | ||
| */ | ||
| public LessThan(ZonedDateTime ref) { super(ref); } | ||
|
|
||
| @Override | ||
| public boolean isValid(ZonedDateTime value) { return value != null && value.isBefore(ref); } | ||
|
|
||
| @Override | ||
| public String getTheValueMustDescription() { return "be less than " + ref; } | ||
| } | ||
|
|
||
| /** | ||
| * Validate that a ZonedDateTime is less than or equal to specified reference. | ||
| */ | ||
| public static class LessThanOrEqualTo extends ZonedDateTimeValidator { | ||
|
|
||
| /** | ||
| * Construct a LessThanOrEqualTo property constraint | ||
| * @param ref to be compared to property value | ||
| */ | ||
| public LessThanOrEqualTo(ZonedDateTime ref) { super(ref); } | ||
|
|
||
| @Override | ||
| public boolean isValid(ZonedDateTime value) { return value != null && (value.isEqual(ref) || value.isBefore(ref)); } | ||
|
|
||
| @Override | ||
| public String getTheValueMustDescription() { return "be less than or equal to " + ref; } | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,52 @@ | ||
| package org.yarnandtail.andhow.valuetype; | ||
|
|
||
| import org.yarnandtail.andhow.api.ParsingException; | ||
|
|
||
| import java.time.ZonedDateTime; | ||
|
|
||
| /** | ||
| * Type representation of a Java ZonedDateTime objects. | ||
| * | ||
| * This class is threadsafe and uses a singleton pattern to prevent multiple | ||
| * instances, since all users can safely use the same instance. | ||
| * | ||
| * @author chace86 | ||
| */ | ||
| public class ZonedDateTimeType extends BaseValueType<ZonedDateTime> { | ||
|
|
||
| private static final ZonedDateTimeType INSTANCE = new ZonedDateTimeType(); | ||
|
|
||
| private ZonedDateTimeType() { super(ZonedDateTime.class); } | ||
|
|
||
| /** | ||
| * @return An instance of the {@link #ZonedDateTimeType()} | ||
| */ | ||
| public static ZonedDateTimeType instance() { return INSTANCE; } | ||
|
|
||
| /** | ||
| * The text format used is the default for ZonedDateTime objects, which uses the | ||
| * ISO format like this: <code>2019-10-31T03:16:15.149Z[Europe/Paris]</code>. Full documentation | ||
| * is here: https://docs.oracle.com/javase/8/docs/api/java/time/format/DateTimeFormatter.html#ISO_ZONED_DATE_TIME | ||
| * @param sourceValue The {@link String} value to be parsed into a @{@link ZonedDateTime} | ||
| * @return A valid @{@link ZonedDateTime} | ||
| * @throws ParsingException If the @{@link String} cannot be parsed into a @{@link ZonedDateTime} | ||
| */ | ||
| @Override | ||
| public ZonedDateTime parse(String sourceValue) throws ParsingException { | ||
|
|
||
| if (sourceValue != null) { | ||
| try { | ||
| return ZonedDateTime.parse(sourceValue); | ||
|
Owner
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think we want to make this easier to construct. The default parse method requires the square bracket construction where as most users don't care about the named region, just the hour offset. Can we switch to this format/parser: https://docs.oracle.com/javase/8/docs/api/java/time/format/DateTimeFormatter.html#ISO_ZONED_DATE_TIME That should allow either. |
||
| } catch (Exception e) { | ||
| throw new ParsingException("Unable to convert to a LocalDateTime", sourceValue, e); | ||
|
Owner
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Should be ZonedDateTime |
||
| } | ||
| } else { | ||
| return null; | ||
| } | ||
| } | ||
|
|
||
| @Override | ||
| public ZonedDateTime cast(Object o) throws RuntimeException { | ||
| return (ZonedDateTime)o; | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,114 @@ | ||
| package org.yarnandtail.andhow.valid; | ||
|
|
||
| import org.junit.Test; | ||
|
|
||
| import java.time.ZonedDateTime; | ||
| import java.time.temporal.ChronoUnit; | ||
|
|
||
| import static org.junit.Assert.*; | ||
|
|
||
| public class ZonedDateTimeValidatorTest { | ||
|
|
||
| private static String EXPECTED_DBL_VALIDATOR_INVALID_MESSAGE = "The constraint may not be null"; | ||
| private static final ZonedDateTime CURRENT_TIME = ZonedDateTime.now(); | ||
|
|
||
| @Test | ||
| public void testGreaterThan_IsSpecificationValid() { | ||
| ZonedDateTimeValidator.GreaterThan instance = new ZonedDateTimeValidator.GreaterThan(CURRENT_TIME); | ||
| assertTrue(instance.isSpecificationValid()); | ||
|
|
||
| instance = new ZonedDateTimeValidator.GreaterThan(null); | ||
| assertFalse(instance.isSpecificationValid()); | ||
| assertEquals(EXPECTED_DBL_VALIDATOR_INVALID_MESSAGE, instance.getInvalidSpecificationMessage()); | ||
| } | ||
|
|
||
| @Test | ||
| public void testGreaterThan_GetTheValueMustDescription() { | ||
| ZonedDateTimeValidator.GreaterThan instance = new ZonedDateTimeValidator.GreaterThan(CURRENT_TIME); | ||
| assertEquals("be greater than " + CURRENT_TIME, instance.getTheValueMustDescription()); | ||
| } | ||
|
|
||
| @Test | ||
| public void testGreaterThan_IsValid() { | ||
| ZonedDateTimeValidator.GreaterThan instance = new ZonedDateTimeValidator.GreaterThan(CURRENT_TIME); | ||
| assertFalse(instance.isValid(CURRENT_TIME)); | ||
| assertFalse(instance.isValid(CURRENT_TIME.minus(1, ChronoUnit.DAYS))); | ||
| assertTrue(instance.isValid(CURRENT_TIME.plus(1, ChronoUnit.DAYS))); | ||
| assertFalse(instance.isValid(null)); | ||
| } | ||
|
|
||
| @Test | ||
| public void testGreaterThanOrEqualTo_IsSpecificationValid() { | ||
| ZonedDateTimeValidator.GreaterThanOrEqualTo instance = new ZonedDateTimeValidator.GreaterThanOrEqualTo(CURRENT_TIME); | ||
| assertTrue(instance.isSpecificationValid()); | ||
|
|
||
| instance = new ZonedDateTimeValidator.GreaterThanOrEqualTo(null); | ||
| assertFalse(instance.isSpecificationValid()); | ||
| assertEquals(EXPECTED_DBL_VALIDATOR_INVALID_MESSAGE, instance.getInvalidSpecificationMessage()); | ||
| } | ||
|
|
||
| @Test | ||
| public void testGreaterThanOrEqualTo_GetTheValueMustDescription() { | ||
| ZonedDateTimeValidator.GreaterThanOrEqualTo instance = new ZonedDateTimeValidator.GreaterThanOrEqualTo(CURRENT_TIME); | ||
| assertEquals("be greater than or equal to " + CURRENT_TIME, instance.getTheValueMustDescription()); | ||
| } | ||
|
|
||
| @Test | ||
| public void testGreaterThanOrEqualTo_IsValid() { | ||
| ZonedDateTimeValidator.GreaterThanOrEqualTo instance = new ZonedDateTimeValidator.GreaterThanOrEqualTo(CURRENT_TIME); | ||
| assertTrue(instance.isValid(CURRENT_TIME)); | ||
| assertFalse(instance.isValid(CURRENT_TIME.minus(1, ChronoUnit.DAYS))); | ||
| assertTrue(instance.isValid(CURRENT_TIME.plus(1, ChronoUnit.DAYS))); | ||
| assertFalse(instance.isValid(null)); | ||
| } | ||
|
|
||
| @Test | ||
| public void testLessThan_IsSpecificationValid() { | ||
| ZonedDateTimeValidator.LessThan instance = new ZonedDateTimeValidator.LessThan(CURRENT_TIME); | ||
| assertTrue(instance.isSpecificationValid()); | ||
|
|
||
| instance = new ZonedDateTimeValidator.LessThan(null); | ||
| assertFalse(instance.isSpecificationValid()); | ||
| assertEquals(EXPECTED_DBL_VALIDATOR_INVALID_MESSAGE, instance.getInvalidSpecificationMessage()); | ||
| } | ||
|
|
||
| @Test | ||
| public void testLessThan_GetTheValueMustDescription() { | ||
| ZonedDateTimeValidator.LessThan instance = new ZonedDateTimeValidator.LessThan(CURRENT_TIME); | ||
| assertEquals("be less than " + CURRENT_TIME, instance.getTheValueMustDescription()); | ||
| } | ||
|
|
||
| @Test | ||
| public void testLessThan_IsValid() { | ||
| ZonedDateTimeValidator.LessThan instance = new ZonedDateTimeValidator.LessThan(CURRENT_TIME); | ||
| assertFalse(instance.isValid(CURRENT_TIME)); | ||
| assertTrue(instance.isValid(CURRENT_TIME.minus(1, ChronoUnit.DAYS))); | ||
| assertFalse(instance.isValid(CURRENT_TIME.plus(1, ChronoUnit.DAYS))); | ||
| assertFalse(instance.isValid(null)); | ||
| } | ||
|
|
||
| @Test | ||
| public void testLessThanOrEqualTo_IsSpecificationValid() { | ||
| ZonedDateTimeValidator.LessThanOrEqualTo instance = new ZonedDateTimeValidator.LessThanOrEqualTo(CURRENT_TIME); | ||
| assertTrue(instance.isSpecificationValid()); | ||
|
|
||
| instance = new ZonedDateTimeValidator.LessThanOrEqualTo(null); | ||
| assertFalse(instance.isSpecificationValid()); | ||
| assertEquals(EXPECTED_DBL_VALIDATOR_INVALID_MESSAGE, instance.getInvalidSpecificationMessage()); | ||
| } | ||
|
|
||
| @Test | ||
| public void testLessThanOrEqualTo_GetTheValueMustDescription() { | ||
| ZonedDateTimeValidator.LessThanOrEqualTo instance = new ZonedDateTimeValidator.LessThanOrEqualTo(CURRENT_TIME); | ||
| assertEquals("be less than or equal to " + CURRENT_TIME, instance.getTheValueMustDescription()); | ||
| } | ||
|
|
||
| @Test | ||
| public void testLessThanOrEqualTo_IsValid() { | ||
| ZonedDateTimeValidator.LessThanOrEqualTo instance = new ZonedDateTimeValidator.LessThanOrEqualTo(CURRENT_TIME); | ||
| assertTrue(instance.isValid(CURRENT_TIME)); | ||
| assertTrue(instance.isValid(CURRENT_TIME.minus(1, ChronoUnit.DAYS))); | ||
| assertFalse(instance.isValid(CURRENT_TIME.plus(1, ChronoUnit.DAYS))); | ||
| assertFalse(instance.isValid(null)); | ||
| } | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice catch - I wonder how long that has been there??