Преобразование java.util.Date в String в формате yyyy-MM-dd без создания большого количества объектов
Мне нужно преобразовать java.util.Date
в String
в формате yyyy-MM-dd
в больших количествах.
Я только что перешел в java 8 и хочу знать, как это сделать правильно. Мое решение с Java 7 было похоже:
DateTimeFormatter DATE_FORMATTER = DateTimeFormat.forPattern(DATE_FORMAT_PATTERN)
DATE_FORMATTER.print(value.getTime())
Это помогло мне не создавать множество избыточных объектов.
Итак, теперь, когда я переехал в java 8, я хочу переписать его правильно, но:
LocalDate.fromDateFields(value).toString())
каждый раз создает новый объект LocalDate
и это дает большую работу GC.
Есть ли способы решить мою проблему? Производительность и безопасность потока очень важны.
После некоторого тестирования я обнаружил, что даже при создании новых объектов с помощью:
new SimpleDateFormat("yyyy-MM-dd")).format(value))
быстрее всего по этой теме.
Ответы
Ответ 1
Ниже перечислены только накладные расходы на преобразование старой даты в новый LocalDate.
Date date = new Date();
LocalDate ldate = LocalDate.from(date.toInstant().atZone(ZoneOffset.UTC));
String s = DateTimeFormatter.ISO_DATE.format(ldate); // uuuu-MM-dd
Однако верно, что DateTimeFormatters являются потокобезопасными и, следовательно, будут иметь один экземпляр за каждый вызов.
PS
Я добавил .atZone(ZoneOffset.UTC)
из-за сообщенного исключения и решения @Flown: указание зоны. Поскольку Date
не обязательно используется для дат UTC, можно использовать другую.
Ответ 2
Используйте SimpleDateFormat для форматирования даты.
следите, SDF НЕ РЕЗЬБОЙ, это может быть не важно, но помните об этом.
Например:
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
System.out.println((sdf.format(new Date())).toString());
LINK с дополнительной информацией.
Ответ 3
У меня нет точных чисел с точки зрения производительности, но я бы использовал Java 8 Time API для решения этой проблемы. В вашем специальном случае я бы использовал следующее выражение:
LocalDate.now().format(DateTimeFormatter.ISO_DATE);
EDIT: для этого решения происходит переход от java.util.Date
к java.time.LocalDate
требуется!
new Date().toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
Ответ 4
Без создания большого количества объектов, что означает, что вы хотите версию исполнения?
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();
}
Эта версия является потокобезопасной и позволяет избежать создания большинства скрытых объектов, и если у вас нет лет в возрасте до 1000 или более 9999, она будет печататься просто отлично.
Ответ 5
вы можете использовать аннотацию @JsonFormat (shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd") в вашем поле.