2 votes

Comparaison de deux horodatages

Je veux comparer les deux horodatages suivants. Il devrait retourner true mais en raison de millisecondes à un chiffre et à deux chiffres dans les deux horodatages, il renvoie false . Que puis-je faire pour qu'il revienne true

public static void main(String[] args) throws ParseException {
    String d1 = "2011-12-31 07:11:01.5";
    String d2 = "2011-12-31 07:11:01.50";
    SimpleDateFormat s1 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.S");
    SimpleDateFormat s2 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SS");

    Date dateOne = s1.parse(d1);
    Date dateTwo = s2.parse(d2);

    System.out.println(dateOne.equals(dateTwo));
}

3voto

black panda Points 1764

Les autres ont déjà répondu au pourquoi. Voici un point de départ pour contourner le problème :

import java.text.*;
import java.util.Date;

public class DatePercentage {

    private final SimpleDateFormat dateFmt = new SimpleDateFormat(
                                "yyyy-MM-dd HH:mm:ss");
    private final DecimalFormat decFmt = new DecimalFormat();

    public Date parse(String text) throws ParseException {
        ParsePosition pos = new ParsePosition(0);
        Date d = dateFmt.parse(text, pos);

        if (d == null) {
            throw new ParseException("Could not parse " + text + ": " + pos,
                                     pos.getErrorIndex());
        } else if (pos.getIndex() < text.length()) {
            Number dec = decFmt.parse(text, pos); // % milliseceonds
            double pct = dec == null ? 0 : dec.doubleValue();

            if (0 < pct && pct < 1) {
                long moreMillis = Math.round(pct * 1000);
                d = new Date(d.getTime() + moreMillis);
            }
        }
        return d;
    }

    public static void main(String[] args) throws ParseException {
        String date = "2011-12-31 07:11:01";
        String [] millis = {"", ".5", ".50", ".500", ".5001", 
                            ".051", ".5009", "garbage"};

        DatePercentage dp = new DatePercentage();

        for (int i = 0; i < millis.length; i++) {
            String str = date + millis[i];
            System.out.format("%2s: %26s -> %tQ%n", i+1, str, dp.parse(str));
        }
    }
}

Sortie :

 1:        2011-12-31 07:11:01 -> 1325333461000
 2:      2011-12-31 07:11:01.5 -> 1325333461500
 3:     2011-12-31 07:11:01.50 -> 1325333461500
 4:    2011-12-31 07:11:01.500 -> 1325333461500
 5:   2011-12-31 07:11:01.5001 -> 1325333461500
 6:    2011-12-31 07:11:01.051 -> 1325333461051
 7:   2011-12-31 07:11:01.5009 -> 1325333461501
 8: 2011-12-31 07:11:01garbage -> 1325333461000

1voto

Tom Anderson Points 22456

Le problème est que le symbole S analyse les chiffres en millisecondes. Toujours. Ainsi, dans le premier cas, ".5" est interprété comme 5 millisecondes, et ".50" comme 50 millisecondes. Aucun d'entre eux n'est interprété comme une demi-seconde, ce qui, je pense, est ce que vous voulez.

Malheureusement, il s'agit d'une lacune de SimpleDateFormat. Il n'y a tout simplement aucun moyen d'analyser ou de formater les champs en décisecondes ou en centièmes de seconde.

La dernière fois que j'ai eu à le faire (il est vrai que c'était pour une heure, pas une date), j'ai fini par analyser manuellement - en découpant la chaîne avec une expression régulière, puis en convertissant les champs en un total de millisecondes à la main. Vous pourriez peut-être découper le champ des fractions de seconde et l'analyser manuellement, puis analyser la chaîne restante avec SimpleDateFormat.

L'autre solution consiste à ajouter des zéros à la fin des chaînes, de manière à ce que les secondes fractionnées soient toujours composées de trois chiffres, qui seront alors analysés correctement. C'est laid, mais au moins c'est simple.

1voto

Tomas Points 4691

C'est vrai que equals renvoie à false . Ces deux chaînes sont différentes - .5 (interprété comme .05 ) ne peut pas être la même chose que .50 . Il est également préférable d'utiliser compareTo si vous voulez comparer Dates .

Et je n'en utiliserais qu'un seul SimpleDateFormat comme ça :

SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SS");

Date dateOne = format.parse(d1);
Date dateTwo = format.parse(d2);

Voici donc mes suggestions :

  • Si vous voulez vraiment que ces différentes valeurs soient identiques, comparez-les en tant que chaînes de caractères avec une expression régulière ( Je ne recommanderais pas cette solution ).
  • Si tu les transformes en Date alors ils seront différents car le ne sont pas la même chose.
  • Ou (comme d'autres personnes ici le suggèrent) vous pouvez supprimer le .SS partie du modèle, mais vous perdrez la précision

0voto

Nambari Points 42066

Essayez simplement ceci (en supposant que vous ne voulez pas tenir compte des millisecondes) :

SimpleDateFormat s1 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");     
        Date dateOne = s1.parse(d1);     
        Date dateTwo = s1.parse(d2);      
System.out.println(dateOne.equals(dateTwo));

0voto

JB Nizet Points 250258

Il semble que SimpleDateFormat interprète la dernière partie comme un nombre entier, et non comme une partie décimale. La solution évidente est de s'assurer qu'il y a toujours trois chiffres à la fin, et de les remplacer par des 0 si ce n'est pas le cas.

Ensuite, utilisez le modèle yyyy-MM-dd HH:mm:ss.SSS pour l'analyser.

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