我是Java 8及更高版本中java.time格式的新手,但我对Joda-Time非常熟悉,而且我非常熟悉Java' { {1}},java.util.Date
和java.util.Calendar
类以及ISO 8601。
我使用PostgreSQL 9.3与jOOQ 3.6.4,DateFormat
表格列包含时间戳:
foo
我使用jOOQ检索bar timestamp with time zone NOT NULL DEFAULT CURRENT_TIMESTAMP
值,并尝试使用java.time' s bar
打印出来:
DateTimeFormatter.ISO_OFFSET_DATE_TIME
这会引发DateTimeFormatter timestampFormatter = DateTimeFormatter.ISO_OFFSET_DATE_TIME;
Cursor<FooRecord> fooRecordCursor = createDSLContext().selectFrom(FOO).fetchLazy();
for(FooRecord fooRecord : fooRecordCursor) {
System.out.println(timestampFormatter.format(fooRecord.getBar().toInstant());
}
:
UnsupportedTemporalTypeException
但是,如果我使用我自己的自定义Caused by: java.time.temporal.UnsupportedTemporalTypeException: Unsupported field: Year
at java.time.Instant.getLong(Instant.java:608)
at java.time.format.DateTimePrintContext$1.getLong(DateTimePrintContext.java:205)
at java.time.format.DateTimePrintContext.getValue(DateTimePrintContext.java:298)
at java.time.format.DateTimeFormatterBuilder$NumberPrinterParser.format(DateTimeFormatterBuilder.java:2543)
at java.time.format.DateTimeFormatterBuilder$CompositePrinterParser.format(DateTimeFormatterBuilder.java:2182)
at java.time.format.DateTimeFormatterBuilder$CompositePrinterParser.format(DateTimeFormatterBuilder.java:2182)
at java.time.format.DateTimeFormatterBuilder$CompositePrinterParser.format(DateTimeFormatterBuilder.java:2182)
at java.time.format.DateTimeFormatter.formatTo(DateTimeFormatter.java:1745)
at java.time.format.DateTimeFormatter.format(DateTimeFormatter.java:1719)
来扩展旧学校ISO8601DateFormat
,我可以很好地解析这个值:
SimpleDateFormat
我觉得这很令人困惑:
final DateFormat timestampFormatter = new ISO8601DateFormat();
...
System.out.println(timestampFormatter.format(fooRecord.getBar());
字段访问器返回bar
。在Java 8版本中,我将其转换为java.sql.Timestamp
,但为什么会减少可用信息量呢?Instant
应该是一个绝对的时间点 - 它不仅仅是基于Instant
偏移,就像JodaTime和Java long
一样?Date
期待来自DateTimeFormatter.ISO_OFFSET_DATE_TIME
的{{1}}字段?格式化程序不应该将Year
偏移量转换为当前时区的日期/时间,并从中检索年份吗?我不希望任何即时消息包含Instant
字段。简而言之:如果基于long
的{{1}}适用于来自PostgreSQL的Year
,那么为什么SimpleDateFormat
无法弄明白如何格式化相同值的ISO8601DateFormat
版本?
答案 0 :(得分:1)
简答:
这是因为json.array?.map ...
类正在分离概念&#34;时间点&#34;和#34;人类看到的时间&#34;而java.time
/ Timestamp
没有。
答案很长:
你是对的,Date
表示时间线中的单个点。这就是为什么不可能对问题给出正确/唯一的答案&#34;年/日/时间是什么?&#34;。这取决于问题在世界的哪个方面:在纽约,它与西德尼不同
但是你的Instant
正在问这个问题。这就是为什么你得到DateTimeFormatter
。
UnsupportedTemporalTypeException
及其子类Date
正在混淆这两个概念。在内部存储Timestamp
&#34;时间点&#34;,他们&#34;回答&#34;如果被要求他们的一年。通常他们假定系统的本地时区将long
- 偏移固定到特定时区
这很容易出错,并引入long
,JodaTime和java.time。
现在,为什么Calendar
不够智能,无法将DateTimeFormatter
与默认的TimeZone对齐?
Instant
适用于TemporalAccessor
界面,并且在DateTimeFormatter
,Instant
或LocalDateTime
等具体实施方式之间没有区别。所有这些实现都有合法的格式化案例,我认为检查具体对象与给定格式的兼容性是不可行的,更不用说执行正确的转换了。
解决方案: 您必须自己将时间戳与时区/偏移量对齐:
ZonedDateTime