在不创建大量对象的情况下将 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
转换成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))
整个主题最快。
从性能的角度来看,我没有确切的数字,但我会使用 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") 注释。
我需要大量地将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))
整个主题最快。
从性能的角度来看,我没有确切的数字,但我会使用 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") 注释。