Skip to content

Commit e37ce2c

Browse files
committed
Merge branch 'bzikarsky-fix-instant-handling'
[pgjdbc#196]
2 parents 257f8c8 + 0ef3ba1 commit e37ce2c

File tree

7 files changed

+30
-18
lines changed

7 files changed

+30
-18
lines changed

README.md

+3-2
Original file line numberDiff line numberDiff line change
@@ -278,8 +278,8 @@ This reference table shows the type mapping between [PostgreSQL][p] and Java dat
278278
| [`text`][psql-text-ref] | [**`String`**][java-string-ref], `Clob`|
279279
| [`time [without time zone]`][psql-time-ref] | [`LocalTime`][java-lt-ref]|
280280
| [`time [with time zone]`][psql-time-ref] | Not yet supported.|
281-
| [`timestamp [without time zone]`][psql-time-ref]|[**`LocalDateTime`**][java-ldt-ref], [`LocalTime`][java-lt-ref], [`LocalDate`][java-ld-ref]|
282-
| [`timestamp [with time zone]`][psql-time-ref] | [**`OffsetDatetime`**][java-odt-ref], [`ZonedDateTime`][java-zdt-ref]|
281+
| [`timestamp [without time zone]`][psql-time-ref]|[**`LocalDateTime`**][java-ldt-ref], [`LocalTime`][java-lt-ref], [`LocalDate`][java-ld-ref], [`java.util.Date`][java-legacy-date-ref]|
282+
| [`timestamp [with time zone]`][psql-time-ref] | [**`OffsetDatetime`**][java-odt-ref], [`ZonedDateTime`][java-zdt-ref], [`Instant`][java-instant-ref]|
283283
| [`tsquery`][psql-tsquery-ref] | Not yet supported.|
284284
| [`tsvector`][psql-tsvector-ref] | Not yet supported.|
285285
| [`txid_snapshot`][psql-txid_snapshot-ref] | Not yet supported.|
@@ -349,6 +349,7 @@ Support for the following single-dimensional arrays (read and write):
349349
[java-ldt-ref]: https://docs.oracle.com/javase/8/docs/api/java/time/LocalDateTime.html
350350
[java-ld-ref]: https://docs.oracle.com/javase/8/docs/api/java/time/LocalDate.html
351351
[java-lt-ref]: https://docs.oracle.com/javase/8/docs/api/java/time/LocalTime.html
352+
[java-legacy-date-ref]: https://docs.oracle.com/javase/8/docs/api/java/util/Date.html
352353
[java-odt-ref]: https://docs.oracle.com/javase/8/docs/api/java/time/OffsetDateTime.html
353354
[java-primitive-ref]: https://docs.oracle.com/javase/tutorial/java/nutsandbolts/datatypes.html
354355
[java-short-ref]: https://docs.oracle.com/javase/8/docs/api/java/lang/Short.html

src/main/java/io/r2dbc/postgresql/codec/DateCodec.java

+7-5
Original file line numberDiff line numberDiff line change
@@ -24,18 +24,19 @@
2424
import io.r2dbc.postgresql.util.Assert;
2525
import reactor.util.annotation.Nullable;
2626

27-
import java.time.Instant;
27+
import java.time.LocalDateTime;
28+
import java.time.ZoneId;
2829
import java.util.Date;
2930

3031
final class DateCodec extends AbstractCodec<Date> {
3132

32-
private final InstantCodec delegate;
33+
private final LocalDateTimeCodec delegate;
3334

3435
DateCodec(ByteBufAllocator byteBufAllocator) {
3536
super(Date.class);
3637

3738
Assert.requireNonNull(byteBufAllocator, "byteBufAllocator must not be null");
38-
this.delegate = new InstantCodec(byteBufAllocator);
39+
this.delegate = new LocalDateTimeCodec(byteBufAllocator);
3940
}
4041

4142
@Override
@@ -55,14 +56,15 @@ boolean doCanDecode(PostgresqlObjectId type, Format format) {
5556
Date doDecode(ByteBuf buffer, PostgresqlObjectId dataType, @Nullable Format format, @Nullable Class<? extends Date> type) {
5657
Assert.requireNonNull(buffer, "byteBuf must not be null");
5758

58-
return Date.from(this.delegate.doDecode(buffer, dataType, format, Instant.class));
59+
LocalDateTime intermediary = this.delegate.doDecode(buffer, dataType, format, LocalDateTime.class);
60+
return Date.from(intermediary.atZone(ZoneId.systemDefault()).toInstant());
5961
}
6062

6163
@Override
6264
Parameter doEncode(Date value) {
6365
Assert.requireNonNull(value, "value must not be null");
6466

65-
return this.delegate.doEncode(value.toInstant());
67+
return this.delegate.doEncode(value.toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime());
6668
}
6769

6870
}

src/main/java/io/r2dbc/postgresql/codec/InstantCodec.java

+3-3
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@
3232
import java.time.ZoneOffset;
3333

3434
import static io.r2dbc.postgresql.message.Format.FORMAT_TEXT;
35-
import static io.r2dbc.postgresql.type.PostgresqlObjectId.TIMESTAMP;
35+
import static io.r2dbc.postgresql.type.PostgresqlObjectId.TIMESTAMPTZ;
3636

3737
final class InstantCodec extends AbstractTemporalCodec<Instant> {
3838

@@ -45,7 +45,7 @@ final class InstantCodec extends AbstractTemporalCodec<Instant> {
4545

4646
@Override
4747
public Parameter encodeNull() {
48-
return createNull(TIMESTAMP, FORMAT_TEXT);
48+
return createNull(TIMESTAMPTZ, FORMAT_TEXT);
4949
}
5050

5151
@Override
@@ -70,7 +70,7 @@ Instant doDecode(ByteBuf buffer, PostgresqlObjectId dataType, @Nullable Format f
7070
Parameter doEncode(Instant value) {
7171
Assert.requireNonNull(value, "value must not be null");
7272

73-
return create(TIMESTAMP, FORMAT_TEXT, () -> ByteBufUtils.encode(this.byteBufAllocator, value.toString()));
73+
return create(TIMESTAMPTZ, FORMAT_TEXT, () -> ByteBufUtils.encode(this.byteBufAllocator, value.toString()));
7474
}
7575

7676
@Override

src/main/java/io/r2dbc/postgresql/codec/LocalDateTimeCodec.java

+6
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,9 @@
2626
import reactor.util.annotation.Nullable;
2727

2828
import java.time.Instant;
29+
import java.time.LocalDate;
2930
import java.time.LocalDateTime;
31+
import java.time.ZoneId;
3032
import java.time.ZoneOffset;
3133

3234
import static io.r2dbc.postgresql.message.Format.FORMAT_TEXT;
@@ -51,6 +53,10 @@ LocalDateTime doDecode(ByteBuf buffer, PostgresqlObjectId dataType, @Nullable Fo
5153
Assert.requireNonNull(buffer, "byteBuf must not be null");
5254

5355
return decodeTemporal(buffer, dataType, format, LocalDateTime.class, temporal -> {
56+
if (temporal instanceof LocalDate) {
57+
return ((LocalDate) temporal).atStartOfDay(ZoneId.systemDefault()).toLocalDateTime();
58+
}
59+
5460
return Instant.from(temporal).atOffset(ZoneOffset.UTC).toLocalDateTime();
5561
});
5662
}

src/test/java/io/r2dbc/postgresql/AbstractCodecIntegrationTests.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -180,7 +180,7 @@ void inetAddress() throws UnknownHostException {
180180

181181
@Test
182182
void instant() {
183-
testCodec(Instant.class, Instant.now(), "TIMESTAMP");
183+
testCodec(Instant.class, Instant.now(), "TIMESTAMPTZ");
184184
}
185185

186186
@Test

src/test/java/io/r2dbc/postgresql/codec/DateCodecTest.java

+6-4
Original file line numberDiff line numberDiff line change
@@ -49,9 +49,10 @@ void constructorNoByteBufAllocator() {
4949

5050
@Test
5151
void decode() {
52-
Date date = Date.from(Instant.parse("2018-11-04T15:37:31.177Z"));
52+
Instant testInstant = LocalDateTime.parse("2010-02-01T10:08:04.412").atZone(ZoneId.systemDefault()).toInstant();
53+
Date date = Date.from(testInstant);
5354

54-
assertThat(new DateCodec(TEST).decode(encode(TEST, "2018-11-04 15:37:31.177"), dataType, FORMAT_TEXT, Date.class))
55+
assertThat(new DateCodec(TEST).decode(encode(TEST, "2010-02-01 10:08:04.412"), dataType, FORMAT_TEXT, Date.class))
5556
.isEqualTo(date);
5657
}
5758

@@ -91,12 +92,13 @@ void doCanDecodeNoType() {
9192

9293
@Test
9394
void doEncode() {
94-
Date date = new Date();
95+
Instant testInstant = LocalDateTime.parse("2010-02-01T10:08:04.412").atZone(ZoneId.systemDefault()).toInstant();
96+
Date date = Date.from(testInstant);
9597

9698
assertThat(new DateCodec(TEST).doEncode(date))
9799
.hasFormat(FORMAT_TEXT)
98100
.hasType(TIMESTAMP.getObjectId())
99-
.hasValue(encode(TEST, date.toInstant().toString()));
101+
.hasValue(encode(TEST, "2010-02-01T10:08:04.412"));
100102
}
101103

102104
@Test

src/test/java/io/r2dbc/postgresql/codec/InstantCodecTest.java

+4-3
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@
2020
import org.junit.jupiter.api.Test;
2121

2222
import java.time.Instant;
23-
import java.time.LocalTime;
2423
import java.time.ZonedDateTime;
2524

2625
import static io.r2dbc.postgresql.client.Parameter.NULL_VALUE;
@@ -75,6 +74,8 @@ void doCanDecode() {
7574
assertThat(codec.doCanDecode(TIMESTAMP, FORMAT_BINARY)).isTrue();
7675
assertThat(codec.doCanDecode(MONEY, FORMAT_TEXT)).isFalse();
7776
assertThat(codec.doCanDecode(TIMESTAMP, FORMAT_TEXT)).isTrue();
77+
assertThat(codec.doCanDecode(TIMESTAMPTZ, FORMAT_TEXT)).isTrue();
78+
assertThat(codec.doCanDecode(TIMESTAMPTZ, FORMAT_BINARY)).isTrue();
7879
}
7980

8081
@Test
@@ -95,7 +96,7 @@ void doEncode() {
9596

9697
assertThat(new InstantCodec(TEST).doEncode(instant))
9798
.hasFormat(FORMAT_TEXT)
98-
.hasType(TIMESTAMP.getObjectId())
99+
.hasType(TIMESTAMPTZ.getObjectId())
99100
.hasValue(encode(TEST, instant.toString()));
100101
}
101102

@@ -108,7 +109,7 @@ void doEncodeNoValue() {
108109
@Test
109110
void encodeNull() {
110111
assertThat(new InstantCodec(TEST).encodeNull())
111-
.isEqualTo(new Parameter(FORMAT_TEXT, TIMESTAMP.getObjectId(), NULL_VALUE));
112+
.isEqualTo(new Parameter(FORMAT_TEXT, TIMESTAMPTZ.getObjectId(), NULL_VALUE));
112113
}
113114

114115
}

0 commit comments

Comments
 (0)