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.
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.
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.
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.
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();
vous pouvez utiliser l'annotation @JsonFormat (shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd") sur votre champ.