91 votes

Analyser n'importe quelle date en Java

Je sais que cette question est posée un peu, et évidemment, vous ne pouvez pas analyser n'importe quelle date. Cependant, je trouve que le python-dateutil bibliothèque est capable d'analyser chaque jour, je jeter à elle, tout en nécessitant absolument aucun effort de trouver une chaîne de format de date. Joda time est toujours vendu comme étant un grand Java date de l'analyseur, mais il nécessite encore à vous de décider de ce format de votre date est en avant de vous choisir un Format (ou en créer un). Vous ne pouvez pas simplement appeler DateFormatter.parse(madate) et comme par magie un objet Date de retour.

Par exemple, la date du "Mer Mar 04 05:09:06 GMT-06:00 2009" est correctement analysé avec python-dateutil:

import dateutil.parser
print dateutil.parser.parse('Wed Mar 04 05:09:06 GMT-06:00 2009')

mais la suite de Joda temps d'appel ne fonctionne pas:

    String date = "Wed Mar 04 05:09:06 GMT-06:00 2009";
    DateTimeFormatter fmt = ISODateTimeFormat.dateTime();
    DateTime dt = fmt.parseDateTime(date);
    System.out.println(date);

Et de la création de votre propre DateTimeFormatter défaites le but, puisque cela semble être le même que l'utilisation de SimpleDateFormatter avec le bon format de chaîne de caractères.

Est-il comparable à analyser une date en Java, comme python-dateutil? Je n'ai pas de soins sur les erreurs, j'ai juste envie de la plupart parfaite.

122voto

BalusC Points 498232

Votre meilleur pari est vraiment demandant de l'aide de regex pour faire correspondre le format de la date motif et/ou de faire de force brute.

Il y a plusieurs années, j'ai écrit un peu idiot DateUtil de la classe qui fait le travail. Voici un extrait de pertinence:

private static final Map<String, String> DATE_FORMAT_REGEXPS = new HashMap<String, String>() {{
    put("^\\d{8}$", "yyyyMMdd");
    put("^\\d{1,2}-\\d{1,2}-\\d{4}$", "dd-MM-yyyy");
    put("^\\d{4}-\\d{1,2}-\\d{1,2}$", "yyyy-MM-dd");
    put("^\\d{1,2}/\\d{1,2}/\\d{4}$", "MM/dd/yyyy");
    put("^\\d{4}/\\d{1,2}/\\d{1,2}$", "yyyy/MM/dd");
    put("^\\d{1,2}\\s[a-z]{3}\\s\\d{4}$", "dd MMM yyyy");
    put("^\\d{1,2}\\s[a-z]{4,}\\s\\d{4}$", "dd MMMM yyyy");
    put("^\\d{12}$", "yyyyMMddHHmm");
    put("^\\d{8}\\s\\d{4}$", "yyyyMMdd HHmm");
    put("^\\d{1,2}-\\d{1,2}-\\d{4}\\s\\d{1,2}:\\d{2}$", "dd-MM-yyyy HH:mm");
    put("^\\d{4}-\\d{1,2}-\\d{1,2}\\s\\d{1,2}:\\d{2}$", "yyyy-MM-dd HH:mm");
    put("^\\d{1,2}/\\d{1,2}/\\d{4}\\s\\d{1,2}:\\d{2}$", "MM/dd/yyyy HH:mm");
    put("^\\d{4}/\\d{1,2}/\\d{1,2}\\s\\d{1,2}:\\d{2}$", "yyyy/MM/dd HH:mm");
    put("^\\d{1,2}\\s[a-z]{3}\\s\\d{4}\\s\\d{1,2}:\\d{2}$", "dd MMM yyyy HH:mm");
    put("^\\d{1,2}\\s[a-z]{4,}\\s\\d{4}\\s\\d{1,2}:\\d{2}$", "dd MMMM yyyy HH:mm");
    put("^\\d{14}$", "yyyyMMddHHmmss");
    put("^\\d{8}\\s\\d{6}$", "yyyyMMdd HHmmss");
    put("^\\d{1,2}-\\d{1,2}-\\d{4}\\s\\d{1,2}:\\d{2}:\\d{2}$", "dd-MM-yyyy HH:mm:ss");
    put("^\\d{4}-\\d{1,2}-\\d{1,2}\\s\\d{1,2}:\\d{2}:\\d{2}$", "yyyy-MM-dd HH:mm:ss");
    put("^\\d{1,2}/\\d{1,2}/\\d{4}\\s\\d{1,2}:\\d{2}:\\d{2}$", "MM/dd/yyyy HH:mm:ss");
    put("^\\d{4}/\\d{1,2}/\\d{1,2}\\s\\d{1,2}:\\d{2}:\\d{2}$", "yyyy/MM/dd HH:mm:ss");
    put("^\\d{1,2}\\s[a-z]{3}\\s\\d{4}\\s\\d{1,2}:\\d{2}:\\d{2}$", "dd MMM yyyy HH:mm:ss");
    put("^\\d{1,2}\\s[a-z]{4,}\\s\\d{4}\\s\\d{1,2}:\\d{2}:\\d{2}$", "dd MMMM yyyy HH:mm:ss");
}};

/**
 * Determine SimpleDateFormat pattern matching with the given date string. Returns null if
 * format is unknown. You can simply extend DateUtil with more formats if needed.
 * @param dateString The date string to determine the SimpleDateFormat pattern for.
 * @return The matching SimpleDateFormat pattern, or null if format is unknown.
 * @see SimpleDateFormat
 */
public static String determineDateFormat(String dateString) {
    for (String regexp : DATE_FORMAT_REGEXPS.keySet()) {
        if (dateString.toLowerCase().matches(regexp)) {
            return DATE_FORMAT_REGEXPS.get(regexp);
        }
    }
    return null; // Unknown format.
}

(toux, double accolade de l'initialisation, de la toux, c'était juste pour obtenir tous pour s'adapter à 100 char longueur max ;) )

Vous pouvez facilement étendre vous-même avec de nouveaux regex et dateformat modèles.

52voto

Cacovsky Points 806

Il y a une belle bibliothèque appelée Natty qui je pense correspond à vos fins:

Natty est un langage naturel date de l'analyseur écrit en Java. Donné une date expression, natty appliquera la norme de la reconnaissance de la langue et de la traduction des techniques pour produire une liste de dates correspondantes avec, en option, d'analyser et informations sur la syntaxe.

Vous pouvez aussi essayer en ligne!

7voto

Robert Diana Points 689

Ce que j'ai vu faire est une classe Date util qui contient plusieurs formats de date typiques. Ainsi, lorsque DateUtil.parse (date) est appelé, il tente d'analyser la date avec chaque format de date en interne et ne lève les exceptions que si aucun des formats internes ne peut l'analyser.

C'est fondamentalement une approche de force brute à votre problème.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X