web-dev-qa-db-fra.com

Convertir Java.util.Date en chaîne au format aaaa-MM-jj sans créer beaucoup d'objets

J'ai besoin de convertir Java.util.Date à String dans yyyy-MM-dd format en grande quantité.

Je viens de passer à Java 8 et je veux savoir comment le faire correctement. Ma solution avec Java 7 était comme:

DateTimeFormatter DATE_FORMATTER = DateTimeFormat.forPattern(DATE_FORMAT_PATTERN)

DATE_FORMATTER.print(value.getTime())

Cela m'a aidé à ne pas créer beaucoup d'objets redondants.

Alors maintenant, quand je suis passé à Java 8 je veux le réécrire correctement mais:

LocalDate.fromDateFields(value).toString())

crée à chaque fois un nouvel objet LocalDate et cela donne beaucoup de travail au GC.

Existe-t-il des moyens de résoudre mon problème? Les performances et la sécurité des threads sont très importantes.

Après quelques tests, j'ai constaté que même en créant de nouvelles constructions d'objets avec:

new SimpleDateFormat("yyyy-MM-dd")).format(value)) 

le plus rapide sur ce sujet.

17
Oleksandr Riznyk

Ce qui suit n'a qu'une surcharge pour la conversion de l'ancienne date en la nouvelle date locale.

    Date date = new Date();
    LocalDate ldate = LocalDate.from(date.toInstant().atZone(ZoneOffset.UTC));
    String s = DateTimeFormatter.ISO_DATE.format(ldate); // uuuu-MM-dd

Il est vrai cependant que DateTimeFormatters sont thread-safe et auront donc une instanciation de plus par appel.

P.S.

J'ai ajouté .atZone(ZoneOffset.UTC) en raison d'une exception signalée et de la solution de @ Flown: spécifier la zone. Comme Date n'est pas nécessairement utilisé pour les dates UTC, on peut en utiliser une autre.

8
Joop Eggen

Utilisez SimpleDateFormat pour formater la date.

attention, SDF n'est pas PAS ENFILÉ , cela peut ne pas être important mais gardez cela à l'esprit.

Par exemple:

SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
System.out.println((sdf.format(new Date())).toString());

LIEN avec plus d'informations.

3
Emil Hotkowski

Sans créer beaucoup d'objets, ce qui signifie que vous voulez la version performante?

public static String getIsoDate(Java.util.Date time) {
    Java.util.Calendar cal = Java.util.Calendar.getInstance();
    cal.setTime(time);
    StringBuilder sb = new StringBuilder();
    int year = cal.get(Java.util.Calendar.YEAR);
    int month = cal.get(Java.util.Calendar.MONTH) + 1;
    int day = cal.get(Java.util.Calendar.DAY_OF_MONTH);
    sb.append(year);
    sb.append('-');
    if (month < 10) {
        sb.append('0');
    }
    sb.append(month);
    sb.append('-');
    if (day < 10) {
        sb.append('0');
    }
    sb.append(day);
    return sb.toString();
}

Cette version est thread-safe et évite la plupart des créations d'objets cachés, et à moins que vous ayez des années sous 1000 ou plus de 9999, elle s'imprimera très bien.

2
coladict

Je n'ai pas de chiffres exacts du point de vue des performances mais j'utiliserais Java 8 Time API pour résoudre ce problème. Dans votre cas particulier, j'utiliserais la déclaration suivante:

LocalDate.now().format(DateTimeFormatter.ISO_DATE);

EDIT: Pour cette solution est une conversion de Java.util.Date à Java.time.LocalDate Champs obligatoires!

new Date().toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
2
0x1C1B

vous pouvez utiliser l'annotation @JsonFormat (shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd") sur votre champ.

1
Raheela Aslam