Validation du format de date de regex sur Java

Je me demande simplement s’il existe un moyen (peut-être avec regex) de valider qu’une entrée sur une application de bureau Java est exactement une chaîne formulée comme suit: “AAAA-MM-JJ”.

J’ai cherché mais sans succès.

Je vous remercie

Utilisez l’expression régulière suivante:

^\d{4}-\d{2}-\d{2}$ 

un péché

 if (str.matches("\\d{4}-\\d{2}-\\d{2}")) { ... } 

Avec la méthode des matches , les ancres ^ et $ (début et fin de chaîne, respectivement) sont implicitement présentes.

Vous avez besoin de plus qu’une regex régulière, par exemple “9999-99-00” n’est pas une date valide. Il existe une classe SimpleDateFormat conçue pour cela. Plus lourd, mais plus complet.

par exemple

 SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd"); boolean isValidDate(ssortingng input) { try { format.parse(input); return true; } catch(ParseException e){ return false; } } 

Malheureusement, SimpleDateFormat est à la fois lourd et non thread-safe.

Mettre tous ensemble:

  • REGEX ne valide pas les valeurs (comme “2010-19-19”)
  • SimpleDateFormat ne vérifie pas le format (“2010-1-2”, “1-0002-003” sont acceptés)

il faut utiliser les deux pour valider le format et la valeur:

 public static boolean isValid(Ssortingng text) { if (text == null || !text.matches("\\d{4}-[01]\\d-[0-3]\\d")) return false; SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd"); df.setLenient(false); try { df.parse(text); return true; } catch (ParseException ex) { return false; } } 


Un ThreadLocal peut être utilisé pour éviter la création d’un nouveau SimpleDateFormat pour chaque appel.
Il est nécessaire dans un contexte multithread car le SimpleDateFormat n’est pas thread-safe:

 private static final ThreadLocal format = new ThreadLocal() { @Override protected SimpleDateFormat initialValue() { SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd"); df.setLenient(false); System.out.println("created"); return df; } }; public static boolean isValid(Ssortingng text) { if (text == null || !text.matches("\\d{4}-[01]\\d-[0-3]\\d")) return false; try { format.get().parse(text); return true; } catch (ParseException ex) { return false; } } 

(même chose pour un Matcher, qui n’est pas non plus thread-safe)

Cela le fera regex: "^((19|20)\\d\\d)-(0?[1-9]|1[012])-(0?[1-9]|[12][0-9]|3[01])$" Cela prendra en charge les formats valides et les dates valides. Il ne validera pas les jours corrects du mois, c’est-à-dire l’année bissextile.

 Ssortingng regex = "^((19|20)\\d\\d)-(0?[1-9]|1[012])-(0?[1-9]|[12][0-9]|3[01])$"; Assert.assertTrue("Date: matched.", Pattern.matches(regex, "2011-1-1")); Assert.assertFalse("Date (month): not matched.", Pattern.matches(regex, "2011-13-1")); 

Bonne chance!

J’irais avec un regex simple qui vérifiera que les jours n’ont pas plus de 31 jours et mois pas plus de 12. Quelque chose comme:

 (0?[1-9]|[12][0-9]|3[01])-(0?[1-9]|1[012])-((18|19|20|21)\\d\\d) 

C’est le format “jj-MM-aaaa”. Vous pouvez l’ajuster à vos besoins (par exemple, enlevez le? Pour rendre le 0 principal requirejs – maintenant facultatif), puis utilisez une logique personnalisée pour réduire les règles spécifiques telles que les années bissextiles en février nombre de jours et autres. mois nombre de jours cas. Voir le code DateChecker ci-dessous.

Je choisis cette approche depuis que j’ai testé que c’est la meilleure lorsque la performance est prise en compte. J’ai vérifié cette (1ère) approche par rapport à la 2ème approche de validation d’une date par rapport à une regex qui prend en compte les autres cas d’utilisation, et la 3ème approche d’utiliser la même regex simple en combinaison avec SimpleDateFormat.parse (date).
La 1ère approche était 4 fois plus rapide que la 2ème approche et 8 fois plus rapide que la 3ème approche. Voir le vérificateur de date autonome et la classe principale de testeur de performance en bas. Une des choses que je n’ai pas cochées est l’approche du temps joda. (La bibliothèque date / heure la plus efficace).

Code de vérification de date:

 class DateChecker { private Matcher matcher; private Pattern pattern; public DateChecker(Ssortingng regex) { pattern = Pattern.comstack(regex); } /** * Checks if the date format is a valid. * Uses the regex pattern to match the date first. * Than additionally checks are performed on the boundaries of the days taken the month into account (leap years are covered). * * @param date the date that needs to be checked. * @return if the date is of an valid format or not. */ public boolean check(final Ssortingng date) { matcher = pattern.matcher(date); if (matcher.matches()) { matcher.reset(); if (matcher.find()) { int day = Integer.parseInt(matcher.group(1)); int month = Integer.parseInt(matcher.group(2)); int year = Integer.parseInt(matcher.group(3)); switch (month) { case 1: case 3: case 5: case 7: case 8: case 10: case 12: return day < 32; case 4: case 6: case 9: case 11: return day < 31; case 2: int modulo100 = year % 100; //http://science.howstuffworks.com/science-vs-myth/everyday-myths/question50.htm if ((modulo100 == 0 && year % 400 == 0) || (modulo100 != 0 && year % LEAP_STEP == 0)) { //its a leap year return day < 30; } else { return day < 29; } default: break; } } } return false; } public String getRegex() { return pattern.pattern(); } } 

Vérification / test de date et test de performance:

 import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.List; import java.util.regex.Matcher; import java.util.regex.Pattern; public class Tester { private static final Ssortingng[] validDateSsortingngs = new Ssortingng[]{ "1-1-2000", //leading 0s for day and month optional "01-1-2000", //leading 0 for month only optional "1-01-2000", //leading 0 for day only optional "01-01-1800", //first accepted date "31-12-2199", //last accepted date "31-01-2000", //January has 31 days "31-03-2000", //March has 31 days "31-05-2000", //May has 31 days "31-07-2000", //July has 31 days "31-08-2000", //August has 31 days "31-10-2000", //October has 31 days "31-12-2000", //December has 31 days "30-04-2000", //April has 30 days "30-06-2000", //June has 30 days "30-09-2000", //September has 30 days "30-11-2000", //November has 30 days }; private static final Ssortingng[] invalidDateSsortingngs = new Ssortingng[]{ "00-01-2000", //there is no 0-th day "01-00-2000", //there is no 0-th month "31-12-1799", //out of lower boundary date "01-01-2200", //out of high boundary date "32-01-2000", //January doesn't have 32 days "32-03-2000", //March doesn't have 32 days "32-05-2000", //May doesn't have 32 days "32-07-2000", //July doesn't have 32 days "32-08-2000", //August doesn't have 32 days "32-10-2000", //October doesn't have 32 days "32-12-2000", //December doesn't have 32 days "31-04-2000", //April doesn't have 31 days "31-06-2000", //June doesn't have 31 days "31-09-2000", //September doesn't have 31 days "31-11-2000", //November doesn't have 31 days "001-02-2000", //SimpleDateFormat valid date (day with leading 0s) even with lenient set to false "1-0002-2000", //SimpleDateFormat valid date (month with leading 0s) even with lenient set to false "01-02-0003", //SimpleDateFormat valid date (year with leading 0s) even with lenient set to false "01.01-2000", //. invalid separator between day and month "01-01.2000", //. invalid separator between month and year "01/01-2000", /// invalid separator between day and month "01-01/2000", /// invalid separator between month and year "01_01-2000", //_ invalid separator between day and month "01-01_2000", //_ invalid separator between month and year "01-01-2000-12345", //only whole ssortingng should be matched "01-13-2000", //month bigger than 13 }; /** * These constants will be used to generate the valid and invalid boundary dates for the leap years. (For no leap year, Feb. 28 valid and Feb. 29 invalid; for a leap year Feb. 29 valid and Feb. 30 invalid) */ private static final int LEAP_STEP = 4; private static final int YEAR_START = 1800; private static final int YEAR_END = 2199; /** * This date regex will find matches for valid dates between 1800 and 2199 in the format of "dd-MM-yyyy". * The leading 0 is optional. */ private static final Ssortingng DATE_REGEX = "((0?[1-9]|[12][0-9]|3[01])-(0?[13578]|1[02])-(18|19|20|21)[0-9]{2})|((0?[1-9]|[12][0-9]|30)-(0?[469]|11)-(18|19|20|21)[0-9]{2})|((0?[1-9]|1[0-9]|2[0-8])-(0?2)-(18|19|20|21)[0-9]{2})|(29-(0?2)-(((18|19|20|21)(04|08|[2468][048]|[13579][26]))|2000))"; /** * This date regex is similar to the first one, but with the difference of matching only the whole ssortingng. So "01-01-2000-12345" won't pass with a match. * Keep in mind that Ssortingng.matches sortinges to match only the whole ssortingng. */ private static final Ssortingng DATE_REGEX_ONLY_WHOLE_STRING = "^" + DATE_REGEX + "$"; /** * The simple regex (without checking for 31 day months and leap years): */ private static final Ssortingng DATE_REGEX_SIMPLE = "(0?[1-9]|[12][0-9]|3[01])-(0?[1-9]|1[012])-((18|19|20|21)\\d\\d)"; /** * This date regex is similar to the first one, but with the difference of matching only the whole ssortingng. So "01-01-2000-12345" won't pass with a match. */ private static final Ssortingng DATE_REGEX_SIMPLE_ONLY_WHOLE_STRING = "^" + DATE_REGEX_SIMPLE + "$"; private static final SimpleDateFormat SDF = new SimpleDateFormat("dd-MM-yyyy"); static { SDF.setLenient(false); } private static final DateChecker dateValidatorSimple = new DateChecker(DATE_REGEX_SIMPLE); private static final DateChecker dateValidatorSimpleOnlyWholeSsortingng = new DateChecker(DATE_REGEX_SIMPLE_ONLY_WHOLE_STRING); /** * @param args */ public static void main(Ssortingng[] args) { DateTimeStatistics dateTimeStatistics = new DateTimeStatistics(); boolean shouldMatch = true; for (int i = 0; i < validDateStrings.length; i++) { String validDate = validDateStrings[i]; matchAssertAndPopulateTimes( dateTimeStatistics, shouldMatch, validDate); } shouldMatch = false; for (int i = 0; i < invalidDateStrings.length; i++) { String invalidDate = invalidDateStrings[i]; matchAssertAndPopulateTimes(dateTimeStatistics, shouldMatch, invalidDate); } for (int year = YEAR_START; year < (YEAR_END + 1); year++) { FebruaryBoundaryDates februaryBoundaryDates = createValidAndInvalidFebruaryBoundaryDateStringsFromYear(year); shouldMatch = true; matchAssertAndPopulateTimes(dateTimeStatistics, shouldMatch, februaryBoundaryDates.getValidFebruaryBoundaryDateString()); shouldMatch = false; matchAssertAndPopulateTimes(dateTimeStatistics, shouldMatch, februaryBoundaryDates.getInvalidFebruaryBoundaryDateString()); } dateTimeStatistics.calculateAvarageTimesAndPrint(); } private static void matchAssertAndPopulateTimes( DateTimeStatistics dateTimeStatistics, boolean shouldMatch, String date) { dateTimeStatistics.addDate(date); matchAndPopulateTimeToMatch(date, DATE_REGEX, shouldMatch, dateTimeStatistics.getTimesTakenWithDateRegex()); matchAndPopulateTimeToMatch(date, DATE_REGEX_ONLY_WHOLE_STRING, shouldMatch, dateTimeStatistics.getTimesTakenWithDateRegexOnlyWholeString()); boolean matchesSimpleDateFormat = matchWithSimpleDateFormatAndPopulateTimeToMatchAndReturnMatches(date, dateTimeStatistics.getTimesTakenWithSimpleDateFormatParse()); matchAndPopulateTimeToMatchAndReturnMatchesAndCheck( dateTimeStatistics.getTimesTakenWithDateRegexSimple(), shouldMatch, date, matchesSimpleDateFormat, DATE_REGEX_SIMPLE); matchAndPopulateTimeToMatchAndReturnMatchesAndCheck( dateTimeStatistics.getTimesTakenWithDateRegexSimpleOnlyWholeString(), shouldMatch, date, matchesSimpleDateFormat, DATE_REGEX_SIMPLE_ONLY_WHOLE_STRING); matchAndPopulateTimeToMatch(date, dateValidatorSimple, shouldMatch, dateTimeStatistics.getTimesTakenWithdateValidatorSimple()); matchAndPopulateTimeToMatch(date, dateValidatorSimpleOnlyWholeString, shouldMatch, dateTimeStatistics.getTimesTakenWithdateValidatorSimpleOnlyWholeString()); } private static void matchAndPopulateTimeToMatchAndReturnMatchesAndCheck( List times, boolean shouldMatch, Ssortingng date, boolean matchesSimpleDateFormat, Ssortingng regex) { boolean matchesFromRegex = matchAndPopulateTimeToMatchAndReturnMatches(date, regex, times); assert !((matchesSimpleDateFormat && matchesFromRegex) ^ shouldMatch) : "Parsing with SimpleDateFormat and date:" + date + "\nregex:" + regex + "\nshouldMatch:" + shouldMatch; } private static void matchAndPopulateTimeToMatch(Ssortingng date, Ssortingng regex, boolean shouldMatch, List times) { boolean matches = matchAndPopulateTimeToMatchAndReturnMatches(date, regex, times); assert !(matches ^ shouldMatch) : "date:" + date + "\nregex:" + regex + "\nshouldMatch:" + shouldMatch; } private static void matchAndPopulateTimeToMatch(Ssortingng date, DateChecker dateValidator, boolean shouldMatch, List times) { long timestampStart; long timestampEnd; boolean matches; timestampStart = System.nanoTime(); matches = dateValidator.check(date); timestampEnd = System.nanoTime(); times.add(timestampEnd - timestampStart); assert !(matches ^ shouldMatch) : "date:" + date + "\ndateValidator with regex:" + dateValidator.getRegex() + "\nshouldMatch:" + shouldMatch; } private static boolean matchAndPopulateTimeToMatchAndReturnMatches(Ssortingng date, Ssortingng regex, List times) { long timestampStart; long timestampEnd; boolean matches; timestampStart = System.nanoTime(); matches = date.matches(regex); timestampEnd = System.nanoTime(); times.add(timestampEnd - timestampStart); return matches; } private static boolean matchWithSimpleDateFormatAndPopulateTimeToMatchAndReturnMatches(Ssortingng date, List times) { long timestampStart; long timestampEnd; boolean matches = true; timestampStart = System.nanoTime(); try { SDF.parse(date); } catch (ParseException e) { matches = false; } finally { timestampEnd = System.nanoTime(); times.add(timestampEnd - timestampStart); } return matches; } private static FebruaryBoundaryDates createValidAndInvalidFebruaryBoundaryDateSsortingngsFromYear(int year) { FebruaryBoundaryDates februaryBoundaryDates; int modulo100 = year % 100; //http://science.howstuffworks.com/science-vs-myth/everyday-myths/question50.htm if ((modulo100 == 0 && year % 400 == 0) || (modulo100 != 0 && year % LEAP_STEP == 0)) { februaryBoundaryDates = new FebruaryBoundaryDates( createFebruaryDateFromDayAndYear(29, year), createFebruaryDateFromDayAndYear(30, year) ); } else { februaryBoundaryDates = new FebruaryBoundaryDates( createFebruaryDateFromDayAndYear(28, year), createFebruaryDateFromDayAndYear(29, year) ); } return februaryBoundaryDates; } private static Ssortingng createFebruaryDateFromDayAndYear(int day, int year) { return Ssortingng.format("%d-02-%d", day, year); } static class FebruaryBoundaryDates { private Ssortingng validFebruaryBoundaryDateSsortingng; Ssortingng invalidFebruaryBoundaryDateSsortingng; public FebruaryBoundaryDates(Ssortingng validFebruaryBoundaryDateSsortingng, Ssortingng invalidFebruaryBoundaryDateSsortingng) { super(); this.validFebruaryBoundaryDateSsortingng = validFebruaryBoundaryDateSsortingng; this.invalidFebruaryBoundaryDateSsortingng = invalidFebruaryBoundaryDateSsortingng; } public Ssortingng getValidFebruaryBoundaryDateSsortingng() { return validFebruaryBoundaryDateSsortingng; } public void setValidFebruaryBoundaryDateSsortingng( Ssortingng validFebruaryBoundaryDateSsortingng) { this.validFebruaryBoundaryDateSsortingng = validFebruaryBoundaryDateSsortingng; } public Ssortingng getInvalidFebruaryBoundaryDateSsortingng() { return invalidFebruaryBoundaryDateSsortingng; } public void setInvalidFebruaryBoundaryDateSsortingng( Ssortingng invalidFebruaryBoundaryDateSsortingng) { this.invalidFebruaryBoundaryDateSsortingng = invalidFebruaryBoundaryDateSsortingng; } } static class DateTimeStatistics { private List dates = new ArrayList(); private List timesTakenWithDateRegex = new ArrayList(); private List timesTakenWithDateRegexOnlyWholeSsortingng = new ArrayList(); private List timesTakenWithDateRegexSimple = new ArrayList(); private List timesTakenWithDateRegexSimpleOnlyWholeSsortingng = new ArrayList(); private List timesTakenWithSimpleDateFormatParse = new ArrayList(); private List timesTakenWithdateValidatorSimple = new ArrayList(); private List timesTakenWithdateValidatorSimpleOnlyWholeSsortingng = new ArrayList(); public List getDates() { return dates; } public List getTimesTakenWithDateRegex() { return timesTakenWithDateRegex; } public List getTimesTakenWithDateRegexOnlyWholeSsortingng() { return timesTakenWithDateRegexOnlyWholeSsortingng; } public List getTimesTakenWithDateRegexSimple() { return timesTakenWithDateRegexSimple; } public List getTimesTakenWithDateRegexSimpleOnlyWholeSsortingng() { return timesTakenWithDateRegexSimpleOnlyWholeSsortingng; } public List getTimesTakenWithSimpleDateFormatParse() { return timesTakenWithSimpleDateFormatParse; } public List getTimesTakenWithdateValidatorSimple() { return timesTakenWithdateValidatorSimple; } public List getTimesTakenWithdateValidatorSimpleOnlyWholeSsortingng() { return timesTakenWithdateValidatorSimpleOnlyWholeSsortingng; } public void addDate(Ssortingng date) { dates.add(date); } public void addTimesTakenWithDateRegex(long time) { timesTakenWithDateRegex.add(time); } public void addTimesTakenWithDateRegexOnlyWholeSsortingng(long time) { timesTakenWithDateRegexOnlyWholeSsortingng.add(time); } public void addTimesTakenWithDateRegexSimple(long time) { timesTakenWithDateRegexSimple.add(time); } public void addTimesTakenWithDateRegexSimpleOnlyWholeSsortingng(long time) { timesTakenWithDateRegexSimpleOnlyWholeSsortingng.add(time); } public void addTimesTakenWithSimpleDateFormatParse(long time) { timesTakenWithSimpleDateFormatParse.add(time); } public void addTimesTakenWithdateValidatorSimple(long time) { timesTakenWithdateValidatorSimple.add(time); } public void addTimesTakenWithdateValidatorSimpleOnlyWholeSsortingng(long time) { timesTakenWithdateValidatorSimpleOnlyWholeSsortingng.add(time); } private void calculateAvarageTimesAndPrint() { long[] sumOfTimes = new long[7]; int timesSize = timesTakenWithDateRegex.size(); for (int i = 0; i < timesSize; i++) { sumOfTimes[0] += timesTakenWithDateRegex.get(i); sumOfTimes[1] += timesTakenWithDateRegexOnlyWholeString.get(i); sumOfTimes[2] += timesTakenWithDateRegexSimple.get(i); sumOfTimes[3] += timesTakenWithDateRegexSimpleOnlyWholeString.get(i); sumOfTimes[4] += timesTakenWithSimpleDateFormatParse.get(i); sumOfTimes[5] += timesTakenWithdateValidatorSimple.get(i); sumOfTimes[6] += timesTakenWithdateValidatorSimpleOnlyWholeString.get(i); } System.out.println("AVG from timesTakenWithDateRegex (in nanoseconds):" + (double) sumOfTimes[0] / timesSize); System.out.println("AVG from timesTakenWithDateRegexOnlyWholeString (in nanoseconds):" + (double) sumOfTimes[1] / timesSize); System.out.println("AVG from timesTakenWithDateRegexSimple (in nanoseconds):" + (double) sumOfTimes[2] / timesSize); System.out.println("AVG from timesTakenWithDateRegexSimpleOnlyWholeString (in nanoseconds):" + (double) sumOfTimes[3] / timesSize); System.out.println("AVG from timesTakenWithSimpleDateFormatParse (in nanoseconds):" + (double) sumOfTimes[4] / timesSize); System.out.println("AVG from timesTakenWithDateRegexSimple + timesTakenWithSimpleDateFormatParse (in nanoseconds):" + (double) (sumOfTimes[2] + sumOfTimes[4]) / timesSize); System.out.println("AVG from timesTakenWithDateRegexSimpleOnlyWholeString + timesTakenWithSimpleDateFormatParse (in nanoseconds):" + (double) (sumOfTimes[3] + sumOfTimes[4]) / timesSize); System.out.println("AVG from timesTakenWithdateValidatorSimple (in nanoseconds):" + (double) sumOfTimes[5] / timesSize); System.out.println("AVG from timesTakenWithdateValidatorSimpleOnlyWholeString (in nanoseconds):" + (double) sumOfTimes[6] / timesSize); } } static class DateChecker { private Matcher matcher; private Pattern pattern; public DateChecker(String regex) { pattern = Pattern.compile(regex); } /** * Checks if the date format is a valid. * Uses the regex pattern to match the date first. * Than additionally checks are performed on the boundaries of the days taken the month into account (leap years are covered). * * @param date the date that needs to be checked. * @return if the date is of an valid format or not. */ public boolean check(final String date) { matcher = pattern.matcher(date); if (matcher.matches()) { matcher.reset(); if (matcher.find()) { int day = Integer.parseInt(matcher.group(1)); int month = Integer.parseInt(matcher.group(2)); int year = Integer.parseInt(matcher.group(3)); switch (month) { case 1: case 3: case 5: case 7: case 8: case 10: case 12: return day < 32; case 4: case 6: case 9: case 11: return day < 31; case 2: int modulo100 = year % 100; //http://science.howstuffworks.com/science-vs-myth/everyday-myths/question50.htm if ((modulo100 == 0 && year % 400 == 0) || (modulo100 != 0 && year % LEAP_STEP == 0)) { //its a leap year return day < 30; } else { return day < 29; } default: break; } } } return false; } public String getRegex() { return pattern.pattern(); } } } 

Quelques notes utiles:
- pour activer les assertions (vérifications d'assert), vous devez utiliser l'argument -ea lors de l'exécution du testeur. (Dans eclipse, cela se fait en éditant la configuration Run / Debug -> onglet Arguments -> Arguments VM -> insérer "-ea"
- le regex ci-dessus est limité aux années 1800 à 2199
- Vous n'avez pas besoin d'utiliser ^ au début et $ à la fin pour correspondre uniquement à la chaîne de date entière. Ssortingng.matches s'en charge.
- Assurez-vous de vérifier les cas valides et non valides et modifiez-les selon les règles que vous avez.
- la version "seule chaîne complète" de chaque expression régulière donne la même vitesse que la version "normale" (celle sans ^ et $). Si vous constatez des différences de performances, c'est parce que java "s'habitue" au traitement des mêmes instructions pour que le temps diminue. Si vous changez les lignes où la version "normal" et la version "uniquement la chaîne entière" sont exécutées, vous verrez que cela a été prouvé.

J'espère que cela aide quelqu'un!
À votre santé,
Despote

java.time

La méthode appropriée (et simple) pour valider la date / heure à l’aide de Java 8+ consiste à utiliser la classe java.time.format.DateTimeFormatter . Utiliser une regex pour la validation n’est pas vraiment idéal pour les dates. Pour l’exemple dans cette question:

 DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd"); try { LocalDate date = formatter.parse(text, LocalDate::from); } catch (DateTimeParseException e) { // Thrown if text could not be parsed in the specified format } 

Ce code va parsingr le texte, valider qu’il s’agit d’une date valide et renvoyer également la date en tant qu’object LocalDate . Notez que la classe DateTimeFormatter possède un certain nombre de formats de date prédéfinis statiques correspondant aux normes ISO si votre cas d’utilisation correspond à l’un d’entre eux.

Construisez un SimpleDateFormat avec le masque, puis appelez: SimpleDateFormat.parse (Ssortingng s, ParsePosition p)

Pour un contrôle précis , considérez un InputVerifier utilisant le SimpleDateFormat("YYYY-MM-dd") proposé par Steve B.

Si vous voulez une expression rationnelle simple, ce ne sera pas exact. https://www.freeformatter.com/java-regex-tester.html#ad-output offre un outil pour tester votre regex Java. De plus, en bas, vous pouvez trouver des suggestions pour valider une date.

Format de date ISO (aaaa-mm-jj):

 ^[0-9]{4}-(((0[13578]|(10|12))-(0[1-9]|[1-2][0-9]|3[0-1]))|(02-(0[1-9]|[1-2][0-9]))|((0[469]|11)-(0[1-9]|[1-2][0-9]|30)))$ 

Format de date ISO (aaaa-mm-jj) avec les séparateurs ‘-‘ ou ‘/’ ou ‘.’ ou ‘ ‘. Force l’utilisation du même séparateur à la date.

 ^[0-9]{4}([- /.])(((0[13578]|(10|12))\1(0[1-9]|[1-2][0-9]|3[0-1]))|(02\1(0[1-9]|[1-2][0-9]))|((0[469]|11)\1(0[1-9]|[1-2][0-9]|30)))$ 

Format de date des États-Unis (mm / jj / aaaa)

 ^(((0[13578]|(10|12))/(0[1-9]|[1-2][0-9]|3[0-1]))|(02/(0[1-9]|[1-2][0-9]))|((0[469]|11)/(0[1-9]|[1-2][0-9]|30)))/[0-9]{4}$ 

Heures et minutes, format 24 heures (HH: MM):

 ^(20|21|22|23|[01]\d|\d)((:[0-5]\d){1,2})$ 

Bonne chance

Le code ajouté ci-dessous fonctionne pour moi si vous utilisez le modèle dd-MM-yyyy.

 public boolean isValidDate(Ssortingng date) { boolean check; Ssortingng date1 = "^(0?[1-9]|[12][0-9]|3[01])-(0?[1-9]|1[012])-([12][0-9]{3})$"; check = date.matches(date1); return check; }