diff --git a/dhis-2/dhis-services/dhis-service-tracker/src/main/java/org/hisp/dhis/tracker/imports/validation/validator/enrollment/DateValidator.java b/dhis-2/dhis-services/dhis-service-tracker/src/main/java/org/hisp/dhis/tracker/imports/validation/validator/enrollment/DateValidator.java index f541434cdc55..b04a0a71f038 100644 --- a/dhis-2/dhis-services/dhis-service-tracker/src/main/java/org/hisp/dhis/tracker/imports/validation/validator/enrollment/DateValidator.java +++ b/dhis-2/dhis-services/dhis-service-tracker/src/main/java/org/hisp/dhis/tracker/imports/validation/validator/enrollment/DateValidator.java @@ -36,7 +36,7 @@ import static org.hisp.dhis.tracker.imports.validation.ValidationCode.E1052; import java.time.LocalDate; -import java.time.ZoneOffset; +import java.time.ZoneId; import java.util.Objects; import org.hisp.dhis.program.Program; import org.hisp.dhis.tracker.imports.bundle.TrackerBundle; @@ -84,13 +84,13 @@ private void validateEnrollmentDatesNotInFuture( final LocalDate now = LocalDate.now(); if (Objects.nonNull(enrollment.getEnrolledAt()) && Boolean.FALSE.equals(program.getSelectEnrollmentDatesInFuture()) - && enrollment.getEnrolledAt().atOffset(ZoneOffset.UTC).toLocalDate().isAfter(now)) { + && enrollment.getEnrolledAt().atZone(ZoneId.systemDefault()).toLocalDate().isAfter(now)) { reporter.addError(enrollment, E1020, enrollment.getEnrolledAt()); } if (Objects.nonNull(enrollment.getOccurredAt()) && Boolean.FALSE.equals(program.getSelectIncidentDatesInFuture()) - && enrollment.getOccurredAt().atOffset(ZoneOffset.UTC).toLocalDate().isAfter(now)) { + && enrollment.getOccurredAt().atZone(ZoneId.systemDefault()).toLocalDate().isAfter(now)) { reporter.addError(enrollment, E1021, enrollment.getOccurredAt()); } } diff --git a/dhis-2/dhis-services/dhis-service-tracker/src/test/java/org/hisp/dhis/tracker/imports/validation/validator/enrollment/DateValidatorTest.java b/dhis-2/dhis-services/dhis-service-tracker/src/test/java/org/hisp/dhis/tracker/imports/validation/validator/enrollment/DateValidatorTest.java index 8797e7c53603..4c05e068becf 100644 --- a/dhis-2/dhis-services/dhis-service-tracker/src/test/java/org/hisp/dhis/tracker/imports/validation/validator/enrollment/DateValidatorTest.java +++ b/dhis-2/dhis-services/dhis-service-tracker/src/test/java/org/hisp/dhis/tracker/imports/validation/validator/enrollment/DateValidatorTest.java @@ -41,6 +41,8 @@ import java.time.Duration; import java.time.Instant; +import java.time.LocalDate; +import java.time.ZoneId; import org.hisp.dhis.common.CodeGenerator; import org.hisp.dhis.common.UID; import org.hisp.dhis.program.EnrollmentStatus; @@ -101,7 +103,7 @@ void testMandatoryDatesMustBePresent() { @Test void testDatesMustNotBeInTheFuture() { - final Instant dateInTheFuture = now().plus(Duration.ofDays(2)); + final Instant dateInTheFuture = now().plus(Duration.ofDays(1)); Enrollment enrollment = Enrollment.builder() .enrollment(UID.generate()) @@ -119,6 +121,33 @@ void testDatesMustNotBeInTheFuture() { () -> assertHasError(reporter, enrollment, E1021)); } + @Test + void testDatesWithNoTimeZoneMustNotBeInTheFuture() { + ZoneId systemZone = ZoneId.systemDefault(); + LocalDate tomorrow = LocalDate.now(systemZone).plusDays(1); + Instant dateTomorrow = tomorrow.atStartOfDay(systemZone).toInstant(); + + // Create enrollment with dates set to tomorrow + Enrollment enrollment = + Enrollment.builder() + .enrollment(UID.generate()) + .program(MetadataIdentifier.ofUid(CodeGenerator.generateUid())) + .occurredAt(dateTomorrow) + .enrolledAt(dateTomorrow) + .build(); + + when(preheat.getProgram(enrollment.getProgram())).thenReturn(new Program()); + + // Run validation + validator.validate(reporter, bundle, enrollment); + + // Assert that the future dates are detected as errors + assertAll( + () -> assertHasError(reporter, enrollment, E1020), // enrolledAt in the future + () -> assertHasError(reporter, enrollment, E1021) // occurredAt in the future + ); + } + @Test void testDatesShouldBeAllowedOnSameDayIfFutureDatesAreNotAllowed() { final Instant today = now().plus(Duration.ofMinutes(1));