在不创建大量对象的情况下将 java.util.Date 转换为 yyyy-MM-dd 格式的字符串

Convert java.util.Date to String in yyyy-MM-dd format without creating a lot of objects

我需要大量地将java.util.Date转换成Stringyyyy-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)) 

整个主题最快。

从性能的角度来看,我没有确切的数字,但我会使用 Java 8 Time API 来解决这个问题。在您的特殊情况下,我会使用以下语句:

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

编辑: 对于此解决方案,需要从 java.util.Date 转换为 java.time.LocalDate

new Date().toInstant().atZone(ZoneId.systemDefault()).toLocalDate();

使用 SimpleDateFormat 格式化日期。

注意,SDF 不是线程安全的,它可能不重要,但请记住这一点。

例如:

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

LINK 有更多信息。

下面只对旧Date到新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 确实是线程安全的,因此每次调用都会多一个实例化。

P.S.

我添加了 .atZone(ZoneOffset.UTC) 因为报告了异常,@Flown 的解决方案:指定区域。由于 Date 不一定用于 UTC 日期,因此可以使用另一个。

没有创建大量对象,这意味着您想要性能版本?

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,否则它会打印得很好。

您可以在您的字段上使用@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd") 注释。