格式化java.time PostgreSQL时间戳值的即时值

时间:2015-10-21 15:18:34

标签: java postgresql date-format jooq java-time

我是Java 8及更高版本中java.time格式的新手,但我对Joda-Time非常熟悉,而且我非常熟悉Java' { {1}},java.util.Datejava.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

我觉得这很令人困惑:

  • jOOQ 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版本?

1 个答案:

答案 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界面,并且在DateTimeFormatterInstantLocalDateTime等具体实施方式之间没有区别。所有这些实现都有合法的格式化案例,我认为检查具体对象与给定格式的兼容性是不可行的,更不用说执行正确的转换了。

解决方案: 您必须自己将时间戳与时区/偏移量对齐:

ZonedDateTime