New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fix #1390 LocalDateTime
string serialization
#1391
Conversation
This removes the tethering of passed in `LocalDateTime` objects to the current time zone. Instead it tethers it to the UTC offset only for purposes of code reuse. Tethering it to UTC at least guarantees the value won’t be changed during serialization as it sometimes is when tething to the current time zone.
@kdubb don't get me wrong I have no clue what is the "correct" interpretation, but do we have any corroborating evidence this is the correct thing to do ? |
Depends on what your definition of this is... If you're asking for corroborating evidence that my fix is the correct one, no. If you read my actual commit message I tether it to UTC only to re-use the string formatting routine already in place; because it will not ever alter the value. Alternatively a specific LocalDateTime formatter could be written; but it seems unnecessary. If you're asking the bigger question then the answer is "sort of" read the docs for The spec is most interesting in that it only specifies that They also specify that It seems pretty clear, to me at least, they're looking to ensure they don't make the mistakes of the past and they're making the API user be explicit about how they are using timezones. The previous code flies directly in the face of that explicit-ness. It converts a |
Reading the javadocs now I'd have to agree that LocalDateTime was never supposed to have any timezone information. In which case I agree with this change |
Just in case, the test is locale-dependent. That is not good.
|
@vlsi Just to be clear... that isn't the test I altered. This existed before my change and is related to other tests. |
@kdubb , technically speaking, the test was disturbed in https://github.com/pgjdbc/pgjdbc/pull/1388/files#diff-8b723c347b2146e27df7b1aa5f76e800L317 As far as I understand, when using ISO, PostgreSQL never prints locale-dependent BC. |
@vlsi The code the formatter replaced appended the literal value "BC". Again, existed before my change.
I'm all for it being fixed but maybe this should be taken up in a different issue/PR as not to conflate the reasoning of this one. |
Re this one: https://travis-ci.org/pgjdbc/pgjdbc/jobs/482125785#L1090-L1094
|
@vlsi I am fully aware my "fix" may not handle all cases you are adding. It doesn't change the fact that the original test was incorrect. It seems I fixed the |
ZonedDateTime zonedDateTime = localDateTime.atZone(getDefaultTz().toZoneId()); | ||
return toString(zonedDateTime.toOffsetDateTime()); | ||
OffsetDateTime offsetDateTime = localDateTime.atOffset(ZoneOffset.UTC); | ||
return toString(offsetDateTime); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This renders something like 2019-07-30 09:17:25.676+00
Why can't this be 2019-07-30 09:17:25.676
, i.e. without zone offset?
Consider use-cases
- inserting
?
bound toLocalDateTime
to atimestamp
column. Then zone-less literal would be OK. - inserting
?
bound toLocalDateTime
to atimestamp with time zone
column (which represents point in time in PostgreSQL). Then zone-less literal should probably be coerced on server side to session zone, so zone-less literal should be OK. UTC-zoned literal will likely be not OK as it will represent a different point in time. - (....)
If this needs to stay this way, please add some explanation.
c25d807
to
adcb194
Compare
4c39f96
to
866c6a9
Compare
// LocalDateTime is always passed with time zone so backend can decide between timestamp and timestamptz | ||
ZonedDateTime zonedDateTime = localDateTime.atZone(getDefaultTz().toZoneId()); | ||
return toString(zonedDateTime.toOffsetDateTime()); | ||
OffsetDateTime offsetDateTime = localDateTime.atOffset(ZoneOffset.UTC); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we should do the opposite there. LocalDateTime
has no time zone, we should not make up one. I would simply not send a time zone if we don't have one.
@@ -199,7 +214,7 @@ public void testSetLocalDateTime() throws SQLException { | |||
ZoneId zone = ZoneId.of(zoneId); | |||
for (String date : datesToTest) { | |||
LocalDateTime localDateTime = LocalDateTime.parse(date); | |||
String expected = localDateTime.atZone(zone) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
IMHO it is correct this was changed, asserting that 2000-03-26T02:00:00
is stored or retrieved as 2000-03-26T03:00:00
when the system time zone is a specific one is wrong IMHO. 2000-03-26T02:00:00
is 2000-03-26T02:00:00
. As it has no time zone the behaviour should be the same and independent of any time zone.
I think the tests should be changed though to not call #getString
as it currently calls PgResultSet#internalGetObject
which ends up calling java.sql.Timestamp#toString()
which is bound to the JVM time zone and can therefore not display timestamps that don't exist in that time zone. As LocalDateTime
has no time zone this is wrong IMHO.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
makes sense.. care to provide a PR ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm looking at this and wondering why we are using timezones at all on LocalDateTime?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
makes sense.. care to provide a PR ?
I can have a look. I'll have to check if it breaks any tests. It may take a few days.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Probably not worth your time until we decide how to deal with this.
My understanding of the timestamp and timestamptz data types is that both are effectively some fractional second offset since epoch, but the difference is that for timestamp epoch is Jan 1, 1970 in some user defined timezone and for timestamptz it is always UTC. Neither of those map very cleanly to the concept of LocalDateTime, which is timezone-less and has no concept of epoch. |
That's an interesting question. What value is actually stored in a timestamp. I assume it would be epoh from UTC |
Unfortunately, I do not understand the nature of the issue yet. I would review this sometime later. The old behavior was there for quite some time, so users might already have implemented workarounds to "invalid pgjdbc behaviour". So we can't easily change the default without breaking people's data. If we really want to flip the default (e.g. if the current behaviour is buggy), I would suggest the following:
|
@davecramer, the binary parsing[1] of |
@bokken thanks for that... more data for the indecision ... I guess my concern is what to do with timestamps without TZ. If the object that they request requires TZ then we can attempt to do something although it's apparent that it may be wrong. |
Short answer: no, these are unfortunate side effects of implementation details of old JDK classes ( Long answer: In SQL Where it gets complicated is once we involve Now for |
@davecramer, |
I'm struggling to come up with a good way to detect this:
|
@marschall, are you suggesting to use the [1] - https://docs.oracle.com/javase/8/docs/api/java/time/LocalDateTime.html#plus-long-java.time.temporal.TemporalUnit- |
Postgresql does not actually store any timezone or offset information as part of timestamptz. It is effectively identical to |
This is a proposed fix for #1390.
All Submissions:
New Feature Submissions:
Changes to Existing Features:
Yes,
LocalDateTime
is now inserted and retrieved without regard for any current time zone. Which, in my interpretation, is the correct thing to do.