From bf5eaa8dce158ef821935ef34687a0fbd19ce9bc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Eivind=20Bergst=C3=B8l?= <> Date: Thu, 19 Sep 2024 23:45:56 +0200 Subject: [PATCH 1/7] Update some dev dependendencies --- pom.xml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pom.xml b/pom.xml index 859150c..e1b6693 100644 --- a/pom.xml +++ b/pom.xml @@ -116,7 +116,7 @@ org.junit.jupiter junit-jupiter-api - 5.9.0 + 5.11.0 test @@ -266,8 +266,8 @@ - 1.8 - 1.8 + 8 + 8 UTF-8 From b84a964c2e348c9f3d78fceb3917ef33f069648e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Eivind=20Bergst=C3=B8l?= Date: Fri, 20 Sep 2024 09:28:14 +0200 Subject: [PATCH 2/7] Rewrite NorwegianDateUtil to use java.time java.util.Date and java.util.Calendar is old now and we don't want to use that any more. Breaking changes: We use ZonedDateTime in stead of Date to represent a date to check for working days. The list of holidays are now a NavigableSet and not a Date[]. Co-authored-by: tobiasgwaaler Co-authored-by: runeflobakk Co-authored-by: martin-jackson Co-authored-by: hhaga Co-authored-by: fredrbus --- pom.xml | 6 + .../bekk/bekkopen/date/NorwegianDateUtil.java | 259 +++++------------- .../bekkopen/date/NorwegianDateUtilTest.java | 202 ++++++++------ 3 files changed, 191 insertions(+), 276 deletions(-) diff --git a/pom.xml b/pom.xml index e1b6693..7f695f9 100644 --- a/pom.xml +++ b/pom.xml @@ -125,6 +125,12 @@ 2.2 test + + uk.co.probablyfine + java-8-matchers + 1.9 + test + org.hibernate.validator hibernate-validator diff --git a/src/main/java/no/bekk/bekkopen/date/NorwegianDateUtil.java b/src/main/java/no/bekk/bekkopen/date/NorwegianDateUtil.java index 343ef1d..7e6e2c5 100644 --- a/src/main/java/no/bekk/bekkopen/date/NorwegianDateUtil.java +++ b/src/main/java/no/bekk/bekkopen/date/NorwegianDateUtil.java @@ -26,19 +26,24 @@ * #L% */ -import java.util.Arrays; -import java.util.Calendar; -import java.util.Date; +import java.time.DayOfWeek; +import java.time.LocalDate; +import java.time.Month; +import java.time.ZonedDateTime; +import java.util.Comparator; import java.util.HashMap; -import java.util.HashSet; import java.util.Map; +import java.util.NavigableSet; import java.util.Set; +import java.util.TreeSet; +import java.util.stream.Stream; /** * Utility class for Norwegian dates. */ public class NorwegianDateUtil { - private static Map> holidays; + + private final static Map> holidays = new HashMap<>(); /** * Adds the given number of working days to the given date. A working day is @@ -60,19 +65,14 @@ public class NorwegianDateUtil { * The number of working days to add. * @return The new date. */ - public static Date addWorkingDaysToDate(Date date, int days) { - Calendar cal = dateToCalendar(date); - - for (int i = 0; i < days; i++) { - cal.add(Calendar.DATE, 1); - while (!isWorkingDay(cal)) { - cal.add(Calendar.DATE, 1); - } - } - - return cal.getTime(); + public static ZonedDateTime addWorkingDaysToDate(ZonedDateTime date, int days) { + return Stream.iterate(date, (d) -> d.plusDays(1)) + .filter(NorwegianDateUtil::isWorkingDay) + .limit(days + 1) + .max(Comparator.naturalOrder()) + .orElse(date); } - + /** * Will check if the given date is a working day. That is check if the given * date is a weekend day or a national holiday. @@ -81,8 +81,8 @@ public static Date addWorkingDaysToDate(Date date, int days) { * The date to check. * @return true if the given date is a working day, false otherwise. */ - public static boolean isWorkingDay(Date date) { - return isWorkingDay(dateToCalendar(date)); + public static boolean isWorkingDay(ZonedDateTime date) { + return date.getDayOfWeek() != DayOfWeek.SATURDAY && date.getDayOfWeek() != DayOfWeek.SUNDAY && !isHoliday(date); } /** @@ -92,24 +92,50 @@ public static boolean isWorkingDay(Date date) { * The Date to check. * @return true if holiday, false otherwise. */ - public static boolean isHoliday(Date date) { - return isHoliday(dateToCalendar(date)); + public static boolean isHoliday(ZonedDateTime date) { + final Set holidaySet = getHolidaySet(date.getYear()); + return holidaySet.contains(date.toLocalDate()); } - + /** - * Return a sorted array of holidays for a given year. + * Return a sorted set of holidays for a given year. * * @param year * The year to get holidays for. - * @return The array of holidays, sorted by date. + * @return The set of holidays, naturally sorted by date. */ - public static Date[] getHolidays(int year) { - Set days = getHolidaySet(year); - Date[] dates = days.toArray(new Date[days.size()]); - Arrays.sort(dates); - return dates; + public static NavigableSet getHolidays(int year) { + return getHolidaySet(year); } + /** + * Calculates easter day (sunday) by using Spencer Jones formula found here: + * Wikipedia - + * Påskeformelen + * + * @param year + * The year to calculate from. + * @return The LocalDate representing easter day for the given year. + */ + private static LocalDate getEasterDay(int year) { + int a = year % 19; + int b = year / 100; + int c = year % 100; + int d = b / 4; + int e = b % 4; + int f = (b + 8) / 25; + int g = (b - f + 1) / 3; + int h = ((19 * a) + b - d - g + 15) % 30; + int i = c / 4; + int k = c % 4; + int l = (32 + (2 * e) + (2 * i) - h - k) % 7; + int m = (a + (11 * h) + (22 * l)) / 451; + int n = (h + l - (7 * m) + 114) / 31; // This is the month number. + int p = (h + l - (7 * m) + 114) % 31; // This is the date minus one. + + return LocalDate.of(year, n, p + 1); + } + /** * Get a set of holidays for a given year. * @@ -117,189 +143,46 @@ public static Date[] getHolidays(int year) { * The year to get holidays for. * @return The set of dates. */ - private static Set getHolidaySet(int year) { - if (holidays == null) { - holidays = new HashMap<>(); - } + private static NavigableSet getHolidaySet(int year) { if (!holidays.containsKey(year)) { - Set yearSet = new HashSet<>(); + NavigableSet yearSet = new TreeSet<>(); // Add set holidays. - yearSet.add(getDate(1, Calendar.JANUARY, year)); - yearSet.add(getDate(1, Calendar.MAY, year)); - yearSet.add(getDate(17, Calendar.MAY, year)); - yearSet.add(getDate(25, Calendar.DECEMBER, year)); - yearSet.add(getDate(26, Calendar.DECEMBER, year)); + yearSet.add(LocalDate.of(year, Month.JANUARY, 1)); + yearSet.add(LocalDate.of(year, Month.MAY, 1)); + yearSet.add(LocalDate.of(year, Month.MAY, 17)); + yearSet.add(LocalDate.of(year, Month.DECEMBER, 25)); + yearSet.add(LocalDate.of(year, Month.DECEMBER, 26)); // Add movable holidays - based on easter day. - Calendar easterDay = dateToCalendar(getEasterDay(year)); + final LocalDate easterDay = getEasterDay(year); // Sunday before easter. - yearSet.add(rollGetDate(easterDay, -7)); + yearSet.add(easterDay.minusDays(7)); // Thursday before easter. - yearSet.add(rollGetDate(easterDay, -3)); + yearSet.add(easterDay.minusDays(3)); // Friday before easter. - yearSet.add(rollGetDate(easterDay, -2)); + yearSet.add(easterDay.minusDays(2)); // Easter day. - yearSet.add(easterDay.getTime()); + yearSet.add(easterDay); // Second easter day. - yearSet.add(rollGetDate(easterDay, 1)); + yearSet.add(easterDay.plusDays(1)); // "Kristi himmelfart" day. - yearSet.add(rollGetDate(easterDay, 39)); + yearSet.add(easterDay.plusDays(39)); // "Pinse" day. - yearSet.add(rollGetDate(easterDay, 49)); + yearSet.add(easterDay.plusDays(49)); // Second "Pinse" day. - yearSet.add(rollGetDate(easterDay, 50)); + yearSet.add(easterDay.plusDays(50)); holidays.put(year, yearSet); } return holidays.get(year); } - - /** - * Will check if the given date is a working day. That is check if the given - * date is a weekend day or a national holiday. - * - * @param cal - * The Calendar object representing the date. - * @return true if the given date is a working day, false otherwise. - */ - private static boolean isWorkingDay(Calendar cal) { - return cal.get(Calendar.DAY_OF_WEEK) != Calendar.SATURDAY && cal.get(Calendar.DAY_OF_WEEK) != Calendar.SUNDAY - && !isHoliday(cal); - } - - /** - * Check if given Calendar object represents a holiday. - * - * @param cal - * The Calendar to check. - * @return true if holiday, false otherwise. - */ - private static boolean isHoliday(Calendar cal) { - int year = cal.get(Calendar.YEAR); - Set yearSet = getHolidaySet(year); - for (Object aYearSet : yearSet) { - Date date = (Date) aYearSet; - if (checkDate(cal, dateToCalendar(date))) { - return true; - } - } - return false; - } - - /** - * Calculates easter day (sunday) by using Spencer Jones formula found here: - * Wikipedia - - * Påskeformelen - * - * @param year - * The year to calculate from. - * @return The Calendar object representing easter day for the given year. - */ - private static Date getEasterDay(int year) { - int a = year % 19; - int b = year / 100; - int c = year % 100; - int d = b / 4; - int e = b % 4; - int f = (b + 8) / 25; - int g = (b - f + 1) / 3; - int h = ((19 * a) + b - d - g + 15) % 30; - int i = c / 4; - int k = c % 4; - int l = (32 + (2 * e) + (2 * i) - h - k) % 7; - int m = (a + (11 * h) + (22 * l)) / 451; - int n = (h + l - (7 * m) + 114) / 31; // This is the month number. - int p = (h + l - (7 * m) + 114) % 31; // This is the date minus one. - - Calendar cal = Calendar.getInstance(); - cal.set(Calendar.YEAR, year); - cal.set(Calendar.MONTH, n - 1); - cal.set(Calendar.DATE, p + 1); - - return cal.getTime(); - } - - /** - * Check if the given dates match on day and month. - * - * @param cal - * The Calendar representing the first date. - * @param other - * The Calendar representing the second date. - * @return true if they match, false otherwise. - */ - private static boolean checkDate(Calendar cal, Calendar other) { - return checkDate(cal, other.get(Calendar.DATE), other.get(Calendar.MONTH)); - } - - /** - * Check if the given date represents the given date and month. - * - * @param cal - * The Calendar object representing date to check. - * @param date - * The date. - * @param month - * The month. - * @return true if they match, false otherwise. - */ - private static boolean checkDate(Calendar cal, int date, int month) { - return cal.get(Calendar.DATE) == date && cal.get(Calendar.MONTH) == month; - } - - /** - * Convert the given Date object to a Calendar instance. - * - * @param date - * The Date object. - * @return The Calendar instance. - */ - private static Calendar dateToCalendar(Date date) { - Calendar cal = Calendar.getInstance(); - cal.setTime(date); - return cal; - } - - /** - * Add the given number of days to the calendar and convert to Date. - * - * @param calendar - * The calendar to add to. - * @param days - * The number of days to add. - * @return The date object given by the modified calendar. - */ - private static Date rollGetDate(Calendar calendar, int days) { - Calendar easterSunday = (Calendar) calendar.clone(); - easterSunday.add(Calendar.DATE, days); - return easterSunday.getTime(); - } - - /** - * Get the date for the given values. - * - * @param day - * The day. - * @param month - * The month. - * @param year - * The year. - * @return The date represented by the given values. - */ - private static Date getDate(int day, int month, int year) { - Calendar cal = Calendar.getInstance(); - cal.set(Calendar.YEAR, year); - cal.set(Calendar.MONTH, month); - cal.set(Calendar.DATE, day); - return cal.getTime(); - } } diff --git a/src/test/java/no/bekk/bekkopen/date/NorwegianDateUtilTest.java b/src/test/java/no/bekk/bekkopen/date/NorwegianDateUtilTest.java index 6e6f32e..9bf038d 100644 --- a/src/test/java/no/bekk/bekkopen/date/NorwegianDateUtilTest.java +++ b/src/test/java/no/bekk/bekkopen/date/NorwegianDateUtilTest.java @@ -26,139 +26,165 @@ * #L% */ -import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; -import java.text.DateFormat; -import java.text.ParseException; -import java.text.SimpleDateFormat; -import java.util.Calendar; -import java.util.Date; -import java.util.Locale; +import java.time.LocalDate; +import java.time.Month; +import java.time.ZoneId; +import java.time.ZonedDateTime; +import java.util.Arrays; +import java.util.LinkedHashSet; +import java.util.NavigableSet; +import static org.hamcrest.MatcherAssert.assertThat; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertTrue; +import static uk.co.probablyfine.matchers.Java8Matchers.where; public class NorwegianDateUtilTest { - private static DateFormat FORMAT(){ - return new SimpleDateFormat("dd.MM.yyyy"); - } + + public static ZoneId NORGESONE = ZoneId.of("Europe/Oslo"); - @BeforeEach - public void setLocale() { - Locale.setDefault(new Locale("no", "NO")); + @Test + public void testAdd2DaysWithinSameWeek() { + ZonedDateTime zonedDateTime = LocalDate.of(2024, 9, 18).atStartOfDay(NORGESONE); + + ZonedDateTime ny = NorwegianDateUtil.addWorkingDaysToDate(zonedDateTime, 2); + + assertEquals(20, ny.getDayOfMonth()); } + @Test - public void testAdd2DaysWithinSameWeek() throws Exception { - Calendar cal = Calendar.getInstance(); - cal.setTime(NorwegianDateUtil.addWorkingDaysToDate(FORMAT().parse("21.03.2007"), 2)); + public void testAdd2DaysBeforeWeekend() { + ZonedDateTime zonedDateTime = LocalDate.of(2024, 9, 20).atStartOfDay(NORGESONE); + + ZonedDateTime ny = NorwegianDateUtil.addWorkingDaysToDate(zonedDateTime, 2); - assertEquals(23, cal.get(Calendar.DATE)); + assertEquals(24, ny.getDayOfMonth()); } + @Test - public void testAdd2DaysToLastDayOfMonth() throws Exception { - Calendar cal = Calendar.getInstance(); - cal.setTime(NorwegianDateUtil.addWorkingDaysToDate(FORMAT().parse("28.02.2007"), 2)); + void testAdd2DaysToLastDayOfMonth() { + ZonedDateTime zonedDateTime = LocalDate.of(2024, 9, 30).atStartOfDay(NORGESONE); + + ZonedDateTime ny = NorwegianDateUtil.addWorkingDaysToDate(zonedDateTime, 2); - assertEquals(2, cal.get(Calendar.DATE)); - assertEquals(Calendar.MARCH, cal.get(Calendar.MONTH)); + assertEquals(2, ny.getDayOfMonth()); + assertEquals(Month.OCTOBER, ny.getMonth()); } @Test - public void testAdd5DaysWithNoHolidays() throws Exception { - Calendar cal = Calendar.getInstance(); - cal.setTime(NorwegianDateUtil.addWorkingDaysToDate(FORMAT().parse("21.03.2007"), 5)); + void testAdd5DaysWithNoHolidays() { + ZonedDateTime zonedDateTime = LocalDate.of(2024, 9, 30).atStartOfDay(NORGESONE); - assertEquals(28, cal.get(Calendar.DATE)); + ZonedDateTime ny = NorwegianDateUtil.addWorkingDaysToDate(zonedDateTime, 5); + + assertEquals(7, ny.getDayOfMonth()); + assertEquals(Month.OCTOBER, ny.getMonth()); } @Test - public void testAdd5DaysBeforeEasterHoliday() throws Exception { - Calendar cal = Calendar.getInstance(); - cal.setTime(NorwegianDateUtil.addWorkingDaysToDate(FORMAT().parse("04.04.2007"), 5)); + void testAdd5DaysBeforeEasterHoliday() { + ZonedDateTime zonedDateTime = LocalDate.of(2025, 4, 11).atStartOfDay(NORGESONE); + + ZonedDateTime ny = NorwegianDateUtil.addWorkingDaysToDate(zonedDateTime, 5); - assertEquals(16, cal.get(Calendar.DATE)); + assertEquals(23, ny.getDayOfMonth()); + assertEquals(Month.APRIL, ny.getMonth()); } @Test - public void testAdd5DaysBeforeNationalDay() throws Exception { - Calendar cal = Calendar.getInstance(); - cal.setTime(NorwegianDateUtil.addWorkingDaysToDate(FORMAT().parse("16.05.2007"), 5)); + void testAdd5DaysBeforeNationalDay() { + ZonedDateTime zonedDateTime = LocalDate.of(2007, 5, 16).atStartOfDay(NORGESONE); - assertEquals(24, cal.get(Calendar.DATE)); + ZonedDateTime ny = NorwegianDateUtil.addWorkingDaysToDate(zonedDateTime, 5); + + assertEquals(24, ny.getDayOfMonth()); + assertEquals(Month.MAY, ny.getMonth()); } @Test - public void testAdd5DaysBeforeChristmas() throws Exception { - Calendar cal = Calendar.getInstance(); - cal.setTime(NorwegianDateUtil.addWorkingDaysToDate(FORMAT().parse("21.12.2007"), 5)); + void testAdd5DaysBeforeChristmas() { + ZonedDateTime zonedDateTime = LocalDate.of(2024, 12, 20).atStartOfDay(NORGESONE); + + ZonedDateTime ny = NorwegianDateUtil.addWorkingDaysToDate(zonedDateTime, 6); - assertEquals(2, cal.get(Calendar.DATE)); - assertEquals(Calendar.JANUARY, cal.get(Calendar.MONTH)); - assertEquals(2008, cal.get(Calendar.YEAR)); + assertEquals(2, ny.getDayOfMonth()); + assertEquals(Month.JANUARY, ny.getMonth()); + assertEquals(2025, ny.getYear()); } @Test - public void testWorkingDays() throws Exception { - assertFalse(NorwegianDateUtil.isWorkingDay(FORMAT().parse("25.03.2007")), "Sunday not working day"); - assertTrue(NorwegianDateUtil.isWorkingDay(FORMAT().parse("26.03.2007")), "Monday is working day"); - assertFalse(NorwegianDateUtil.isWorkingDay(FORMAT().parse("01.01.2007")), "New years day not working day"); - assertFalse(NorwegianDateUtil.isWorkingDay(FORMAT().parse("08.04.2007")), "Easter day not working day"); + public void testWorkingDays() { + assertFalse(NorwegianDateUtil.isWorkingDay(LocalDate.of(2024, 9, 22).atStartOfDay(NORGESONE)), "Sunday not working day"); + assertTrue(NorwegianDateUtil.isWorkingDay(LocalDate.of(2024, 9, 16).atStartOfDay(NORGESONE)), "Monday is working day"); + assertFalse(NorwegianDateUtil.isWorkingDay(LocalDate.of(2025, 1, 1).atStartOfDay(NORGESONE)), "New years day not working day"); + assertFalse(NorwegianDateUtil.isWorkingDay(LocalDate.of(2007, 4, 8).atStartOfDay(NORGESONE)), "Easter day not working day"); } + @Test - public void testVariousNorwegianHolidays() throws Exception { + public void testVariousNorwegianHolidays() { // Set dates - checkHoliday("01.01.2007"); - checkHoliday("01.05.2007"); - checkHoliday("17.05.2007"); - checkHoliday("25.12.2007"); - checkHoliday("26.12.2007"); - - // Movable dates 2007 - checkHoliday("01.04.2007"); - checkHoliday("05.04.2007"); - checkHoliday("06.04.2007"); - checkHoliday("08.04.2007"); - checkHoliday("09.04.2007"); - checkHoliday("17.05.2007"); - checkHoliday("27.05.2007"); - checkHoliday("28.05.2007"); - - // Movable dates 2008 - checkHoliday("16.03.2008"); - checkHoliday("20.03.2008"); - checkHoliday("21.03.2008"); - checkHoliday("23.03.2008"); - checkHoliday("24.03.2008"); - checkHoliday("01.05.2008"); - checkHoliday("11.05.2008"); - checkHoliday("12.05.2008"); + checkHoliday(LocalDate.of(2007, 1, 1)); + checkHoliday(LocalDate.of(2007, 5, 1)); + checkHoliday(LocalDate.of(2007, 5, 17)); + checkHoliday(LocalDate.of(2007, 12, 25)); + checkHoliday(LocalDate.of(2007, 12, 26)); + + // Movable daLocalDate.of(2, 2, 2);tes 2007 + checkHoliday(LocalDate.of(2007, 4, 1)); + checkHoliday(LocalDate.of(2007, 4, 5)); + checkHoliday(LocalDate.of(2007, 4, 6)); + checkHoliday(LocalDate.of(2007, 4, 8)); + checkHoliday(LocalDate.of(2007, 4, 8)); + checkHoliday(LocalDate.of(2007, 5, 17)); + checkHoliday(LocalDate.of(2007, 5, 27)); + checkHoliday(LocalDate.of(2007, 5, 28)); + + // Movable daLocalDate.of(2, 2, 2);tes 2008 + checkHoliday(LocalDate.of(2008, 3, 16)); + checkHoliday(LocalDate.of(2008, 3, 20)); + checkHoliday(LocalDate.of(2008, 3, 21)); + checkHoliday(LocalDate.of(2008, 3, 23)); + checkHoliday(LocalDate.of(2008, 3, 24)); + checkHoliday(LocalDate.of(2008, 5, 1)); + checkHoliday(LocalDate.of(2008, 5, 11)); + checkHoliday(LocalDate.of(2008, 5, 12)); } + @Test public void testGetAllNorwegianHolidaysForYear() { - Date[] holidays = NorwegianDateUtil.getHolidays(2009); - assertEquals(13, holidays.length); - assertEquals("01.01.2009", FORMAT().format(holidays[0])); - assertEquals("05.04.2009", FORMAT().format(holidays[1])); - assertEquals("09.04.2009", FORMAT().format(holidays[2])); - assertEquals("10.04.2009", FORMAT().format(holidays[3])); - assertEquals("12.04.2009", FORMAT().format(holidays[4])); - assertEquals("13.04.2009", FORMAT().format(holidays[5])); - assertEquals("01.05.2009", FORMAT().format(holidays[6])); - assertEquals("17.05.2009", FORMAT().format(holidays[7])); - assertEquals("21.05.2009", FORMAT().format(holidays[8])); - assertEquals("31.05.2009", FORMAT().format(holidays[9])); - assertEquals("01.06.2009", FORMAT().format(holidays[10])); - assertEquals("25.12.2009", FORMAT().format(holidays[11])); - assertEquals("26.12.2009", FORMAT().format(holidays[12])); + NavigableSet holidays = NorwegianDateUtil.getHolidays(2009); + + assertEquals(13, holidays.size()); + + LinkedHashSet fasit = new LinkedHashSet<>(Arrays.asList( + LocalDate.of(2009, 1, 1), + LocalDate.of(2009, 4, 5), + LocalDate.of(2009, 4, 9), + LocalDate.of(2009, 4, 10), + LocalDate.of(2009, 4, 12), + LocalDate.of(2009, 4, 13), + LocalDate.of(2009, 5, 1), + LocalDate.of(2009, 5, 17), + LocalDate.of(2009, 5, 21), + LocalDate.of(2009, 5, 31), + LocalDate.of(2009, 6, 1), + LocalDate.of(2009, 12, 25), + LocalDate.of(2009, 12, 26) + )); + + assertEquals(fasit, holidays); + + } - private void checkHoliday(String date) throws ParseException { - assertTrue(NorwegianDateUtil.isHoliday(FORMAT().parse(date)), date); + private void checkHoliday(LocalDate date) { + assertThat(date.atStartOfDay(NORGESONE), where(NorwegianDateUtil::isHoliday)); } } From 288a1a3d5a9451404a058cfdafc10ce174e31342 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Eivind=20Bergst=C3=B8l?= Date: Fri, 4 Oct 2024 18:14:44 +0200 Subject: [PATCH 3/7] Expose constants for Norwegian standard ZoneId Europe/Oslo --- .../bekk/bekkopen/date/NorwegianDateUtil.java | 4 +++ .../bekkopen/date/NorwegianDateUtilTest.java | 27 +++++++++---------- 2 files changed, 17 insertions(+), 14 deletions(-) diff --git a/src/main/java/no/bekk/bekkopen/date/NorwegianDateUtil.java b/src/main/java/no/bekk/bekkopen/date/NorwegianDateUtil.java index 7e6e2c5..ed18295 100644 --- a/src/main/java/no/bekk/bekkopen/date/NorwegianDateUtil.java +++ b/src/main/java/no/bekk/bekkopen/date/NorwegianDateUtil.java @@ -29,6 +29,7 @@ import java.time.DayOfWeek; import java.time.LocalDate; import java.time.Month; +import java.time.ZoneId; import java.time.ZonedDateTime; import java.util.Comparator; import java.util.HashMap; @@ -42,6 +43,9 @@ * Utility class for Norwegian dates. */ public class NorwegianDateUtil { + + public static final String ZONEID_EUROPE_OSLO = "Europe/Oslo"; + public static final ZoneId ZONE_NORWAY = ZoneId.of(ZONEID_EUROPE_OSLO); private final static Map> holidays = new HashMap<>(); diff --git a/src/test/java/no/bekk/bekkopen/date/NorwegianDateUtilTest.java b/src/test/java/no/bekk/bekkopen/date/NorwegianDateUtilTest.java index 9bf038d..74b4165 100644 --- a/src/test/java/no/bekk/bekkopen/date/NorwegianDateUtilTest.java +++ b/src/test/java/no/bekk/bekkopen/date/NorwegianDateUtilTest.java @@ -30,12 +30,12 @@ import java.time.LocalDate; import java.time.Month; -import java.time.ZoneId; import java.time.ZonedDateTime; import java.util.Arrays; import java.util.LinkedHashSet; import java.util.NavigableSet; +import static no.bekk.bekkopen.date.NorwegianDateUtil.ZONE_NORWAY; import static org.hamcrest.MatcherAssert.assertThat; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; @@ -44,11 +44,10 @@ public class NorwegianDateUtilTest { - public static ZoneId NORGESONE = ZoneId.of("Europe/Oslo"); @Test public void testAdd2DaysWithinSameWeek() { - ZonedDateTime zonedDateTime = LocalDate.of(2024, 9, 18).atStartOfDay(NORGESONE); + ZonedDateTime zonedDateTime = LocalDate.of(2024, 9, 18).atStartOfDay(ZONE_NORWAY); ZonedDateTime ny = NorwegianDateUtil.addWorkingDaysToDate(zonedDateTime, 2); @@ -58,7 +57,7 @@ public void testAdd2DaysWithinSameWeek() { @Test public void testAdd2DaysBeforeWeekend() { - ZonedDateTime zonedDateTime = LocalDate.of(2024, 9, 20).atStartOfDay(NORGESONE); + ZonedDateTime zonedDateTime = LocalDate.of(2024, 9, 20).atStartOfDay(ZONE_NORWAY); ZonedDateTime ny = NorwegianDateUtil.addWorkingDaysToDate(zonedDateTime, 2); @@ -68,7 +67,7 @@ public void testAdd2DaysBeforeWeekend() { @Test void testAdd2DaysToLastDayOfMonth() { - ZonedDateTime zonedDateTime = LocalDate.of(2024, 9, 30).atStartOfDay(NORGESONE); + ZonedDateTime zonedDateTime = LocalDate.of(2024, 9, 30).atStartOfDay(ZONE_NORWAY); ZonedDateTime ny = NorwegianDateUtil.addWorkingDaysToDate(zonedDateTime, 2); @@ -78,7 +77,7 @@ void testAdd2DaysToLastDayOfMonth() { @Test void testAdd5DaysWithNoHolidays() { - ZonedDateTime zonedDateTime = LocalDate.of(2024, 9, 30).atStartOfDay(NORGESONE); + ZonedDateTime zonedDateTime = LocalDate.of(2024, 9, 30).atStartOfDay(ZONE_NORWAY); ZonedDateTime ny = NorwegianDateUtil.addWorkingDaysToDate(zonedDateTime, 5); @@ -88,7 +87,7 @@ void testAdd5DaysWithNoHolidays() { @Test void testAdd5DaysBeforeEasterHoliday() { - ZonedDateTime zonedDateTime = LocalDate.of(2025, 4, 11).atStartOfDay(NORGESONE); + ZonedDateTime zonedDateTime = LocalDate.of(2025, 4, 11).atStartOfDay(ZONE_NORWAY); ZonedDateTime ny = NorwegianDateUtil.addWorkingDaysToDate(zonedDateTime, 5); @@ -98,7 +97,7 @@ void testAdd5DaysBeforeEasterHoliday() { @Test void testAdd5DaysBeforeNationalDay() { - ZonedDateTime zonedDateTime = LocalDate.of(2007, 5, 16).atStartOfDay(NORGESONE); + ZonedDateTime zonedDateTime = LocalDate.of(2007, 5, 16).atStartOfDay(ZONE_NORWAY); ZonedDateTime ny = NorwegianDateUtil.addWorkingDaysToDate(zonedDateTime, 5); @@ -108,7 +107,7 @@ void testAdd5DaysBeforeNationalDay() { @Test void testAdd5DaysBeforeChristmas() { - ZonedDateTime zonedDateTime = LocalDate.of(2024, 12, 20).atStartOfDay(NORGESONE); + ZonedDateTime zonedDateTime = LocalDate.of(2024, 12, 20).atStartOfDay(ZONE_NORWAY); ZonedDateTime ny = NorwegianDateUtil.addWorkingDaysToDate(zonedDateTime, 6); @@ -119,10 +118,10 @@ void testAdd5DaysBeforeChristmas() { @Test public void testWorkingDays() { - assertFalse(NorwegianDateUtil.isWorkingDay(LocalDate.of(2024, 9, 22).atStartOfDay(NORGESONE)), "Sunday not working day"); - assertTrue(NorwegianDateUtil.isWorkingDay(LocalDate.of(2024, 9, 16).atStartOfDay(NORGESONE)), "Monday is working day"); - assertFalse(NorwegianDateUtil.isWorkingDay(LocalDate.of(2025, 1, 1).atStartOfDay(NORGESONE)), "New years day not working day"); - assertFalse(NorwegianDateUtil.isWorkingDay(LocalDate.of(2007, 4, 8).atStartOfDay(NORGESONE)), "Easter day not working day"); + assertFalse(NorwegianDateUtil.isWorkingDay(LocalDate.of(2024, 9, 22).atStartOfDay(ZONE_NORWAY)), "Sunday not working day"); + assertTrue(NorwegianDateUtil.isWorkingDay(LocalDate.of(2024, 9, 16).atStartOfDay(ZONE_NORWAY)), "Monday is working day"); + assertFalse(NorwegianDateUtil.isWorkingDay(LocalDate.of(2025, 1, 1).atStartOfDay(ZONE_NORWAY)), "New years day not working day"); + assertFalse(NorwegianDateUtil.isWorkingDay(LocalDate.of(2007, 4, 8).atStartOfDay(ZONE_NORWAY)), "Easter day not working day"); } @@ -185,6 +184,6 @@ public void testGetAllNorwegianHolidaysForYear() { } private void checkHoliday(LocalDate date) { - assertThat(date.atStartOfDay(NORGESONE), where(NorwegianDateUtil::isHoliday)); + assertThat(date.atStartOfDay(ZONE_NORWAY), where(NorwegianDateUtil::isHoliday)); } } From d118d24c3ad679bd55386fe67148a62742c07555 Mon Sep 17 00:00:00 2001 From: Martin Jackson Date: Wed, 22 Oct 2025 19:24:08 +0200 Subject: [PATCH 4/7] =?UTF-8?q?Skriv=20om=20no.bekk.bekkopen.person=20til?= =?UTF-8?q?=20=C3=A5=20bruke=20java.time?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Breaking change: Du må erstatte java.util.Date med java.time.LocalDate. Gjorde i tillegg en liten endring i Person::getFodselsDato slik at LocalDate-en som returneres har riktig århundre. Beregning av fødselsdato fra fødselsnummer blir riktignok deprecated i pull requesten nedenfor, men metoden får vel leve en liten stund til. https://github.com/bekkopen/NoCommons/pull/74 --- .../person/FodselsnummerCalculator.java | 46 ++++++++----------- .../java/no/bekk/bekkopen/person/Person.java | 12 ++--- .../person/FodselsnummerCalculatorTest.java | 33 ++++++------- .../no/bekk/bekkopen/person/PersonTest.java | 27 ++++------- .../SyntheticFodselsnummerCalculatorTest.java | 14 ++---- .../FodselsnummerAnnotationTest.java | 5 +- 6 files changed, 50 insertions(+), 87 deletions(-) diff --git a/src/main/java/no/bekk/bekkopen/person/FodselsnummerCalculator.java b/src/main/java/no/bekk/bekkopen/person/FodselsnummerCalculator.java index 1d11774..1920e8e 100644 --- a/src/main/java/no/bekk/bekkopen/person/FodselsnummerCalculator.java +++ b/src/main/java/no/bekk/bekkopen/person/FodselsnummerCalculator.java @@ -26,12 +26,10 @@ * #L% */ -import java.text.DateFormat; -import java.text.SimpleDateFormat; +import java.time.LocalDate; +import java.time.format.DateTimeFormatter; import java.util.ArrayList; -import java.util.Calendar; import java.util.Collections; -import java.util.Date; import java.util.Iterator; import java.util.List; @@ -54,8 +52,7 @@ private FodselsnummerCalculator() { * @param kjonn kjønn * @return liste med fødselsnummer */ - @Deprecated - public static List getFodselsnummerForDateAndGender(Date date, KJONN kjonn) { + public static List getFodselsnummerForDateAndGender(LocalDate date, KJONN kjonn) { List result = getManyFodselsnummerForDate(date); splitByGender(kjonn, result); return result; @@ -66,7 +63,7 @@ public static List getFodselsnummerForDateAndGender(Date date, KJ * @param date en dato * @return et fødselsnummer */ - public static Fodselsnummer getFodselsnummerForDate(Date date){ + public static Fodselsnummer getFodselsnummerForDate(LocalDate date) { List fodselsnummerList = getManyFodselsnummerForDate(date); Collections.shuffle(fodselsnummerList); return fodselsnummerList.get(0); @@ -78,14 +75,13 @@ public static Fodselsnummer getFodselsnummerForDate(Date date){ * @param date The Date instance * @return A List with Fodelsnummer instances */ - - public static List getManyDNumberFodselsnummerForDate(Date date) { + public static List getManyDNumberFodselsnummerForDate(LocalDate date) { if (date == null) { throw new IllegalArgumentException(); } - DateFormat df = new SimpleDateFormat("ddMMyy"); + DateTimeFormatter dtf = DateTimeFormatter.ofPattern("ddMMyy"); String centuryString = getCentury(date); - String dateString = df.format(date); + String dateString = dtf.format(date); dateString = Character.toChars(dateString.charAt(0) + 4)[0] + dateString.substring(1); return generateFodselsnummerForDate(dateString, centuryString); @@ -97,14 +93,13 @@ public static List getManyDNumberFodselsnummerForDate(Date date) * @param date The Date instance * @return A List with Fodelsnummer instances */ - - public static List getManySyntheticFodselsnummerForDate(Date date) { + public static List getManySyntheticFodselsnummerForDate(LocalDate date) { if (date == null) { throw new IllegalArgumentException(); } - DateFormat df = new SimpleDateFormat("ddMMyy"); + DateTimeFormatter dtf = DateTimeFormatter.ofPattern("ddMMyy"); String centuryString = getCentury(date); - String dateString = df.format(date); + String dateString = dtf.format(date); dateString = dateString.substring(0, 2) + Character.toChars(dateString.charAt(2) + 8)[0] + dateString.substring(3); @@ -117,14 +112,13 @@ public static List getManySyntheticFodselsnummerForDate(Date date * @param date The Date instance * @return A List with Fodelsnummer instances */ - - public static List getManySyntheticDNumberFodselsnummerForDate(Date date) { + public static List getManySyntheticDNumberFodselsnummerForDate(LocalDate date) { if (date == null) { throw new IllegalArgumentException(); } - DateFormat df = new SimpleDateFormat("ddMMyy"); + DateTimeFormatter dtf = DateTimeFormatter.ofPattern("ddMMyy"); String centuryString = getCentury(date); - String dateString = df.format(date); + String dateString = dtf.format(date); dateString = Character.toChars(dateString.charAt(0) + 4)[0] + dateString.substring(1, 2) + Character.toChars(dateString.charAt(2) + 8)[0] + @@ -138,14 +132,13 @@ public static List getManySyntheticDNumberFodselsnummerForDate(Da * @param date The Date instance * @return A List with Fodelsnummer instances */ - - public static List getManyFodselsnummerForDate(Date date) { + public static List getManyFodselsnummerForDate(LocalDate date) { if (date == null) { throw new IllegalArgumentException(); } - DateFormat df = new SimpleDateFormat("ddMMyy"); + DateTimeFormatter dtf = DateTimeFormatter.ofPattern("ddMMyy"); String centuryString = getCentury(date); - String dateString = df.format(date); + String dateString = dtf.format(date); return generateFodselsnummerForDate(dateString, centuryString); } @@ -178,11 +171,8 @@ private static List generateFodselsnummerForDate(String dateStrin return result; } - private static String getCentury(Date date) { - Calendar c = Calendar.getInstance(); - c.setTime(date); - int year = c.get(Calendar.YEAR); - return Integer.toString(year).substring(0, 2); + private static String getCentury(LocalDate date) { + return Integer.toString(date.getYear()).substring(0, 2); } private static void splitByGender(KJONN kjonn, List result) { diff --git a/src/main/java/no/bekk/bekkopen/person/Person.java b/src/main/java/no/bekk/bekkopen/person/Person.java index 57b26ee..31960b4 100644 --- a/src/main/java/no/bekk/bekkopen/person/Person.java +++ b/src/main/java/no/bekk/bekkopen/person/Person.java @@ -26,14 +26,12 @@ * #L% */ -import java.text.DateFormat; -import java.text.ParseException; -import java.text.SimpleDateFormat; -import java.util.Date; +import java.time.LocalDate; +import java.time.format.DateTimeFormatter; public class Person { - private final static DateFormat fDatoFormat = new SimpleDateFormat("ddMMyy"); + private static final DateTimeFormatter fDatoFormat = DateTimeFormatter.ofPattern("ddMMyyyy"); private final Navn navn; private final Fodselsnummer fodselsnummer; @@ -67,8 +65,8 @@ public String getFodselsdatoAsString() { return this.fodselsnummer.getDateOfBirth(); } - public Date getFodselsdato() throws ParseException { - return fDatoFormat.parse(this.fodselsnummer.getDateOfBirth()); + public LocalDate getFodselsdato() { + return LocalDate.parse(this.fodselsnummer.getDateAndMonth() + this.fodselsnummer.getBirthYear(), fDatoFormat); } public String getPersonnummer() { diff --git a/src/test/java/no/bekk/bekkopen/person/FodselsnummerCalculatorTest.java b/src/test/java/no/bekk/bekkopen/person/FodselsnummerCalculatorTest.java index a297d25..4865bbd 100644 --- a/src/test/java/no/bekk/bekkopen/person/FodselsnummerCalculatorTest.java +++ b/src/test/java/no/bekk/bekkopen/person/FodselsnummerCalculatorTest.java @@ -26,13 +26,12 @@ * #L% */ -import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; -import java.text.DateFormat; import java.text.ParseException; -import java.text.SimpleDateFormat; -import java.util.Date; +import java.time.LocalDate; +import java.time.Month; +import java.time.format.DateTimeFormatter; import java.util.List; import static org.junit.jupiter.api.Assertions.assertEquals; @@ -41,14 +40,8 @@ public class FodselsnummerCalculatorTest { - private DateFormat df = null; - private Date date = null; - - @BeforeEach - public void setUpDate() throws Exception { - df = new SimpleDateFormat("ddMMyyyy"); - date = df.parse("09062006"); - } + private final DateTimeFormatter dtf = DateTimeFormatter.ofPattern("ddMMyyyy"); + private LocalDate date = LocalDate.of(2006, Month.JUNE, 9); @Test public void testGetFodselsnummerForDate() { @@ -87,9 +80,9 @@ public void testThatAtLeastOneDNumberIsGenerated() { } @Test - public void testThatAtLeastOneDNumberIsGeneratedsas() throws ParseException { - assertEquals(82, FodselsnummerCalculator.getManyDNumberFodselsnummerForDate(df.parse("06061878")).size()); - assertEquals(164, FodselsnummerCalculator.getManyDNumberFodselsnummerForDate(df.parse("12101921")).size()); + public void testThatAtLeastOneDNumberIsGeneratedsas() { + assertEquals(82, FodselsnummerCalculator.getManyDNumberFodselsnummerForDate(LocalDate.parse("06061878", dtf)).size()); + assertEquals(164, FodselsnummerCalculator.getManyDNumberFodselsnummerForDate(LocalDate.parse("12101921", dtf)).size()); } @Test @@ -107,22 +100,22 @@ public void testThatAllGeneratedDNumbersAreDNumbers() { } @Test - public void testInvalidDateTooEarly() throws ParseException { - date = df.parse("09091853"); + public void testInvalidDateTooEarly() { + date = LocalDate.parse("09091853", dtf); List options = FodselsnummerCalculator.getManyFodselsnummerForDate(date); assertEquals(0, options.size()); } @Test - public void testInvalidDateTooLate() throws ParseException { - date = df.parse("09092040"); + public void testInvalidDateTooLate() { + date = LocalDate.parse("09092040", dtf); List options = FodselsnummerCalculator.getManyFodselsnummerForDate(date); assertEquals(0, options.size()); } @Test public void testOneFodselsnummer() throws ParseException { - date = df.parse("01121980"); + date = LocalDate.parse("01121980", dtf); Fodselsnummer fodselsnummer = FodselsnummerCalculator.getFodselsnummerForDate(date); assertTrue(FodselsnummerValidator.isValid(fodselsnummer.toString())); } diff --git a/src/test/java/no/bekk/bekkopen/person/PersonTest.java b/src/test/java/no/bekk/bekkopen/person/PersonTest.java index 14ca255..0308074 100644 --- a/src/test/java/no/bekk/bekkopen/person/PersonTest.java +++ b/src/test/java/no/bekk/bekkopen/person/PersonTest.java @@ -26,15 +26,12 @@ * #L% */ -import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; -import java.text.DateFormat; -import java.text.ParseException; -import java.util.Calendar; -import java.util.Date; +import java.time.LocalDate; +import java.time.Month; +import java.time.format.DateTimeFormatter; import java.util.List; -import java.util.Locale; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; @@ -43,17 +40,9 @@ public class PersonTest { - private Calendar kalender; - - @BeforeEach - public void initialiserKalender() { - kalender = Calendar.getInstance(); - } - @Test - public void lagMann() throws ParseException { - kalender.set(1973, Calendar.DECEMBER, 10); - Date fodselsdato = kalender.getTime(); + public void lagMann() { + LocalDate fodselsdato = LocalDate.of(1973, Month.DECEMBER, 10); List fodselsnumre = FodselsnummerCalculator.getFodselsnummerForDateAndGender(fodselsdato, KJONN.MANN); Fodselsnummer fodselsnummer = fodselsnumre.get(0); @@ -80,9 +69,9 @@ public void lagMann() throws ParseException { Navn pNavn = person.getNavn(); NavnGeneratorTest.assertGyldigNavn(pNavn); - Date pFodselsdato = person.getFodselsdato(); - DateFormat df = DateFormat.getDateInstance(DateFormat.SHORT, new Locale("no", "NO")); - assertEquals(df.format(fodselsdato), df.format(pFodselsdato)); + LocalDate pFodselsdato = person.getFodselsdato(); + DateTimeFormatter dtf = DateTimeFormatter.ofPattern("dd.MM.yyyy"); + assertEquals(dtf.format(fodselsdato), dtf.format(pFodselsdato)); String pFodselsdatoString = person.getFodselsdatoAsString(); assertEquals("101273", pFodselsdatoString); diff --git a/src/test/java/no/bekk/bekkopen/person/SyntheticFodselsnummerCalculatorTest.java b/src/test/java/no/bekk/bekkopen/person/SyntheticFodselsnummerCalculatorTest.java index 42d1705..2c87a9c 100644 --- a/src/test/java/no/bekk/bekkopen/person/SyntheticFodselsnummerCalculatorTest.java +++ b/src/test/java/no/bekk/bekkopen/person/SyntheticFodselsnummerCalculatorTest.java @@ -28,18 +28,16 @@ import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.BeforeAll; -import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; -import java.text.DateFormat; -import java.text.SimpleDateFormat; -import java.util.Date; +import java.time.LocalDate; +import java.time.Month; import static org.junit.jupiter.api.Assertions.assertTrue; public class SyntheticFodselsnummerCalculatorTest { - private Date date = null; + private LocalDate date = LocalDate.of(2006, Month.JUNE, 9); @BeforeAll public static void setup() { @@ -51,12 +49,6 @@ public static void teardown() { FodselsnummerValidator.ALLOW_SYNTHETIC_NUMBERS = false; } - @BeforeEach - public void setUpDate() throws Exception { - DateFormat df = new SimpleDateFormat("ddMMyyyy"); - date = df.parse("09062006"); - } - @Test public void testThatAllGeneratedSyntheticDNumbersAreValid() { for (Fodselsnummer fnr : FodselsnummerCalculator.getManySyntheticDNumberFodselsnummerForDate(date)) { diff --git a/src/test/java/no/bekk/bekkopen/person/annotation/FodselsnummerAnnotationTest.java b/src/test/java/no/bekk/bekkopen/person/annotation/FodselsnummerAnnotationTest.java index 4b3ac8e..9dca296 100644 --- a/src/test/java/no/bekk/bekkopen/person/annotation/FodselsnummerAnnotationTest.java +++ b/src/test/java/no/bekk/bekkopen/person/annotation/FodselsnummerAnnotationTest.java @@ -34,7 +34,8 @@ import jakarta.validation.Validation; import jakarta.validation.Validator; import jakarta.validation.ValidatorFactory; -import java.util.Date; + +import java.time.LocalDate; import java.util.Set; import static org.junit.jupiter.api.Assertions.assertEquals; @@ -69,7 +70,7 @@ public void should_accept_null_values(){ @Test public void should_validate_valid_fodselsnummer(){ - Person k = new Person(FodselsnummerCalculator.getFodselsnummerForDate(new Date()).toString()); + Person k = new Person(FodselsnummerCalculator.getFodselsnummerForDate(LocalDate.now()).toString()); Set> violations = validator.validate(k); From b3c901b5dc9784b0952e76dbada1f74df8c50138 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Eivind=20Bergst=C3=B8l?= Date: Thu, 24 Sep 2026 15:21:21 +0200 Subject: [PATCH 5/7] =?UTF-8?q?Fjern=20kj=C3=B8nn=20fra=20Fodselsnummer?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Kjønn vil slutte å være et konsept i 2032 i sammenheng med fødselsnummer. Vi forbereder oss allerede nå ved å ta vekk konseptet i god tid. Siden kjønn forsvinner fra fodselsnummer har vi ingen måte i Person-klassen å identifisere om det er mannsnavn eller kvinnenavn. jeg fjerner derfor enkelt og greit denne funksjonen fra Person. --- .../bekk/bekkopen/person/Fodselsnummer.java | 42 +------------------ .../person/FodselsnummerCalculator.java | 28 ------------- .../java/no/bekk/bekkopen/person/Person.java | 9 ---- .../no/bekk/bekkopen/person/PersonTest.java | 9 +--- 4 files changed, 3 insertions(+), 85 deletions(-) diff --git a/src/main/java/no/bekk/bekkopen/person/Fodselsnummer.java b/src/main/java/no/bekk/bekkopen/person/Fodselsnummer.java index 61ddc7a..d1a78d1 100644 --- a/src/main/java/no/bekk/bekkopen/person/Fodselsnummer.java +++ b/src/main/java/no/bekk/bekkopen/person/Fodselsnummer.java @@ -170,12 +170,9 @@ public String getIndividnummer() { /** * Returns the digit that decides the gender - the 9th in the Fodselsnummer. - * - * @deprecated For removal - Gender will stop working after 1.1.2032 - * Nytt fødselsnummer fra 2032 + * * @return The digit. */ - @Deprecated public int getGenderDigit() { return getAt(8); } @@ -198,30 +195,6 @@ public int getChecksumDigit2() { return getAt(10); } - /** - * Returns true if the Fodselsnummer represents a man. - * - * @deprecated For removal - Gender will stop working after 1.1.2032 - * Nytt fødselsnummer fra 2032 - * @return true or false. - */ - @Deprecated - public boolean isMale() { - return getGenderDigit() % 2 != 0; - } - - /** - * Returns true if the Fodselsnummer represents a woman. - * - * @deprecated For removal - Gender will stop working after 1.1.2032 - * Nytt fødselsnummer fra 2032 - * @return true or false. - */ - @Deprecated - public boolean isFemale() { - return !isMale(); - } - static String parseSyntheticNumber(String fodselsnummer) { if (!isSynthetic(fodselsnummer)) { return fodselsnummer; @@ -291,19 +264,6 @@ private static int getThirdDigit(String fodselsnummer) { return Integer.parseInt(fodselsnummer.substring(2, 3)); } - /** - * @deprecated For removal - Gender will stop working after 1.1.2032 - * Nytt fødselsnummer fra 2032 - */ - @Deprecated - public KJONN getKjonn() { - if (isFemale()) { - return KJONN.KVINNE; - } else { - return KJONN.MANN; - } - } - @Override public String toString() { return super.getValue(); diff --git a/src/main/java/no/bekk/bekkopen/person/FodselsnummerCalculator.java b/src/main/java/no/bekk/bekkopen/person/FodselsnummerCalculator.java index 1920e8e..0e1ccb9 100644 --- a/src/main/java/no/bekk/bekkopen/person/FodselsnummerCalculator.java +++ b/src/main/java/no/bekk/bekkopen/person/FodselsnummerCalculator.java @@ -30,7 +30,6 @@ import java.time.format.DateTimeFormatter; import java.util.ArrayList; import java.util.Collections; -import java.util.Iterator; import java.util.List; /** @@ -42,22 +41,6 @@ private FodselsnummerCalculator() { super(); } - /** - * Returns a List with valid Fodselsnummer instances for a given Date and gender. - * - * @deprecated For removal - Gender will stop working after 1.1.2032 - * Nytt fødselsnummer fra 2032 - * - * @param date en dato - * @param kjonn kjønn - * @return liste med fødselsnummer - */ - public static List getFodselsnummerForDateAndGender(LocalDate date, KJONN kjonn) { - List result = getManyFodselsnummerForDate(date); - splitByGender(kjonn, result); - return result; - } - /** * Return one random valid fodselsnummer on a given date * @param date en dato @@ -174,15 +157,4 @@ private static List generateFodselsnummerForDate(String dateStrin private static String getCentury(LocalDate date) { return Integer.toString(date.getYear()).substring(0, 2); } - - private static void splitByGender(KJONN kjonn, List result) { - Iterator iter = result.iterator(); - while (iter.hasNext()) { - Fodselsnummer f = iter.next(); - if (f.getKjonn() != kjonn) { - iter.remove(); - } - } - } - } diff --git a/src/main/java/no/bekk/bekkopen/person/Person.java b/src/main/java/no/bekk/bekkopen/person/Person.java index 31960b4..ebde163 100644 --- a/src/main/java/no/bekk/bekkopen/person/Person.java +++ b/src/main/java/no/bekk/bekkopen/person/Person.java @@ -72,13 +72,4 @@ public LocalDate getFodselsdato() { public String getPersonnummer() { return this.fodselsnummer.getPersonnummer(); } - - public boolean erKvinne() { - return fodselsnummer.isFemale(); - } - - public boolean erMann() { - return fodselsnummer.isMale(); - } - } diff --git a/src/test/java/no/bekk/bekkopen/person/PersonTest.java b/src/test/java/no/bekk/bekkopen/person/PersonTest.java index 0308074..d6866a9 100644 --- a/src/test/java/no/bekk/bekkopen/person/PersonTest.java +++ b/src/test/java/no/bekk/bekkopen/person/PersonTest.java @@ -34,24 +34,19 @@ import java.util.List; import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertTrue; public class PersonTest { @Test - public void lagMann() { + public void lagPerson() { LocalDate fodselsdato = LocalDate.of(1973, Month.DECEMBER, 10); - List fodselsnumre = FodselsnummerCalculator.getFodselsnummerForDateAndGender(fodselsdato, - KJONN.MANN); + List fodselsnumre = FodselsnummerCalculator.getManyFodselsnummerForDate(fodselsdato); Fodselsnummer fodselsnummer = fodselsnumre.get(0); Navn navn = NavnGenerator.genererMannsnavn(); Person person = new Person(navn, fodselsnummer); - assertTrue(person.erMann()); - assertFalse(person.erKvinne()); - String pFornavn = person.getFornavn(); assertTrue(pFornavn.matches(NavnGeneratorTest.NAVN_PATTERN), pFornavn + " matcher ikke " + NavnGeneratorTest.NAVN_PATTERN); From 29ab89627670f03ced4bd90cd7597705a7a97d8a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Eivind=20Bergst=C3=B8l?= Date: Thu, 24 Sep 2026 15:52:29 +0200 Subject: [PATCH 6/7] Remove function regarding gender --- src/main/java/no/bekk/bekkopen/person/Fodselsnummer.java | 9 --------- .../java/no/bekk/bekkopen/person/FodselsnummerTest.java | 5 ----- 2 files changed, 14 deletions(-) diff --git a/src/main/java/no/bekk/bekkopen/person/Fodselsnummer.java b/src/main/java/no/bekk/bekkopen/person/Fodselsnummer.java index d1a78d1..37b83a5 100644 --- a/src/main/java/no/bekk/bekkopen/person/Fodselsnummer.java +++ b/src/main/java/no/bekk/bekkopen/person/Fodselsnummer.java @@ -168,15 +168,6 @@ public String getIndividnummer() { return getValue().substring(6, 9); } - /** - * Returns the digit that decides the gender - the 9th in the Fodselsnummer. - * - * @return The digit. - */ - public int getGenderDigit() { - return getAt(8); - } - /** * Returns the first checksum digit - the 10th in the Fodselsnummer. * diff --git a/src/test/java/no/bekk/bekkopen/person/FodselsnummerTest.java b/src/test/java/no/bekk/bekkopen/person/FodselsnummerTest.java index 5dc39b4..f0eb72a 100644 --- a/src/test/java/no/bekk/bekkopen/person/FodselsnummerTest.java +++ b/src/test/java/no/bekk/bekkopen/person/FodselsnummerTest.java @@ -139,11 +139,6 @@ public void testGetIndividnummer() { assertEquals("234", sut.getIndividnummer()); } - @Test - public void testGetGenderDigit() { - assertEquals(4, sut.getGenderDigit()); - } - @Test public void testGetChecksumDigits() { assertEquals(7, sut.getChecksumDigit1()); From 68d5915555f31f0634319cdee714cac220a902dd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Eivind=20Bergst=C3=B8l?= Date: Thu, 24 Sep 2026 15:59:24 +0200 Subject: [PATCH 7/7] Fjern bruk av SimpleDateFormat til fordel for java.time --- .../bekkopen/person/FodselsnummerValidator.java | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/src/main/java/no/bekk/bekkopen/person/FodselsnummerValidator.java b/src/main/java/no/bekk/bekkopen/person/FodselsnummerValidator.java index 501b616..dbb50ac 100644 --- a/src/main/java/no/bekk/bekkopen/person/FodselsnummerValidator.java +++ b/src/main/java/no/bekk/bekkopen/person/FodselsnummerValidator.java @@ -31,9 +31,10 @@ import jakarta.validation.ConstraintValidator; import jakarta.validation.ConstraintValidatorContext; import java.net.URL; -import java.text.DateFormat; -import java.text.ParseException; -import java.text.SimpleDateFormat; +import java.time.LocalDate; +import java.time.format.DateTimeFormatter; +import java.time.format.DateTimeParseException; +import java.time.format.ResolverStyle; import static no.bekk.bekkopen.common.Checksums.ERROR_INVALID_CHECKSUM; import static no.bekk.bekkopen.common.Checksums.calculateMod11CheckSum; @@ -54,7 +55,7 @@ public class FodselsnummerValidator extends StringNumberValidator implements Con private static final int LENGTH = 11; - private static final String DATE_FORMAT = "ddMMyyyy"; + private static final DateTimeFormatter DATE_FORMATTER = DateTimeFormatter.ofPattern("ddMMuuuu").withResolverStyle(ResolverStyle.STRICT); private static final int[] K1_WEIGHTS = new int[] { 2, 5, 4, 9, 8, 1, 6, 7, 3 }; private static final int[] K2_WEIGHTS = new int[] { 2, 3, 4, 5, 6, 7, 2, 3, 4, 5 }; @@ -131,10 +132,8 @@ static void validateDate(String fodselsnummer) { no.bekk.bekkopen.person.Fodselsnummer fnr = new no.bekk.bekkopen.person.Fodselsnummer(fodselsnummer); try { String dateString = fnr.getDateAndMonth() + fnr.getCentury() + fnr.get2DigitBirthYear(); - DateFormat df = new SimpleDateFormat(DATE_FORMAT); - df.setLenient(false); - df.parse(dateString); - } catch (ParseException e) { + LocalDate.parse(dateString, DATE_FORMATTER); + } catch (DateTimeParseException e) { throw new IllegalArgumentException(ERROR_INVALID_DATE + fodselsnummer); } }