From 09eec336be05f3de860c6d7138bb2b060074cb38 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Johannes=20Tegn=C3=A9r?= Date: Sun, 12 Mar 2023 11:12:21 +0100 Subject: [PATCH] feat: Implemented interim numbers. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Johannes Tegnér --- .../java/dev/personnummer/Personnummer.java | 19 +++++++++++++++++-- src/test/java/DataProvider.java | 9 +++++++-- src/test/java/InterimnummerTest.java | 8 ++++---- 3 files changed, 28 insertions(+), 8 deletions(-) diff --git a/src/main/java/dev/personnummer/Personnummer.java b/src/main/java/dev/personnummer/Personnummer.java index 9cd407b..1bc856f 100644 --- a/src/main/java/dev/personnummer/Personnummer.java +++ b/src/main/java/dev/personnummer/Personnummer.java @@ -14,9 +14,12 @@ */ public final class Personnummer implements Comparable { private static final Pattern regexPattern; + private static final Pattern interimPatternTest; + private static final String interimTestStr = "(?![-+])\\D"; static { - regexPattern = Pattern.compile("^(\\d{2})?(\\d{2})(\\d{2})(\\d{2})([-+]?)?((?!000)\\d{3})(\\d?)$"); + regexPattern = Pattern.compile("^(\\d{2})?(\\d{2})(\\d{2})(\\d{2})([-+]?)?((?!000)\\d{3}|[TRSUWXJKLMN]\\d{2})(\\d?)$"); + interimPatternTest = Pattern.compile(interimTestStr); } /** @@ -112,6 +115,13 @@ public Personnummer(String personnummer, Options options) throws PersonnummerExc throw new PersonnummerException("Failed to parse personal identity number. Invalid input."); } + if (!options.allowInterimNumbers && interimPatternTest.matcher(personnummer).find()) { + throw new PersonnummerException( + personnummer + + " contains non-integer characters and options are set to not allow interim numbers" + ); + } + Matcher matches = regexPattern.matcher(personnummer); if (!matches.find()) { throw new PersonnummerException("Failed to parse personal identity number. Invalid input."); @@ -154,9 +164,14 @@ public Personnummer(String personnummer, Options options) throws PersonnummerExc this.isMale = Integer.parseInt(Character.toString(this.numbers.charAt(2))) % 2 == 1; + String nums = matches.group(6); + if (options.allowInterimNumbers) { + nums = nums.replaceFirst(interimTestStr, "1"); + } + // The format passed to Luhn method is supposed to be YYmmDDNNN // Hence all numbers that are less than 10 (or in last case 100) will have leading 0's added. - if (luhn(String.format("%s%s%s%s", this.year, this.month, this.day, matches.group(6))) != Integer.parseInt(this.controlNumber)) { + if (luhn(String.format("%s%s%s%s", this.year, this.month, this.day, nums)) != Integer.parseInt(this.controlNumber)) { throw new PersonnummerException("Invalid personal identity number."); } } diff --git a/src/test/java/DataProvider.java b/src/test/java/DataProvider.java index ba4dca4..cb14006 100644 --- a/src/test/java/DataProvider.java +++ b/src/test/java/DataProvider.java @@ -71,11 +71,16 @@ public static void initialize() throws IOException { JSONObject current = rootObject.getJSONObject(i); interimNr.add(new PersonnummerData( current.getLong("integer"), + current.getString("long_format"), current.getString("short_format"), current.getString("separated_format"), + current.getString("separated_long"), current.getBoolean("valid"), - current.getString("type") - )); + current.getString("type"), + false, // ignore + false // ignore + ) + ); } } diff --git a/src/test/java/InterimnummerTest.java b/src/test/java/InterimnummerTest.java index 91089a1..c0bac6d 100644 --- a/src/test/java/InterimnummerTest.java +++ b/src/test/java/InterimnummerTest.java @@ -34,8 +34,8 @@ public void testValidateInvalidInterim(PersonnummerData ssn) { public void testFormatLongInterim(PersonnummerData ssn) throws PersonnummerException { Personnummer pnr = Personnummer.parse(ssn.longFormat, opts); - assertEquals(pnr.format(false), ssn.longFormat); - assertEquals(pnr.format(), ssn.separatedFormat); + assertEquals(pnr.format(false), ssn.separatedFormat); + assertEquals(pnr.format(true), ssn.longFormat); } @ParameterizedTest @@ -43,8 +43,8 @@ public void testFormatLongInterim(PersonnummerData ssn) throws PersonnummerExcep public void testFormatShortInterim(PersonnummerData ssn) throws PersonnummerException { Personnummer pnr = Personnummer.parse(ssn.shortFormat, opts); - assertEquals(pnr.format(false), ssn.longFormat); - assertEquals(pnr.format(), ssn.separatedFormat); + assertEquals(pnr.format(false), ssn.separatedFormat); + assertEquals(pnr.format(true), ssn.longFormat); } @ParameterizedTest