JPA和Hibernate目前都不支持JSR-310在JDK8中带来的新日期/时间类(JPA 票证,Hibernate 票证).尽管如此,我想用JDK8日期/时间类进行编码,因为它们最终设计得很好.特别是,我感兴趣java.time.Instant,并不是完全支持所有java.time.*类型,因为我的所有实体都将使用这个特定的类(或者我现在想,至少:-)
一种选择是编写类型转换器,如JPA 2.1所定义.但是,我们的应用服务器是JBoss EAP 6.3,它是JPA 2.0但不兼容2.1,所以现在这是不可能的.
下一个选项是使用Hibernate用户类型(关于在此处转换其他JSR-310类的博客文章).
有更好的选择吗?谢谢.
我有以下类要使用Spring Data存储在MongoDB中
@Document()
public class Tuple2<T extends Enum<T>> {
@Id
private String id;
@Indexed
@DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME)
private final Instant timeCreated;
...
}
Run Code Online (Sandbox Code Playgroud)
DateTimeFormat注释javadoc状态:
声明字段应格式化为日期时间.支持按样式模式,ISO日期时间模式或自定义格式模式字符串格式化.可以应用于java.util.Date,java.util.Calendar,java.long.Long,Joda-Time值类型; 从Spring 4和JDK 8开始,到JSR-310也是java.time类型.
我使用的是Spring 4.1.1和JDK 8,所以我希望它适用于Instant.但是,这是实际存储的内容:
"timeCreated" : {
"seconds" : NumberLong(1416757496),
"nanos" : 503000000
}
Run Code Online (Sandbox Code Playgroud)
如果我从即时到日期编写和注册自定义转换器,就像在这个答案中解释的一样,那么它是有效的,但是我想避免这种情况,因为我确信必须有更好的方法.
在进一步挖掘Spring源代码之后,我发现了以下Jsr310DateTimeFormatAnnotationFormatterFactory看起来很有希望的类:
使用JDK 8中的JSR-310 java.time包格式化使用DateTimeFormat注释注释的字段.
它的'源代码没有引用Instant,但确实引用了OffsetTime和LocalTime.即便如此,当我在我的示例中将Instant更改为OffsetDateTime时,它仍然存储为复合对象而不是ISODate.
缺什么?
我一直在尝试使用Java 8中内置的java.time包将"DateTime"转换为毫秒.
但我无法正确地做到这一点.我想将"29/Jan/2015:18:00:00"转换为毫秒.以下是我尝试过的
Instant instant = Instant.parse("2015-01-29T18:00:00.0z");
Long instantMilliSeconds = Long.parseLong(instant.getEpochSecond() + "" + instant.get(ChronoField.MILLI_OF_SECOND));
System.out.println(new Date(instantMilliSeconds)); // prints Sun Jun 14 05:06:00 PDT 1970
Run Code Online (Sandbox Code Playgroud)
我尝试过使用LocalDateTime,但找不到有效转换为毫秒的方法.我并不是说这是最好的方法,如果你知道更好的东西,我会非常感谢一些指示.
Calendar从java.time.Instant或获取对象的最简单方法是java.time.ZonedDateTime什么?
我正在使用描述Jackson数据类型JSR310页面的库,但我仍然难以让它工作.
我配置了以下bean:
@Bean
@Primary
public ObjectMapper objectMapper() {
ObjectMapper mapper = new ObjectMapper();
mapper.registerModule(new JSR310Module());
return mapper;
}
Run Code Online (Sandbox Code Playgroud)
当我调用我的REST API时,日期格式输出是yyyy-MM-dd'T'HH:ss.SSSSSS,例如2015-04-11T00:10:38.905847.这可以通过我的AngularJS代码处理得很好.
当我想向REST API提交内容时,日期会发布为yyyy-MM-dd'T'HH:mm:ss.SSS'Z',例如2015-04-09T08:30:00.000Z
杰克逊最后一直在抱怨'Z'.如果我查看LocalDateTimeDeserializer它在文档中使用的DateTimeFormatter.ISO_LOCAL_DATE_TIMEboils ISO_LOCAL_DATE'T'ISO_LOCAL_TIME,它提到它没有覆盖区域.
所以我想我应该设置DateFormat在ObjectMapper我创建:
@Bean
@Primary
public ObjectMapper objectMapper() {
ObjectMapper mapper = new ObjectMapper();
mapper.registerModule(new JSR310Module());
mapper.setDateFormat(new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'"));
return mapper;
}
Run Code Online (Sandbox Code Playgroud)
但这没有任何作用.我将其更改为简单的类似yyyy-MM-dd但序列化日期保留为以前的格式,反序列化也不受影响.
我在这做错了什么才能让它发挥作用?据我所知,我的JavaScript代码中的日期格式是ISO 8601格式...
我希望将毫秒截断到几天,我可以使用
Instant.now().truncatedTo(ChronoUnit.DAYS).toEpochMilli()
Run Code Online (Sandbox Code Playgroud)
但我无法截断ChronoUnit.MONTH(它抛出异常).我需要使用日历吗?
有没有简单的方法将Java 8的LocalDateTime转换为Joda的LocalDateTime?
其中一种方法是将其转换为String,然后从该String创建Joda的LocalDateTime.
我有一个Instant(org.joda.time.Instant)的实例,我得到了一些api响应.我有另一个来自(java.time.Instant)的实例,我可以从其他一些调用获得.现在,我想比较这两个对象来检查哪一个得到最新的.怎么可能?
我们的数据存储区中的记录具有有效和到期时间.此信息使用字符串表示形式存储Instant.
有些记录永远不会过期.但由于到期日的值是强制性的,我们决定存储字符串表示Instant.MAX.
到现在为止还挺好.我们有搜索用例来返回在输入时间范围内有效的所有记录[s,e].我们查询数据存储区并返回[Si, Ei]满足条件的所有此类记录Si < s && e < Ei请注意,此处将比较字符串表示形式.
现在的问题是,+它被预先添加到字符串表示中Instant.MAX.这是失败的条件e < Ei,因为ASCII('+') < ASCII(digit).
我已经写了一段代码知道之后second,+开始得到前提:
Long e = Instant.now().getEpochSecond()*1000;
for (int i = 0; i < 5; i++) {
System.out.println(e + "->" + Instant.ofEpochMilli(e));
e *= 10;
}
Run Code Online (Sandbox Code Playgroud)
打印:
1471925168000->2016-08-23T04:06:08Z
14719251680000->2436-06-07T17:01:20Z
147192516800000->6634-05-07T02:13:20Z
1471925168000000->+48613-06-14T22:13:20Z
14719251680000000->+468404-07-08T06:13:20Z
Run Code Online (Sandbox Code Playgroud)
我可以选择截断+之前持久化的数据存储区.我更感兴趣的是为什么会这样,我们怎么能明确地避免它呢?
我在Java 8(1.8.0_77)和Java 9(Java HotSpot(TM)64位服务器VM(构建9 + 181,混合模式)中尝试了一些代码)
DateTimeFormatter dtf = DateTimeFormatter.ofPattern("eee", Locale.GERMAN);
DayOfWeek mo = dtf.parse("Mo", DayOfWeek::from);
System.out.println("mo = " + mo);
Run Code Online (Sandbox Code Playgroud)
我不太熟悉这些类的细节,但在Java 8中这个工作,打印:
mo =星期一
在Java 9中,它失败了
线程"main"中的异常java.time.format.DateTimeParseException:无法在java.base上的java.base/java.time.format.DateTimeFormatter.parseResolved0(DateTimeFormatter.java:1988)的索引0处解析文本"Mo"在day.main(day.java:10)的/java.time.format.DateTimeFormatter.parse(DateTimeFormatter.java:1890)
任何想法,这是可重现的吗?
因此,在格式化时:使用此代码:
DateTimeFormatter dtf = DateTimeFormatter.ofPattern("eee", Locale.GERMAN);
String format = dtf.format(DayOfWeek.MONDAY);
System.out.println("format = " + format);
Run Code Online (Sandbox Code Playgroud)
jdk1.8.0-77:
格式= Mo.
jdk-9(build 9 + 181)
格式= Mo.