Seb*_*ian 13 jpa java.util.date java-8
我怎样才能最好地将其转换java.util.Date为Java 8 java.time.YearMonth?
不幸的是,以下抛出DateTimeException:
YearMonth yearMonth = YearMonth.from(date.toInstant());
Run Code Online (Sandbox Code Playgroud)
结果是:
java.time.DateTimeException: Unable to obtain YearMonth from TemporalAccessor: 2015-01-08T14:28:39.183Z of type java.time.Instant
at java.time.YearMonth.from(YearMonth.java:264)
...
Run Code Online (Sandbox Code Playgroud)
我需要此功能,因为我想YearMonth使用JPA 将值存储在数据库中.目前JPA不支持YearMonth,所以我想出了以下YearMonthConverter(省略了导入):
// TODO (future): delete when next version of JPA (i.e. Java 9?) supports YearMonth. See https://java.net/jira/browse/JPA_SPEC-63
@Converter(autoApply = true)
public class YearMonthConverter implements AttributeConverter<YearMonth, Date> {
@Override
public Date convertToDatabaseColumn(YearMonth attribute) {
// uses default zone since in the end only dates are needed
return attribute == null ? null : Date.from(attribute.atDay(1).atStartOfDay(ZoneId.systemDefault()).toInstant());
}
@Override
public YearMonth convertToEntityAttribute(Date dbData) {
// TODO: check if Date -> YearMonth can't be done in a better way
if (dbData == null) return null;
Calendar calendar = Calendar.getInstance();
calendar.setTime(dbData);
return YearMonth.of(calendar.get(Calendar.YEAR), calendar.get(Calendar.MONTH) + 1);
}
}
Run Code Online (Sandbox Code Playgroud)
是不是有更好的(更清洁,更短)的解决方案(两个方向)?
was*_*ren 19
简短回答:
// From Date to YearMonth
YearMonth yearMonth =
YearMonth.from(date.toInstant()
.atZone(ZoneId.systemDefault())
.toLocalDate());
// From YearMonth to Date
// The same as the OP:s answer
final Date convertedFromYearMonth =
Date.from(yearMonth.atDay(1).atStartOfDay(ZoneId.systemDefault()).toInstant());
Run Code Online (Sandbox Code Playgroud)
说明:
YearMonth.from(TemporalAccessor) -method 的JavaDoc 说:
转换将提取YEAR和MONTH_OF_YEAR字段.仅当时态对象具有ISO年表时,或者可以将其转换为LocalDate时,才允许提取.
所以,你需要能够:
YEAR和MONTH_OF_YEAR字段,或LocalDate.让我们试试吧!
final Date date = new Date();
final Instant instant = date.toInstant();
instant.get(ChronoField.YEAR); // causes an error
Run Code Online (Sandbox Code Playgroud)
这是不可能的,抛出异常:
java.time.temporal.UnsupportedTemporalTypeException:不支持的字段:java.time.Instant.get的年份(Instant.java:571)...
这意味着替代方案1会离开窗口.在这个关于如何将Date转换为LocalDate的优秀答案中解释了原因.
尽管它的名字,
java.util.Date代表了时间线上的瞬间,而不是"日期".存储在对象中的实际数据是自1970-01-01T00:00Z(格林威治标准时间1970 /格林威治标准时间1970年初午夜)以来的长数毫秒数.
java.util.DateJSR-310中的等价类是Instant,因此有一个方便的方法toInstant()来提供转换.
所以,一个Date可以转换成一个Instant但是没有帮助我们,做到了吗?
然而,备选方案2证明是成功的.转换Instant为a LocalDate,然后使用YearMonth.from(TemporalAccessor)-method.
Date date = new Date();
LocalDate localDate = date.toInstant()
.atZone(ZoneId.systemDefault())
.toLocalDate();
YearMonth yearMonth = YearMonth.from(localDate);
System.out.println("YearMonth: " + yearMonth);
Run Code Online (Sandbox Code Playgroud)
输出是(因为代码是在2015年1月执行的;):
YearMonth:2015-01
| 归档时间: |
|
| 查看次数: |
13398 次 |
| 最近记录: |