2

Simple test inserting a serial id and a timestamp with timezone then selecting the data back. The value returned is in my local time but is indicated as UTC. Below are raw selects from Postgres and corresponding values in Java as queried via jOOQ.

set timezone to 'UTC';
select * from date_tests;
 id |     test_timestamp     
----+------------------------
  1 | 2019-05-30 17:54:32+00

set timezone to 'America/Denver';
SET
select * from date_tests;
 id |     test_timestamp     
----+------------------------
  1 | 2019-05-30 11:54:32-06

When querying Postgres, it tells me what time zone the Instant has been converted to. When I get the same responses in Java, the Instant is converted to whatever time the JVM is set to, but the offset is NOT set accordingly. Example below. I believe I would classify this as a jOOQ bug.

        TimeZone.setDefault( TimeZone.getTimeZone( "UTC" ) );
        DateTestsRecord insertedRecord = context.selectFrom( DATE_TESTS ).where( DATE_TESTS.ID.eq( id ) ).fetchAny();
        System.out.println( insertedRecord.getTestTimestamp() );
//Output is 2019-05-30T17:54:32Z
//Makes sense, the inserted timestamp was hour 17 UTC

        TimeZone.setDefault( TimeZone.getTimeZone( "America/Denver" ));
        DateTestsRecord insertedRecordInMountain = context.selectFrom( DATE_TESTS ).where( DATE_TESTS.ID.eq( id ) ).fetchAny();
        System.out.println( insertedRecordInMountain.getTestTimestamp() );
//Output is 2019-05-30T11:54:32Z
//Makes NO sense, the hour was 17 UTC, either give it to me as 17 Z
//Or convert to -6 because my system time is Mountain, 
//but indicate it has a -6 offset.  
//But don't give a -6 time and say it's Z.  

Once again, this seems to have nothing to do with what time the database is set to, depends only on the default time set with TimeZone.setDefault.

Original test code and discussion at jOOQ returns offset date time as Z (UTC) even though it's not

More info after debugging:

After stepping through the jOOQ code for a while, I believe I found the culprit. In DefaultBinding.java:

    else if (type == OffsetDateTime.class) {
        result = (T) offsetDateTime(ctx.resultSet().getString(ctx.index()));
    }

If I call getObject here, I find the object at index 2 (the test_timestamp) is a java.sql.Timestamp. The toString value of this object is the "2019-05-30 11:54:32.0" without the offset, but clearly with the offset applied (look at postgres output above, hour 11 is with a -6 offset). If I call getObject, I can see that the expected offset is stored, but not properly returned using the default toString. I'm on Java 1.8.0_211-b12. I don't know if this toString behavior has changed over time.

Continuing from there, I see the OffsetDateTime parse method comments indicate this string was expected to contain the offset, which seems obvious. No way to invent the correct offset if the string does not contain it, which it does not thanks to the Timestamp toString behavior I discuss above.

Evan
  • 2,441
  • 23
  • 36
  • 1
    Exactly what is your question? It looks like you are just reasking your question again and hoping to get a different answer. – Mark Rotteveel Sep 05 '19 at 17:48
  • This was originally an update to my question trying to point out that if the system timezone is anything other than UTC, the time returned from jOOQ is in the system timezone but incorrectly indicated as in UTC. My question is how to make this stop, or what the best workaround would be if I'm not doing something wrong. Lukas suggested I move the edit to a new question. Frankly, I think it should have remained as an update, but if it helps him to have it separated, then I'm happy to do that. – Evan Sep 05 '19 at 18:07
  • But you are correct, this is the same behavior as I originally indicated in that linked question. You can't please everyone, but I'd prefer to choose the library creator of the product in question. – Evan Sep 05 '19 at 18:07
  • Also to be clear, his answer in the previous question does not answer this. – Evan Sep 05 '19 at 18:08
  • @MarkRotteveel: Is this really a duplicate? I mean, the other question was using jOOQ to write to the database. This one isn't... – Lukas Eder Sep 05 '19 at 20:53
  • @LukasEder In my opinion it presents the same underlying problem, just with a different example and phrased differently. – Mark Rotteveel Sep 06 '19 at 06:38
  • Does this make sense @LukasEder? Do you see the same behavior? – Evan Sep 12 '19 at 17:40
  • I still think this isn't exactly the same question as the previous one, but I'm not sure if I'm going to be able to reproduce exactly this from what you've posted so far. An MCVE might be helpful: https://github.com/jOOQ/jOOQ-mcve – Lukas Eder Sep 13 '19 at 09:30
  • I deleted this based on my findings in the linked question, but I still believe the DefaultBinding.java implementation here can cause problems depending on the driver being used. Swapping postgres drivers causes my test to pass or fail depending on the driver, which is not right. Additionally, I see that the timezone is included in the object on the postgres driver that fails, but toString strips it off. – Evan Sep 24 '19 at 18:38
  • 1
    I subsequently undeleted this post for future reference after seeing the following question come up recently, https://stackoverflow.com/questions/58085244/jooq-localdatetime-fields-use-system-timezone-instead-of-session-timezone/58086181#58086181. It seems likely to me that this person's configuration and MySQL driver suffer from the same behavior I observed here. – Evan Sep 24 '19 at 18:39

0 Answers0