Déterminer si une chaîne est une date valide avant l'analyse
J'ai cette situation où je lis à propos de 130K enregistrements contenant les dates stockées comme des champs de type Chaîne. Certains dossiers contiennent des blancs (null), certains contiennent des chaînes de caractères comme ceci: 'dd-MMM-yy' et certains contiennent cette "jj/MM/aaaa".
J'ai écrit une méthode comme ceci:
public Date parsedate(String date){
if(date !== null){
try{
1. create a SimpleDateFormat object using 'dd-MMM-yy' as the pattern
2. parse the date
3. return the parsed date
}catch(ParseException e){
try{
1. create a SimpleDateFormat object using 'dd/MM/yyy' as the pattern
2. parse the date
3. return parsed date
}catch(ParseException e){
return null
}
}
}else{
return null
}
}
De sorte que vous peut-être déjà repéré le problème. Je suis en utilisant le try .. catch dans le cadre de ma logique. Il serait mieux que je peux déterminer la main avant que la Chaîne contient en fait un parseable date dans un format puis de tenter de l'analyser.
Donc, est-il une API ou une bibliothèque qui peut vous aider avec ceci? Je n'ai pas l'esprit de l'écriture de plusieurs Analyser classes pour gérer les différents formats et ensuite, la création d'une usine pour sélectionner le correct6, mais, comment puis-je déterminer lequel?
Grâce.
source d'informationauteur Morgul Master
Vous devez vous connecter pour publier un commentaire.
Voir Paresseux gestion des Erreurs en Java pour un aperçu de la façon d'éliminer les blocs try/catch à l'aide d'un
Option
type.Fonctionnel Java est votre ami.
En substance, ce que vous voulez faire est d'envelopper la date de l'analyse dans une fonction qui n'a pas de jeter quoi que ce soit, mais indique dans son type de retour si l'analyse a été couronnée de succès ou non. Par exemple:
OK, maintenant que vous avez une réutilisables date de l'analyseur qui n'a pas de jeter quoi que ce soit, mais indique un échec en renvoyant une valeur de type
Option.None
. Voici comment l'utiliser:Qui va vous donner la date analysée avec le premier modèle qui correspond à, ou une valeur de type d'Option.Aucun, qui est de type sécurisé alors que la valeur null n'est pas.
Si vous vous demandez ce que
Stream
est... c'est un paresseux liste. Cela garantit que vous ignorer les modèles après le succès du premier. Pas besoin de faire trop de travail.Appeler votre fonction comme ceci:
Ou...
Ne soyez pas trop dur sur vous-même sur l'utilisation de try-catch dans la logique: c'est l'une de ces situations où la Java des forces de vous donc il n'y a pas beaucoup que vous pouvez faire à ce sujet.
Mais dans ce cas, vous pouvez à la place utiliser
DateFormat.parse(String, ParsePosition)
.Vous pouvez profiter des expressions régulières pour déterminer le format de la chaîne, et si elle correspond à n'importe quel format valide. Quelque chose comme ça (pas testé):
(Oups, j'ai écrit ceci en C# avant de vérifier pour voir ce que la langue que vous utilisez.)
Si vous formats sont exacts (7 juin 1999, soit 07-Jun-99 ou 07/06/1999: vous êtes sûr que vous avez les zéros non significatifs), alors vous pourriez seulement de vérifier la longueur de la chaîne avant d'essayer de l'analyser.
Être prudent avec le nom du mois abrégé dans la première version, parce que Jun ne peut être juin dans une autre langue.
Mais si vos données venant d'une base de données, ensuite, je voudrais juste convertir toutes les dates au format commun (c'est-off, mais alors vous contrôlez les données et le format).
Limitée de situation, la meilleure (et la méthode la plus rapide) est certinally afin d'analyser la journée, puis, sur la base de la prochaine char '/' ou '-' essayer d'analyser le reste. et si à un moment il y a des données inattendues, retourner NULL.
Qui ressemble à trois options si vous avez seulement deux, les formats connus:
-
ou/
première et de commencer avec cette analyse pour ce format.Ce dernier semble inutile.
Utiliser des expressions régulières pour analyser votre chaîne. Assurez-vous que vous gardez les deux regex est pré-compilé (pas de créer de nouveaux à chaque appel de méthode, mais de les stocker en tant que constantes), et de comparer si c'est réellement plus rapide que la
try-catch
vous utilisez.Je trouve toujours étrange que votre méthode renvoie
null
si les deux versions de l'échec plutôt que de lancer une exception.vous pouvez utiliser split pour déterminer le format à utiliser
Qui suppose qu'ils sont tous dans l'une ou l'autre format, vous pourriez améliorer la vérification en cas de besoin
En supposant que les modèles que vous citez sont les seuls susceptibles choix, je regarde la Chaîne transmise à voir le format à appliquer.
Comme d'autres l'ont mentionné, si vous pouvez garantie que vous jamais accéder à la
DateFormat
s dans un environnement multi-thread manière, vous pouvez faire au niveau de la classe ou statique instances.Une alternative à la création d'un SimpleDateFormat (ou deux) par itération serait paresseusement remplir un ThreadLocal conteneur pour ces formats. Cela permettra de résoudre à la fois la sécurité des Threads préoccupations et les inquiétudes autour de la création d'un objet de performance.
Un simple utilitaire de la classe que j'avais écrit pour mon projet. Espérons que cela aide quelqu'un.
Exemples d'utilisation: