title: Formatting java.time Instant values from PostgreSQL Timestamp values
body: <p>I'm new to the java.time formats in Java 8 and later, but I'm reasonably comfortable with <a href="http://www.joda.org/joda-time/" rel="nofollow">Joda-Time</a> and I'm very familiar with Java's <code>java.util.Date</code>, <code>java.util.Calendar</code>, and <code>DateFormat</code> classes along with ISO 8601.</p>
  
  <p>I'm using <a href="http://www.postgresql.org" rel="nofollow">PostgreSQL</a> 9.3 with <a href="http://www.jooq.org" rel="nofollow">jOOQ</a> 3.6.4, with a <code>foo</code> table column containing a timestamp:</p>
  
  <pre><code>bar timestamp with time zone NOT NULL DEFAULT CURRENT_TIMESTAMP
  </code></pre>
  
  <p>I retrieve that <code>bar</code> value using jOOQ, and try to print it out using java.time's <code>DateTimeFormatter.ISO_OFFSET_DATE_TIME</code>:</p>
  
  <pre><code>DateTimeFormatter timestampFormatter = DateTimeFormatter.ISO_OFFSET_DATE_TIME;
  Cursor&lt;FooRecord&gt; fooRecordCursor = createDSLContext().selectFrom(FOO).fetchLazy();
  for(FooRecord fooRecord : fooRecordCursor) {
    System.out.println(timestampFormatter.format(fooRecord.getBar().toInstant());
  }
  </code></pre>
  
  <p>This throws an <code>UnsupportedTemporalTypeException</code>:</p>
  
  <pre><code>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)
  </code></pre>
  
  <p>But if I use my own custom <code>ISO8601DateFormat</code> which extends the old-school <code>SimpleDateFormat</code>, I can parse the value just fine:</p>
  
  <pre><code>final DateFormat timestampFormatter = new ISO8601DateFormat();
  ...
    System.out.println(timestampFormatter.format(fooRecord.getBar());
  </code></pre>
  
  <p>I find this very confusing:</p>
  
  <ul>
  <li>The jOOQ <code>bar</code> field accessor returns a <code>java.sql.Timestamp</code>. In the Java 8 version I convert that to an <code>Instant</code>, but why would that reduce the amount of information available?</li>
  <li>An <code>Instant</code> is supposed to be an absolute point of time --- isn't it simply based upon a <code>long</code> offset just like JodaTime and Java <code>Date</code>?</li>
  <li>Why is <code>DateTimeFormatter.ISO_OFFSET_DATE_TIME</code> expecting a <code>Year</code> field from an <code>Instant</code>? Shouldn't the formatter just convert the <code>long</code> offset to a date/time in the current time zone, and retrieve the year from that? I wouldn't expect <em>any</em> instant to contain a <code>Year</code> field.</li>
  </ul>
  
  <p>In short: <strong>If my <code>SimpleDateFormat</code>-based <code>ISO8601DateFormat</code> works fine for a <code>Timestamp</code> from PostgreSQL, why can't <code>DateTimeFormatter.ISO_OFFSET_DATE_TIME</code> figure out how to format the <code>Instant</code> version of the same value?</strong></p>