From fd9d956be3fcc528745e53fbfd34ec2d87a7bcf7 Mon Sep 17 00:00:00 2001 From: Igor Kugaudo Date: Mon, 8 Jan 2018 19:24:28 +0200 Subject: [PATCH] BAEL-1351 RegEx for matching Date Pattern in Java (#3217) * kugaudo/igor@kugaudo.com * BAEL-1351 RegEx for matching Date Pattern in Java * BAEL-1351 RegEx for matching Date Pattern in Java * BAEL-1351 RegEx for matching Date Pattern in Java * Fixed names of test methods * Refactored class names, split unit tests by classes * Reordered test cases in Gregorian date matcher unit test, formatted code * Added override annotation * Renamed mather main method for better semantics * Fixed names of test methods * Split Gregorian date matcher to separate branches * Fixed test cases according to the article * Revert "Merge branch 'master' into datepattern" This reverts commit 0d57456140bc9e1f36d32b3e707acd2729b2c60f, reversing changes made to c768132dcd24d4312567298f34c67cb31dcde9f8. --- .../regexp/datepattern/DateMatcher.java | 7 ++ .../datepattern/FormattedDateMatcher.java | 14 +++ .../regexp/datepattern/RangedDateMatcher.java | 14 +++ .../gregorian/February29thMatcher.java | 16 +++ .../gregorian/FebruaryGeneralMatcher.java | 16 +++ .../gregorian/GregorianDateMatcher.java | 19 ++++ .../gregorian/MonthsOf30DaysMatcher.java | 17 +++ .../gregorian/MonthsOf31DaysMatcher.java | 17 +++ .../FormattedDateMatcherUnitTest.java | 24 +++++ .../RangedDateMatcherUnitTest.java | 31 ++++++ .../February29thMatcherUnitTest.java | 17 +++ .../FebruaryGeneralMatcherUnitTest.java | 17 +++ .../GregorianDateMatcherUnitTest.java | 42 ++++++++ .../MonthsOf30DaysMatcherUnitTest.java | 17 +++ .../MonthsOf31DaysMatcherUnitTest.java | 17 +++ .../testhelper/GregorianDateTestHelper.java | 102 ++++++++++++++++++ 16 files changed, 387 insertions(+) create mode 100644 core-java/src/main/java/com/baeldung/regexp/datepattern/DateMatcher.java create mode 100644 core-java/src/main/java/com/baeldung/regexp/datepattern/FormattedDateMatcher.java create mode 100644 core-java/src/main/java/com/baeldung/regexp/datepattern/RangedDateMatcher.java create mode 100644 core-java/src/main/java/com/baeldung/regexp/datepattern/gregorian/February29thMatcher.java create mode 100644 core-java/src/main/java/com/baeldung/regexp/datepattern/gregorian/FebruaryGeneralMatcher.java create mode 100644 core-java/src/main/java/com/baeldung/regexp/datepattern/gregorian/GregorianDateMatcher.java create mode 100644 core-java/src/main/java/com/baeldung/regexp/datepattern/gregorian/MonthsOf30DaysMatcher.java create mode 100644 core-java/src/main/java/com/baeldung/regexp/datepattern/gregorian/MonthsOf31DaysMatcher.java create mode 100644 core-java/src/test/java/com/baeldung/regexp/datepattern/FormattedDateMatcherUnitTest.java create mode 100644 core-java/src/test/java/com/baeldung/regexp/datepattern/RangedDateMatcherUnitTest.java create mode 100644 core-java/src/test/java/com/baeldung/regexp/datepattern/gregorian/February29thMatcherUnitTest.java create mode 100644 core-java/src/test/java/com/baeldung/regexp/datepattern/gregorian/FebruaryGeneralMatcherUnitTest.java create mode 100644 core-java/src/test/java/com/baeldung/regexp/datepattern/gregorian/GregorianDateMatcherUnitTest.java create mode 100644 core-java/src/test/java/com/baeldung/regexp/datepattern/gregorian/MonthsOf30DaysMatcherUnitTest.java create mode 100644 core-java/src/test/java/com/baeldung/regexp/datepattern/gregorian/MonthsOf31DaysMatcherUnitTest.java create mode 100644 core-java/src/test/java/com/baeldung/regexp/datepattern/gregorian/testhelper/GregorianDateTestHelper.java diff --git a/core-java/src/main/java/com/baeldung/regexp/datepattern/DateMatcher.java b/core-java/src/main/java/com/baeldung/regexp/datepattern/DateMatcher.java new file mode 100644 index 0000000000..3e85bf13bb --- /dev/null +++ b/core-java/src/main/java/com/baeldung/regexp/datepattern/DateMatcher.java @@ -0,0 +1,7 @@ +package com.baeldung.regexp.datepattern; + +public interface DateMatcher { + + boolean matches(String date); + +} diff --git a/core-java/src/main/java/com/baeldung/regexp/datepattern/FormattedDateMatcher.java b/core-java/src/main/java/com/baeldung/regexp/datepattern/FormattedDateMatcher.java new file mode 100644 index 0000000000..1d3a609b55 --- /dev/null +++ b/core-java/src/main/java/com/baeldung/regexp/datepattern/FormattedDateMatcher.java @@ -0,0 +1,14 @@ +package com.baeldung.regexp.datepattern; + +import java.util.regex.Pattern; + +class FormattedDateMatcher implements DateMatcher { + + private static final Pattern DATE_PATTERN = Pattern.compile( + "^\\d{4}-\\d{2}-\\d{2}$"); + + @Override + public boolean matches(String date) { + return DATE_PATTERN.matcher(date).matches(); + } +} diff --git a/core-java/src/main/java/com/baeldung/regexp/datepattern/RangedDateMatcher.java b/core-java/src/main/java/com/baeldung/regexp/datepattern/RangedDateMatcher.java new file mode 100644 index 0000000000..af4e183fef --- /dev/null +++ b/core-java/src/main/java/com/baeldung/regexp/datepattern/RangedDateMatcher.java @@ -0,0 +1,14 @@ +package com.baeldung.regexp.datepattern; + +import java.util.regex.Pattern; + +class RangedDateMatcher implements DateMatcher { + + private static final Pattern DATE_PATTERN = Pattern.compile( + "^((19|2[0-9])[0-9]{2})-(0[1-9]|1[012])-(0[1-9]|[12][0-9]|3[01])$"); + + @Override + public boolean matches(String date) { + return DATE_PATTERN.matcher(date).matches(); + } +} diff --git a/core-java/src/main/java/com/baeldung/regexp/datepattern/gregorian/February29thMatcher.java b/core-java/src/main/java/com/baeldung/regexp/datepattern/gregorian/February29thMatcher.java new file mode 100644 index 0000000000..b0243ae48f --- /dev/null +++ b/core-java/src/main/java/com/baeldung/regexp/datepattern/gregorian/February29thMatcher.java @@ -0,0 +1,16 @@ +package com.baeldung.regexp.datepattern.gregorian; + +import com.baeldung.regexp.datepattern.DateMatcher; + +import java.util.regex.Pattern; + +public class February29thMatcher implements DateMatcher { + + private static final Pattern DATE_PATTERN = Pattern.compile( + "^((2000|2400|2800|(19|2[0-9](0[48]|[2468][048]|[13579][26])))-02-29)$"); + + @Override + public boolean matches(String date) { + return DATE_PATTERN.matcher(date).matches(); + } +} diff --git a/core-java/src/main/java/com/baeldung/regexp/datepattern/gregorian/FebruaryGeneralMatcher.java b/core-java/src/main/java/com/baeldung/regexp/datepattern/gregorian/FebruaryGeneralMatcher.java new file mode 100644 index 0000000000..f294348928 --- /dev/null +++ b/core-java/src/main/java/com/baeldung/regexp/datepattern/gregorian/FebruaryGeneralMatcher.java @@ -0,0 +1,16 @@ +package com.baeldung.regexp.datepattern.gregorian; + +import com.baeldung.regexp.datepattern.DateMatcher; + +import java.util.regex.Pattern; + +public class FebruaryGeneralMatcher implements DateMatcher { + + private static final Pattern DATE_PATTERN = Pattern.compile( + "^(((19|2[0-9])[0-9]{2})-02-(0[1-9]|1[0-9]|2[0-8]))$"); + + @Override + public boolean matches(String date) { + return DATE_PATTERN.matcher(date).matches(); + } +} diff --git a/core-java/src/main/java/com/baeldung/regexp/datepattern/gregorian/GregorianDateMatcher.java b/core-java/src/main/java/com/baeldung/regexp/datepattern/gregorian/GregorianDateMatcher.java new file mode 100644 index 0000000000..fc8abdb201 --- /dev/null +++ b/core-java/src/main/java/com/baeldung/regexp/datepattern/gregorian/GregorianDateMatcher.java @@ -0,0 +1,19 @@ +package com.baeldung.regexp.datepattern.gregorian; + +import com.baeldung.regexp.datepattern.DateMatcher; + +import java.util.regex.Pattern; + +class GregorianDateMatcher implements DateMatcher { + + private static final Pattern DATE_PATTERN = Pattern.compile( + "^((2000|2400|2800|(19|2[0-9](0[48]|[2468][048]|[13579][26])))-02-29)$" + + "|^(((19|2[0-9])[0-9]{2})-02-(0[1-9]|1[0-9]|2[0-8]))$" + + "|^(((19|2[0-9])[0-9]{2})-(0[13578]|10|12)-(0[1-9]|[12][0-9]|3[01]))$" + + "|^(((19|2[0-9])[0-9]{2})-(0[469]|11)-(0[1-9]|[12][0-9]|30))$"); + + @Override + public boolean matches(String date) { + return DATE_PATTERN.matcher(date).matches(); + } +} diff --git a/core-java/src/main/java/com/baeldung/regexp/datepattern/gregorian/MonthsOf30DaysMatcher.java b/core-java/src/main/java/com/baeldung/regexp/datepattern/gregorian/MonthsOf30DaysMatcher.java new file mode 100644 index 0000000000..be202081e8 --- /dev/null +++ b/core-java/src/main/java/com/baeldung/regexp/datepattern/gregorian/MonthsOf30DaysMatcher.java @@ -0,0 +1,17 @@ +package com.baeldung.regexp.datepattern.gregorian; + +import com.baeldung.regexp.datepattern.DateMatcher; + +import java.util.regex.Pattern; + +public class MonthsOf30DaysMatcher implements DateMatcher { + + private static final Pattern DATE_PATTERN = Pattern.compile( + "^(((19|2[0-9])[0-9]{2})-(0[469]|11)-(0[1-9]|[12][0-9]|30))$"); + + @Override + public boolean matches(String date) { + return DATE_PATTERN.matcher(date).matches(); + } + +} diff --git a/core-java/src/main/java/com/baeldung/regexp/datepattern/gregorian/MonthsOf31DaysMatcher.java b/core-java/src/main/java/com/baeldung/regexp/datepattern/gregorian/MonthsOf31DaysMatcher.java new file mode 100644 index 0000000000..7f0943991b --- /dev/null +++ b/core-java/src/main/java/com/baeldung/regexp/datepattern/gregorian/MonthsOf31DaysMatcher.java @@ -0,0 +1,17 @@ +package com.baeldung.regexp.datepattern.gregorian; + +import com.baeldung.regexp.datepattern.DateMatcher; + +import java.util.regex.Pattern; + +public class MonthsOf31DaysMatcher implements DateMatcher { + + private static final Pattern DATE_PATTERN = Pattern.compile( + "^(((19|2[0-9])[0-9]{2})-(0[13578]|10|12)-(0[1-9]|[12][0-9]|3[01]))$"); + + @Override + public boolean matches(String date) { + return DATE_PATTERN.matcher(date).matches(); + } + +} diff --git a/core-java/src/test/java/com/baeldung/regexp/datepattern/FormattedDateMatcherUnitTest.java b/core-java/src/test/java/com/baeldung/regexp/datepattern/FormattedDateMatcherUnitTest.java new file mode 100644 index 0000000000..0a9599c3f9 --- /dev/null +++ b/core-java/src/test/java/com/baeldung/regexp/datepattern/FormattedDateMatcherUnitTest.java @@ -0,0 +1,24 @@ +package com.baeldung.regexp.datepattern; + +import org.junit.Assert; +import org.junit.Test; + +public class FormattedDateMatcherUnitTest { + + private DateMatcher matcher = new FormattedDateMatcher(); + + @Test + public void whenUsingFormattedDateMatcher_thenFormatConstraintsSatisfied() { + Assert.assertTrue(matcher.matches("2017-12-31")); + Assert.assertTrue(matcher.matches("2018-01-01")); + Assert.assertTrue(matcher.matches("0000-00-00")); + Assert.assertTrue(matcher.matches("1029-99-72")); + + Assert.assertFalse(matcher.matches("2018-01")); + Assert.assertFalse(matcher.matches("2018-01-01-01")); + Assert.assertFalse(matcher.matches("2018-01-XX")); + Assert.assertFalse(matcher.matches(" 2018-01-01")); + Assert.assertFalse(matcher.matches("2018-01-01 ")); + Assert.assertFalse(matcher.matches("2018/01/01")); + } +} diff --git a/core-java/src/test/java/com/baeldung/regexp/datepattern/RangedDateMatcherUnitTest.java b/core-java/src/test/java/com/baeldung/regexp/datepattern/RangedDateMatcherUnitTest.java new file mode 100644 index 0000000000..abbff83ec1 --- /dev/null +++ b/core-java/src/test/java/com/baeldung/regexp/datepattern/RangedDateMatcherUnitTest.java @@ -0,0 +1,31 @@ +package com.baeldung.regexp.datepattern; + +import org.junit.Assert; +import org.junit.Test; + +public class RangedDateMatcherUnitTest { + + private DateMatcher matcher = new RangedDateMatcher(); + + @Test + public void whenUsingRangedDateMatcher_thenFormatConstraintsSatisfied() { + Assert.assertFalse(matcher.matches("2018-01")); + Assert.assertFalse(matcher.matches("2018-01-01-01")); + Assert.assertFalse(matcher.matches("2018-01-XX")); + Assert.assertFalse(matcher.matches(" 2018-01-01")); + Assert.assertFalse(matcher.matches("2018-01-01 ")); + Assert.assertFalse(matcher.matches("2018/01/01")); + } + + @Test + public void whenUsingRangedDateMatcher_thenRangeConstraintsSatisfied() { + Assert.assertTrue(matcher.matches("1900-01-01")); + Assert.assertTrue(matcher.matches("2018-02-31")); + Assert.assertTrue(matcher.matches("2999-12-31")); + + Assert.assertFalse(matcher.matches("1899-12-31")); + Assert.assertFalse(matcher.matches("2018-05-35")); + Assert.assertFalse(matcher.matches("2018-13-05")); + Assert.assertFalse(matcher.matches("3000-01-01")); + } +} diff --git a/core-java/src/test/java/com/baeldung/regexp/datepattern/gregorian/February29thMatcherUnitTest.java b/core-java/src/test/java/com/baeldung/regexp/datepattern/gregorian/February29thMatcherUnitTest.java new file mode 100644 index 0000000000..67a4276728 --- /dev/null +++ b/core-java/src/test/java/com/baeldung/regexp/datepattern/gregorian/February29thMatcherUnitTest.java @@ -0,0 +1,17 @@ +package com.baeldung.regexp.datepattern.gregorian; + +import com.baeldung.regexp.datepattern.DateMatcher; +import com.baeldung.regexp.datepattern.gregorian.testhelper.GregorianDateTestHelper; +import org.junit.Test; + +public class February29thMatcherUnitTest { + + private DateMatcher matcher = new February29thMatcher(); + + private GregorianDateTestHelper testHelper = new GregorianDateTestHelper(matcher); + + @Test + public void whenYearIsLeap_thenYearHasFebruary29th() { + testHelper.assertFebruary29th(); + } +} diff --git a/core-java/src/test/java/com/baeldung/regexp/datepattern/gregorian/FebruaryGeneralMatcherUnitTest.java b/core-java/src/test/java/com/baeldung/regexp/datepattern/gregorian/FebruaryGeneralMatcherUnitTest.java new file mode 100644 index 0000000000..48ff140620 --- /dev/null +++ b/core-java/src/test/java/com/baeldung/regexp/datepattern/gregorian/FebruaryGeneralMatcherUnitTest.java @@ -0,0 +1,17 @@ +package com.baeldung.regexp.datepattern.gregorian; + +import com.baeldung.regexp.datepattern.DateMatcher; +import com.baeldung.regexp.datepattern.gregorian.testhelper.GregorianDateTestHelper; +import org.junit.Test; + +public class FebruaryGeneralMatcherUnitTest { + + private DateMatcher matcher = new FebruaryGeneralMatcher(); + + private GregorianDateTestHelper testHelper = new GregorianDateTestHelper(matcher); + + @Test + public void whenMonthIsFebruary_thenMonthContainsUpTo28Days() { + testHelper.assertFebruaryGeneralDates(); + } +} \ No newline at end of file diff --git a/core-java/src/test/java/com/baeldung/regexp/datepattern/gregorian/GregorianDateMatcherUnitTest.java b/core-java/src/test/java/com/baeldung/regexp/datepattern/gregorian/GregorianDateMatcherUnitTest.java new file mode 100644 index 0000000000..e6e896a09c --- /dev/null +++ b/core-java/src/test/java/com/baeldung/regexp/datepattern/gregorian/GregorianDateMatcherUnitTest.java @@ -0,0 +1,42 @@ +package com.baeldung.regexp.datepattern.gregorian; + +import com.baeldung.regexp.datepattern.DateMatcher; +import com.baeldung.regexp.datepattern.gregorian.testhelper.GregorianDateTestHelper; +import org.junit.Test; + +public class GregorianDateMatcherUnitTest { + + private DateMatcher matcher = new GregorianDateMatcher(); + + private GregorianDateTestHelper testHelper = new GregorianDateTestHelper(matcher); + + @Test + public void whenUsingGregorianDateMatcher_thenFormatConstraintsSatisfied() { + testHelper.assertFormat(); + } + + @Test + public void whenUsingGregorianDateMatcher_thenRangeConstraintsSatisfied() { + testHelper.assertRange(); + } + + @Test + public void whenYearIsLeap_thenFebruaryHas29Days() { + testHelper.assertFebruary29th(); + } + + @Test + public void whenMonthIsFebruary_thenMonthContainsUpTo28Days() { + testHelper.assertFebruaryGeneralDates(); + } + + @Test + public void whenMonthIsShort_thenMonthContainsUpTo30Days() { + testHelper.assertMonthsOf30Days(); + } + + @Test + public void whenMonthIsLong_thenMonthContainsUpTo31Days() { + testHelper.assertMonthsOf31Dates(); + } +} diff --git a/core-java/src/test/java/com/baeldung/regexp/datepattern/gregorian/MonthsOf30DaysMatcherUnitTest.java b/core-java/src/test/java/com/baeldung/regexp/datepattern/gregorian/MonthsOf30DaysMatcherUnitTest.java new file mode 100644 index 0000000000..d1ce4a6d57 --- /dev/null +++ b/core-java/src/test/java/com/baeldung/regexp/datepattern/gregorian/MonthsOf30DaysMatcherUnitTest.java @@ -0,0 +1,17 @@ +package com.baeldung.regexp.datepattern.gregorian; + +import com.baeldung.regexp.datepattern.DateMatcher; +import com.baeldung.regexp.datepattern.gregorian.testhelper.GregorianDateTestHelper; +import org.junit.Test; + +public class MonthsOf30DaysMatcherUnitTest { + + private DateMatcher matcher = new MonthsOf30DaysMatcher(); + + private GregorianDateTestHelper testHelper = new GregorianDateTestHelper(matcher); + + @Test + public void whenMonthIsShort_thenMonthContainsUpTo30Days() { + testHelper.assertMonthsOf30Days(); + } +} \ No newline at end of file diff --git a/core-java/src/test/java/com/baeldung/regexp/datepattern/gregorian/MonthsOf31DaysMatcherUnitTest.java b/core-java/src/test/java/com/baeldung/regexp/datepattern/gregorian/MonthsOf31DaysMatcherUnitTest.java new file mode 100644 index 0000000000..338c8de30c --- /dev/null +++ b/core-java/src/test/java/com/baeldung/regexp/datepattern/gregorian/MonthsOf31DaysMatcherUnitTest.java @@ -0,0 +1,17 @@ +package com.baeldung.regexp.datepattern.gregorian; + +import com.baeldung.regexp.datepattern.DateMatcher; +import com.baeldung.regexp.datepattern.gregorian.testhelper.GregorianDateTestHelper; +import org.junit.Test; + +public class MonthsOf31DaysMatcherUnitTest { + + private DateMatcher matcher = new MonthsOf31DaysMatcher(); + + private GregorianDateTestHelper testHelper = new GregorianDateTestHelper(matcher); + + @Test + public void whenMonthIsLong_thenMonthContainsUpTo31Days() { + testHelper.assertMonthsOf31Dates(); + } +} \ No newline at end of file diff --git a/core-java/src/test/java/com/baeldung/regexp/datepattern/gregorian/testhelper/GregorianDateTestHelper.java b/core-java/src/test/java/com/baeldung/regexp/datepattern/gregorian/testhelper/GregorianDateTestHelper.java new file mode 100644 index 0000000000..6429e4fe2d --- /dev/null +++ b/core-java/src/test/java/com/baeldung/regexp/datepattern/gregorian/testhelper/GregorianDateTestHelper.java @@ -0,0 +1,102 @@ +package com.baeldung.regexp.datepattern.gregorian.testhelper; + +import com.baeldung.regexp.datepattern.DateMatcher; +import org.junit.Assert; + +public class GregorianDateTestHelper { + + private final DateMatcher matcher; + + public GregorianDateTestHelper(DateMatcher matcher) { + this.matcher = matcher; + } + + public void assertFormat() { + Assert.assertTrue(matcher.matches("2017-12-31")); + Assert.assertTrue(matcher.matches("2018-01-01")); + + Assert.assertFalse(matcher.matches("2018-02")); + Assert.assertFalse(matcher.matches("2018-02-01-01")); + Assert.assertFalse(matcher.matches("2018-02-XX")); + Assert.assertFalse(matcher.matches(" 2018-02-01")); + Assert.assertFalse(matcher.matches("2018-02-01 ")); + Assert.assertFalse(matcher.matches("2020/02/28")); + Assert.assertFalse(matcher.matches("2020.02.29")); + } + + public void assertRange() { + Assert.assertTrue(matcher.matches("1900-01-01")); + Assert.assertTrue(matcher.matches("2205-05-25")); + Assert.assertTrue(matcher.matches("2999-12-31")); + + Assert.assertFalse(matcher.matches("1899-12-31")); + Assert.assertFalse(matcher.matches("2018-05-35")); + Assert.assertFalse(matcher.matches("2018-13-05")); + Assert.assertFalse(matcher.matches("3000-01-01")); + Assert.assertFalse(matcher.matches("3200-02-29")); + } + + public void assertFebruary29th() { + Assert.assertTrue(matcher.matches("2000-02-29")); + Assert.assertTrue(matcher.matches("2400-02-29")); + Assert.assertTrue(matcher.matches("2800-02-29")); + Assert.assertTrue(matcher.matches("2020-02-29")); + Assert.assertTrue(matcher.matches("2024-02-29")); + Assert.assertTrue(matcher.matches("2028-02-29")); + + Assert.assertFalse(matcher.matches("2017-02-29")); + Assert.assertFalse(matcher.matches("2018-02-29")); + Assert.assertFalse(matcher.matches("2019-02-29")); + Assert.assertFalse(matcher.matches("2100-02-29")); + Assert.assertFalse(matcher.matches("2200-02-29")); + Assert.assertFalse(matcher.matches("2300-02-29")); + } + + public void assertFebruaryGeneralDates() { + Assert.assertTrue(matcher.matches("2018-02-01")); + Assert.assertTrue(matcher.matches("2019-02-13")); + Assert.assertTrue(matcher.matches("2020-02-25")); + + Assert.assertFalse(matcher.matches("2000-02-30")); + Assert.assertFalse(matcher.matches("2400-02-62")); + Assert.assertFalse(matcher.matches("2420-02-94")); + } + + public void assertMonthsOf30Days() { + Assert.assertTrue(matcher.matches("2018-04-30")); + Assert.assertTrue(matcher.matches("2019-06-30")); + Assert.assertTrue(matcher.matches("2020-09-30")); + Assert.assertTrue(matcher.matches("2021-11-30")); + + Assert.assertTrue(matcher.matches("2022-04-02")); + Assert.assertTrue(matcher.matches("2023-06-14")); + Assert.assertTrue(matcher.matches("2024-09-26")); + + Assert.assertFalse(matcher.matches("2018-04-31")); + Assert.assertFalse(matcher.matches("2019-06-31")); + Assert.assertFalse(matcher.matches("2020-09-31")); + Assert.assertFalse(matcher.matches("2021-11-31")); + + Assert.assertFalse(matcher.matches("2022-04-32")); + Assert.assertFalse(matcher.matches("2023-06-64")); + Assert.assertFalse(matcher.matches("2024-09-96")); + } + + public void assertMonthsOf31Dates() { + Assert.assertTrue(matcher.matches("2018-01-31")); + Assert.assertTrue(matcher.matches("2019-03-31")); + Assert.assertTrue(matcher.matches("2020-05-31")); + Assert.assertTrue(matcher.matches("2021-07-31")); + Assert.assertTrue(matcher.matches("2022-08-31")); + Assert.assertTrue(matcher.matches("2023-10-31")); + Assert.assertTrue(matcher.matches("2024-12-31")); + + Assert.assertTrue(matcher.matches("2025-01-03")); + Assert.assertTrue(matcher.matches("2026-03-15")); + Assert.assertTrue(matcher.matches("2027-05-27")); + + Assert.assertFalse(matcher.matches("2018-01-32")); + Assert.assertFalse(matcher.matches("2019-03-64")); + Assert.assertFalse(matcher.matches("2020-05-96")); + } +}