-
Notifications
You must be signed in to change notification settings - Fork 24
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
refactor: dates validation and formatting (#1177)
* refactor: dates validation and formatting * chore: modifier and typos * refactor: inner class factory and result to record * refactor: oopsies * test: unit test for iso 8601 formatter * refactor: optional instead of null * chore: fix typo in javadoc * refactor: compile year pattern only once
- Loading branch information
Showing
11 changed files
with
387 additions
and
105 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
9 changes: 9 additions & 0 deletions
9
eno-core/src/main/java/fr/insee/eno/core/exceptions/business/InvalidValueException.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
package fr.insee.eno.core.exceptions.business; | ||
|
||
public class InvalidValueException extends RuntimeException { | ||
|
||
public InvalidValueException(String message) { | ||
super(message); | ||
} | ||
|
||
} |
9 changes: 9 additions & 0 deletions
9
eno-core/src/main/java/fr/insee/eno/core/exceptions/business/RequiredPropertyException.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
package fr.insee.eno.core.exceptions.business; | ||
|
||
public class RequiredPropertyException extends RuntimeException { | ||
|
||
public RequiredPropertyException(String message) { | ||
super(message); | ||
} | ||
|
||
} |
54 changes: 54 additions & 0 deletions
54
eno-core/src/main/java/fr/insee/eno/core/i18n/date/DateFormatter.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
package fr.insee.eno.core.i18n.date; | ||
|
||
import fr.insee.eno.core.parameter.EnoParameters; | ||
import lombok.NonNull; | ||
|
||
import java.util.regex.Pattern; | ||
|
||
/** | ||
* Interface to validate and format dates. | ||
*/ | ||
public interface DateFormatter { | ||
|
||
class Factory { | ||
|
||
private Factory() {} | ||
|
||
public static DateFormatter forLanguage(EnoParameters.Language language) { | ||
if (EnoParameters.Language.FR.equals(language)) | ||
return new Iso8601ToFrench(); | ||
// By default, return the implementation that returns date values in ISO-8601 format | ||
return new Iso8601Formatter(); | ||
} | ||
} | ||
|
||
record Result( | ||
boolean isValid, | ||
String value, | ||
String errorMessage) { | ||
|
||
public static Result success(String value) { | ||
return new Result(true, value, null); | ||
} | ||
|
||
public static Result failure(String errorMessage) { | ||
return new Result(false, null, errorMessage); | ||
} | ||
} | ||
|
||
Pattern yearDatePattern = Pattern.compile("\\d{4}"); | ||
|
||
default Result convertYearDate(@NonNull String date) { | ||
if (date.length() != 4 || !yearDatePattern.matcher(date).matches()) | ||
return Result.failure(errorMessage(date, "YYYY")); | ||
return Result.success(date); | ||
} | ||
|
||
Result convertYearMontDate(@NonNull String date); | ||
|
||
Result convertYearMontDayDate(@NonNull String date); | ||
|
||
default String errorMessage(String date, String format) { | ||
return "Date '" + date + "' is invalid or doesn't match format '" + format + "'."; | ||
} | ||
} |
29 changes: 29 additions & 0 deletions
29
eno-core/src/main/java/fr/insee/eno/core/i18n/date/Iso8601Formatter.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
package fr.insee.eno.core.i18n.date; | ||
|
||
import lombok.NonNull; | ||
|
||
import java.time.LocalDate; | ||
import java.time.YearMonth; | ||
import java.time.format.DateTimeFormatter; | ||
|
||
public class Iso8601Formatter implements DateFormatter { | ||
|
||
public Result convertYearMontDate(@NonNull String date) { | ||
try { | ||
return Result.success( | ||
YearMonth.parse(date).format(DateTimeFormatter.ofPattern("yyyy-MM"))); | ||
} catch (Exception e) { | ||
return Result.failure(errorMessage(date, "YYYY-MM")); | ||
} | ||
} | ||
|
||
public Result convertYearMontDayDate(@NonNull String date) { | ||
try { | ||
return Result.success( | ||
LocalDate.parse(date).format(DateTimeFormatter.ofPattern("yyyy-MM-dd"))); | ||
} catch (Exception e) { | ||
return Result.failure(errorMessage(date, "YYYY-MM-DD")); | ||
} | ||
} | ||
|
||
} |
29 changes: 29 additions & 0 deletions
29
eno-core/src/main/java/fr/insee/eno/core/i18n/date/Iso8601ToFrench.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
package fr.insee.eno.core.i18n.date; | ||
|
||
import lombok.NonNull; | ||
|
||
import java.time.LocalDate; | ||
import java.time.YearMonth; | ||
import java.time.format.DateTimeFormatter; | ||
|
||
public class Iso8601ToFrench implements DateFormatter { | ||
|
||
public Result convertYearMontDate(@NonNull String date) { | ||
try { | ||
return Result.success( | ||
YearMonth.parse(date).format(DateTimeFormatter.ofPattern("MM/yyyy"))); | ||
} catch (Exception e) { | ||
return Result.failure(errorMessage(date, "YYYY-MM")); | ||
} | ||
} | ||
|
||
public Result convertYearMontDayDate(@NonNull String date) { | ||
try { | ||
return Result.success( | ||
LocalDate.parse(date).format(DateTimeFormatter.ofPattern("dd/MM/yyyy"))); | ||
} catch (Exception e) { | ||
return Result.failure(errorMessage(date, "YYYY-MM-DD")); | ||
} | ||
} | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
74 changes: 74 additions & 0 deletions
74
eno-core/src/test/java/fr/insee/eno/core/i18n/Iso8601ToFrenchTest.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,74 @@ | ||
package fr.insee.eno.core.i18n; | ||
|
||
import fr.insee.eno.core.i18n.date.DateFormatter; | ||
import fr.insee.eno.core.i18n.date.Iso8601ToFrench; | ||
import org.junit.jupiter.api.Test; | ||
|
||
import static org.junit.jupiter.api.Assertions.*; | ||
|
||
class Iso8601ToFrenchTest { | ||
|
||
@Test | ||
void testConvertYearDate_ValidYear() { | ||
DateFormatter.Result result = new Iso8601ToFrench().convertYearDate("2023"); | ||
assertTrue(result.isValid()); | ||
assertEquals("2023", result.value()); | ||
} | ||
|
||
@Test | ||
void testConvertYearDate_InvalidYearLength() { | ||
DateFormatter.Result result = new Iso8601ToFrench().convertYearDate("23"); | ||
assertFalse(result.isValid()); | ||
assertEquals("Date '23' is invalid or doesn't match format 'YYYY'.", result.errorMessage()); | ||
} | ||
|
||
@Test | ||
void testConvertYearDate_InvalidCharacters() { | ||
DateFormatter.Result result = new Iso8601ToFrench().convertYearDate("abcd"); | ||
assertFalse(result.isValid()); | ||
assertEquals("Date 'abcd' is invalid or doesn't match format 'YYYY'.", result.errorMessage()); | ||
} | ||
|
||
@Test | ||
void testConvertYearMonthDate_ValidInput() { | ||
DateFormatter.Result result = new Iso8601ToFrench().convertYearMontDate("2023-12"); | ||
assertTrue(result.isValid()); | ||
assertEquals("12/2023", result.value()); | ||
} | ||
|
||
@Test | ||
void testConvertYearMonthDate_InvalidFormat() { | ||
DateFormatter.Result result = new Iso8601ToFrench().convertYearMontDate("2023/12"); | ||
assertFalse(result.isValid()); | ||
assertEquals("Date '2023/12' is invalid or doesn't match format 'YYYY-MM'.", result.errorMessage()); | ||
} | ||
|
||
@Test | ||
void testConvertYearMonthDate_ExtraCharacters() { | ||
DateFormatter.Result result = new Iso8601ToFrench().convertYearMontDate("2023-12-01"); | ||
assertFalse(result.isValid()); | ||
assertEquals("Date '2023-12-01' is invalid or doesn't match format 'YYYY-MM'.", result.errorMessage()); | ||
} | ||
|
||
@Test | ||
void testConvertYearMonthDayDate_ValidInput() { | ||
DateFormatter.Result result = new Iso8601ToFrench().convertYearMontDayDate("2023-12-16"); | ||
assertTrue(result.isValid()); | ||
assertEquals("16/12/2023", result.value()); | ||
} | ||
|
||
@Test | ||
void testConvertYearMonthDayDate_InvalidFormat() { | ||
DateFormatter.Result result = new Iso8601ToFrench().convertYearMontDayDate("2023/12/16"); | ||
assertFalse(result.isValid()); | ||
assertEquals("Date '2023/12/16' is invalid or doesn't match format 'YYYY-MM-DD'.", result.errorMessage()); | ||
} | ||
|
||
@Test | ||
void testConvertYearMonthDayDate_InvalidDate() { | ||
DateFormatter.Result result = new Iso8601ToFrench().convertYearMontDayDate("2023-02-30"); | ||
assertFalse(result.isValid()); | ||
assertEquals("Date '2023-02-30' is invalid or doesn't match format 'YYYY-MM-DD'.", result.errorMessage()); | ||
} | ||
|
||
} |
Oops, something went wrong.