diff --git a/engine/src/main/java/org/hibernate/validator/internal/constraintvalidators/bv/time/future/FutureValidatorForDate.java b/engine/src/main/java/org/hibernate/validator/internal/constraintvalidators/bv/time/future/FutureValidatorForDate.java index 7a56506edb..0f8537eadb 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/constraintvalidators/bv/time/future/FutureValidatorForDate.java +++ b/engine/src/main/java/org/hibernate/validator/internal/constraintvalidators/bv/time/future/FutureValidatorForDate.java @@ -20,7 +20,8 @@ public class FutureValidatorForDate extends AbstractFutureInstantBasedValidator< @Override protected Instant getInstant(Date value) { - return value.toInstant(); + // we don't use Date.toInstant() as it's not supported by java.sql.Date + return Instant.ofEpochMilli( value.getTime() ); } } diff --git a/engine/src/main/java/org/hibernate/validator/internal/constraintvalidators/bv/time/futureorpresent/FutureOrPresentValidatorForDate.java b/engine/src/main/java/org/hibernate/validator/internal/constraintvalidators/bv/time/futureorpresent/FutureOrPresentValidatorForDate.java index b682aa991b..29d47357c1 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/constraintvalidators/bv/time/futureorpresent/FutureOrPresentValidatorForDate.java +++ b/engine/src/main/java/org/hibernate/validator/internal/constraintvalidators/bv/time/futureorpresent/FutureOrPresentValidatorForDate.java @@ -20,7 +20,8 @@ public class FutureOrPresentValidatorForDate extends AbstractFutureOrPresentInst @Override protected Instant getInstant(Date value) { - return value.toInstant(); + // we don't use Date.toInstant() as it's not supported by java.sql.Date + return Instant.ofEpochMilli( value.getTime() ); } } diff --git a/engine/src/main/java/org/hibernate/validator/internal/constraintvalidators/bv/time/past/PastValidatorForDate.java b/engine/src/main/java/org/hibernate/validator/internal/constraintvalidators/bv/time/past/PastValidatorForDate.java index 43066f6341..c97662b83b 100644 --- a/engine/src/main/java/org/hibernate/validator/internal/constraintvalidators/bv/time/past/PastValidatorForDate.java +++ b/engine/src/main/java/org/hibernate/validator/internal/constraintvalidators/bv/time/past/PastValidatorForDate.java @@ -20,7 +20,8 @@ public class PastValidatorForDate extends AbstractPastInstantBasedValidator. + */ +package org.hibernate.validator.test.internal.constraintvalidators.bv.time; + +import java.time.Clock; +import java.time.ZonedDateTime; + +import jakarta.validation.ClockProvider; + +class FixedClockProvider implements ClockProvider { + + private Clock clock; + + public FixedClockProvider(ZonedDateTime dateTime) { + clock = Clock.fixed( dateTime.toInstant(), dateTime.getZone() ); + } + + @Override + public Clock getClock() { + return clock; + } + +} diff --git a/engine/src/test/java/org/hibernate/validator/test/internal/constraintvalidators/bv/time/JavaSqlDateTest.java b/engine/src/test/java/org/hibernate/validator/test/internal/constraintvalidators/bv/time/JavaSqlDateTest.java new file mode 100644 index 0000000000..20958e0718 --- /dev/null +++ b/engine/src/test/java/org/hibernate/validator/test/internal/constraintvalidators/bv/time/JavaSqlDateTest.java @@ -0,0 +1,94 @@ +/* + * Hibernate Validator, declare and validate application constraints + * + * License: Apache License, Version 2.0 + * See the license.txt file in the root directory or . + */ +package org.hibernate.validator.test.internal.constraintvalidators.bv.time; + +import static org.hibernate.validator.testutil.ConstraintViolationAssert.assertThat; +import static org.hibernate.validator.testutil.ConstraintViolationAssert.violationOf; +import static org.hibernate.validator.testutils.ValidatorUtil.getConfiguration; + +import java.time.LocalDate; +import java.time.ZoneId; +import java.time.ZonedDateTime; +import java.util.Set; + +import org.hibernate.validator.testutil.TestForIssue; +import org.testng.annotations.BeforeMethod; +import org.testng.annotations.Test; + +import jakarta.validation.ConstraintViolation; +import jakarta.validation.Validator; +import jakarta.validation.ValidatorFactory; +import jakarta.validation.constraints.Future; +import jakarta.validation.constraints.FutureOrPresent; +import jakarta.validation.constraints.Past; +import jakarta.validation.constraints.PastOrPresent; + +/** + * @author Guillaume Smet + */ +@TestForIssue(jiraKey = "HV-1878") +public class JavaSqlDateTest { + + private static final ZoneId TZ_BERLIN = ZoneId.of( "Europe/Berlin" ); + + private Validator validator; + + @BeforeMethod + public void setupValidator() { + FixedClockProvider clockProvider = new FixedClockProvider( + ZonedDateTime.of( + 2000, 2, 15, 4, 0, 0, 0, + TZ_BERLIN ) ); + ValidatorFactory validatorFactory = getConfiguration() + .clockProvider( clockProvider ) + .buildValidatorFactory(); + + validator = validatorFactory.getValidator(); + } + + @Test + public void testFuture() { + JavaSqlDateHolder javaSqlDateHolder = new JavaSqlDateHolder( + new java.sql.Date( LocalDate.of( 2010, 2, 2 ).atStartOfDay( ZoneId.systemDefault() ).toInstant().toEpochMilli() ) ); + Set> constraintViolations = validator.validate( javaSqlDateHolder ); + assertThat( constraintViolations ).containsOnlyViolations( + violationOf( Past.class ), + violationOf( PastOrPresent.class ) ); + } + + @Test + public void testPast() { + JavaSqlDateHolder javaSqlDateHolder = new JavaSqlDateHolder( + new java.sql.Date( LocalDate.of( 1990, 2, 2 ).atStartOfDay( ZoneId.systemDefault() ).toInstant().toEpochMilli() ) ); + Set> constraintViolations = validator.validate( javaSqlDateHolder ); + assertThat( constraintViolations ).containsOnlyViolations( + violationOf( Future.class ), + violationOf( FutureOrPresent.class ) ); + } + + private static class JavaSqlDateHolder { + + @Future + private java.sql.Date future; + + @FutureOrPresent + private java.sql.Date futureOrPresent; + + @Past + private java.sql.Date past; + + @PastOrPresent + private java.sql.Date pastOrPresent; + + JavaSqlDateHolder(java.sql.Date date) { + this.future = date; + this.futureOrPresent = date; + this.past = date; + this.pastOrPresent = date; + } + } +}