Comment la santé mentale vérifier une date en Java
Je trouve curieux que le moyen le plus évident de créer Date
objets en Java est obsolète et qu'il semble avoir été "remplacé" avec un pas si évident de l'utiliser clémente calendrier.
Comment vérifiez-vous qu'un jour, étant donné que d'une combinaison du jour, du mois et de l'année, est une date valide?
Par exemple, 2008-02-31 (comme dans aaaa-mm-jj) serait une date non valide.
- Pour n'importe qui avec une question similaire, veuillez préciser si vous avez besoin de non-calendrier Grégorien soutien.
- Je suis entièrement d'accord avec vous, la fusion semble être la meilleure façon d'aller.
Vous devez vous connecter pour publier un commentaire.
La façon actuelle est d'utiliser le calendrier de la classe. Il a la setLenient méthode qui permettra de valider la date et de le jeter et d'exception si elle est hors de portée, comme dans votre exemple.
Oublié d'ajouter:
Si vous obtenez un calendrier de l'instance et réglez l'heure à l'aide de votre date, c'est comment vous obtenez la validation.
java.util.Date
,java.util.Calendar
, etjava.text.SimpleDateFormat
sont maintenant héritage, supplantée par la java.temps les classes intégré dans Java 8 et les versions ultérieures. Voir Tutoriel par Oracle.Clé est df.setLenient(false);. C'est plus que suffisant pour les cas simples. Si vous êtes à la recherche d'un plus robuste (j'en doute) et/ou de dégagement des bibliothèques comme joda-time puis regarder la répondre par l'utilisateur "tardate"
setLenient
ou pas:SimpleDateFormat
toujours analyser jusqu'à ce que le modèle est adapté et d'ignorer le reste de la chaîne, ainsi vous obtenez201
de l'année.java.util.Date
,java.util.Calendar
, etjava.text.SimpleDateFormat
sont maintenant héritage, supplantée par la java.temps les classes intégré dans Java 8 et les versions ultérieures. Voir Tutoriel par Oracle.Comme indiqué par @Maglob, l'approche de base est de tester la conversion de la chaîne de date à l'aide de SimpleDateFormat.analyser. Qui va attraper invalide jour/mois combinaisons comme 2008-02-31.
Cependant, dans la pratique, c'est rarement suffisant car SimpleDateFormat.analyser est extrêmement libéral. Il y a deux comportements vous pourriez être concerné par:
Des caractères non valides dans la chaîne de date
Étonnamment, 2008-02-2x va "passer" comme une date valide avec les paramètres régionaux de format = "aaaa-MM-jj", par exemple. Même lorsque isLenient==false.
Ans: 2, 3 ou 4 chiffres?
Vous pouvez également appliquer à 4 chiffres des années plutôt que de laisser la valeur par défaut SimpleDateFormat comportement (qui interprétera "12-02-31" différemment selon que votre format "aaaa-MM-jj" ou "yy-MM-dd")
Une Stricte Solution avec la Bibliothèque Standard
Donc une chaîne complète à ce jour de test pourrait ressembler à ceci: une combinaison de regex match, et ensuite forcé la date de conversion. Le truc avec les regex est de rendre les paramètres régionaux de l'environnement.
Noter que la regex suppose la chaîne de format contient uniquement le jour, le mois, l'année, et des caractères de séparation. A côté de cela, le format peut être dans n'importe quel paramètres régionaux de format: "d/MM/yy", "aaaa-MM-jj", et ainsi de suite. La chaîne de format pour les paramètres régionaux actuels pourrait être obtenu comme ceci:
Joda Time - Meilleure Alternative?
J'ai entendu parler de la joda time récemment et j'ai pensé à comparer. Deux points:
C'est assez simple à utiliser:
Date
,SimpleDateFormat
, etc.) sont désormais supplantés par les modernes java.temps classes. De même, le Joda-Time le projet est en mode de maintenance, et conseille la migration vers le java.temps classes.Vous pouvez utiliser SimpleDateFormat
Par exemple quelque chose comme:
java.util.Date
,java.util.Calendar
, etjava.text.SimpleDateFormat
sont maintenant héritage, supplantée par la java.temps les classes intégré dans Java 8 et les versions ultérieures. Voir Tutoriel par Oracle.tl;dr
Utiliser le le mode strict sur
java.temps.DateTimeFormatter
pour analyser unLocalDate
. Piège pour leDateTimeParseException
.Après l'analyse, vous pouvez vérifier la valeur raisonnable. Par exemple, une date de naissance dans les cent dernières années.
Éviter héritage de date-heure classes
Éviter d'utiliser le gênants vieille date-heure classes livré avec les premières versions de Java. Aujourd'hui supplanté par le java.le temps classes.
LocalDate
&DateTimeFormatter
&ResolverStyle
La
LocalDate
classe représente une date uniquement de la valeur, sans le temps de la journée et sans fuseau horaire.La
java.temps.DateTimeFormatter
classe peut être définie pour analyser des chaînes avec l'un des trois clémence modes définis dans leResolverStyle
enum. Nous insérer une ligne dans le code ci-dessus pour essayer chacun des modes.Les résultats:
ResolverStyle.LENIENT
ld: 2000-03-02
ResolverStyle.SMART
ld: 2000-02-29
ResolverStyle.STRICT
ERREUR: java.temps.format.DateTimeParseException: le Texte "31/02/2000' n'a pas pu être analysée: date non Valide 'FÉVRIER 31'
Nous pouvons voir que dans
ResolverStyle.CLÉMENT
mode, l'invalide à la date avance d'un nombre équivalent de jours. DansResolverStyle.SMART
mode (par défaut), une décision logique pour maintenir la date dans le mois et aller avec le dernier jour du mois, le 29 Février d'une année bissextile, comme il n'y a pas de 31 jours dans le mois. LeResolverStyle.STRICT
mode déclenche une exception se plaindre qu'il n'y a aucune date.Tous les trois de celles-ci sont raisonnables en fonction de votre problème d'affaires et politiques. Les sons comme dans votre cas, vous souhaitez que le mode strict de rejeter la date invalide plutôt que de le régler.
Sur java.temps
La java.temps cadre est intégré dans Java 8 et les versions ultérieures. Ces classes permettent d'éviter la pénible vieux héritage date du temps des classes comme
java.util.Date
,Agenda
, &SimpleDateFormat
.La Joda-Time projet, maintenant dans le mode de maintenance, conseille la migration vers le java.le temps classes.
Pour en savoir plus, consultez les Oracle Tutoriel. Et de recherche de Débordement de Pile pour de nombreux exemples et des explications. La spécification est JSR 310.
Vous pouvez échanger java.temps objets directement avec votre base de données. Utiliser un Pilote JDBC compatible avec JDBC 4.2 ou plus tard. Pas besoin de chaînes, pas besoin de
java.sql.*
classes.Où obtenir le java.les classes de temps?
La ThreeTen-Extra projet s'étend java.temps avec d'autres classes. Ce projet est un terrain d'essai pour de possibles futurs ajouts à java.temps. Vous pouvez trouver quelques classes utiles ici comme
Intervalle
,YearWeek
,YearQuarter
, et plus.java.temps
Avec le La Date et l'Heure de l'API (java.le temps classes) intégré dans Java 8 et les versions ultérieures, vous pouvez utiliser le
LocalDate
classe.ResolverStyle.SMART
qui ajuste la valeur résultante à une date valide plutôt que de lancer une exception. Donc, ce code ne permettront pas d'atteindre l'objectif de la Question. Voir ma Réponse par exemple, et pour la solution à l'aide deResolverStyle.STRICT
.Une alternative stricte de la solution à l'aide de la bibliothèque standard est à effectuer les opérations suivantes:
1) Créer un strict SimpleDateFormat à l'aide de votre modèle
2) tente d'analyser l'utilisateur a entré une valeur à l'aide du format de l'objet
3) en Cas de succès, de reformater, de la Date résultant de (2) en utilisant le même format de date (à partir de (1))
4) Comparer les reformaté date à l'encontre de l'original, la valeur saisie par l'utilisateur. S'ils sont égaux alors la valeur entrée strictement correspond à votre modèle.
De cette façon, vous n'avez pas besoin de créer des expressions régulières - dans mon cas, j'avais besoin de l'appui de tout SimpleDateFormat le modèle de la syntaxe, plutôt que de se limiter à certains types comme des jours, des mois et des années.
Bâtiment sur la réponse de @Pangea pour résoudre le problème signalé par @ceklock, j'ai ajouté une méthode pour vérifier que le
dateString
ne contiennent pas de caractères non valides.Voici comment je fais:
Je vous suggérons d'utiliser
org.apache.commons.validator.GenericValidator
classe de apache.GenericValidator.isDate(String value, String datePattern, boolean strict);
Remarque: strict de savoir Si ou de ne pas avoir une correspondance exacte de la datePattern.
Je pense que le plus simple est juste de convertir une chaîne de caractères dans un objet date et le convertir en une chaîne de caractères. La chaîne de date est bien si les deux chaînes correspondent toujours.
En supposant que ces deux sont des Chaînes de caractères (sinon ils seraient déjà Dates de validité), voici un moyen:
Voici la sortie j'obtiens:
Comme vous pouvez le voir, il ne gérer à la fois de votre cas bien.
C'est génial de travailler pour moi. L'approche proposée ci-dessus par Ben.
Deux observations sur l'utilisation de SimpleDateFormat.
IME qui est mieux que de créer une instance pour chaque analyser d'une date.
Méthodes ci-dessus, de la date de l'analyse sont sympa , j'ai juste ajouté de nouvelles vérifier dans les méthodes existantes de cette double vérification de la conversion de date à date d'origine à l'aide de formateur de table, de sorte qu'il fonctionne pour presque chaque cas, comme je l'ai vérifié. par exemple, 02/29/2013 est de date non valide.
Compte tenu de la fonction parse la date, conformément à l'actuel acceptables, les formats de date. Elle renvoie true si la date n'est pas analysé correctement.
Voici ce que j'ai fait pour le Nœud de l'environnement à l'aide de pas de bibliothèques externes:
Et voici comment l'utiliser:
Ici c'est que je voudrais vérifier le format de la date: