Skip to content

Commit

Permalink
Revise temporal rendering and parsing in text mode.
Browse files Browse the repository at this point in the history
We now revised text-encoded temporal value parsing to accomodate for proper timezone and ERA indicators. Also, we now translate infinity and -infinity values into the corresponding MAX (e.g. LocalDateTime.MAX) and MIN values.

[resolves #578]

Signed-off-by: Mark Paluch <mpaluch@vmware.com>
  • Loading branch information
mp911de committed Feb 16, 2023
1 parent b6ebc1c commit 1852777
Show file tree
Hide file tree
Showing 22 changed files with 809 additions and 158 deletions.
Expand Up @@ -24,12 +24,10 @@
import reactor.util.annotation.Nullable;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.OffsetDateTime;
import java.time.OffsetTime;
import java.time.ZoneOffset;
import java.time.ZonedDateTime;
import java.time.temporal.Temporal;
import java.util.EnumSet;
import java.util.Set;
Expand Down Expand Up @@ -118,28 +116,28 @@ private Temporal decodeTemporal(ByteBuf buffer, PostgresqlObjectId dataType, @Nu
return EpochTime.fromLong(buffer.readLong()).toLocalDateTime();
}

return PostgresqlDateTimeFormatter.parse(ByteBufUtils.decode(buffer), LocalDateTime::from);
return PostgresqlDateTimeFormatter.parseLocalDateTime(ByteBufUtils.decode(buffer));
case DATE:
case DATE_ARRAY:
if (FORMAT_BINARY == format) {
return LocalDate.ofEpochDay(EpochTime.fromInt(buffer.readInt()).getJavaDays());
}

return LocalDate.parse(ByteBufUtils.decode(buffer));
return PostgresqlDateTimeFormatter.parseLocalDate(ByteBufUtils.decode(buffer));
case TIME:
case TIME_ARRAY:
if (FORMAT_BINARY == format) {
return LocalTime.ofNanoOfDay(buffer.readLong() * 1000);
}

return LocalTime.parse(ByteBufUtils.decode(buffer));
return PostgresqlTimeFormatter.parseLocalTime(ByteBufUtils.decode(buffer));
case TIMESTAMPTZ:
case TIMESTAMPTZ_ARRAY:
if (FORMAT_BINARY == format) {
return EpochTime.fromLong(buffer.readLong()).toInstant().atOffset(OffsetDateTime.now().getOffset());
}

return PostgresqlDateTimeFormatter.parse(ByteBufUtils.decode(buffer), ZonedDateTime::from);
return PostgresqlDateTimeFormatter.parseOffsetDateTime(ByteBufUtils.decode(buffer));
case TIMETZ:
case TIMETZ_ARRAY:
if (FORMAT_BINARY == format) {
Expand All @@ -148,7 +146,7 @@ private Temporal decodeTemporal(ByteBuf buffer, PostgresqlObjectId dataType, @Nu
return OffsetTime.of(LocalTime.ofNanoOfDay(timeNano), ZoneOffset.ofTotalSeconds(offsetSec));
}

return PostgresqlTimeFormatter.parse(ByteBufUtils.decode(buffer), OffsetTime::from);
return PostgresqlTimeFormatter.parseOffsetTime(ByteBufUtils.decode(buffer));
}

throw new UnsupportedOperationException(String.format("Cannot decode value for type %s, format %s", dataType, format));
Expand Down
2 changes: 1 addition & 1 deletion src/main/java/io/r2dbc/postgresql/codec/InstantCodec.java
Expand Up @@ -37,7 +37,7 @@ final class InstantCodec extends AbstractTemporalCodec<Instant> {
private final Supplier<ZoneId> zoneIdSupplier;

InstantCodec(ByteBufAllocator byteBufAllocator, Supplier<ZoneId> zoneIdSupplier) {
super(Instant.class, byteBufAllocator, TIMESTAMPTZ, TIMESTAMPTZ_ARRAY, Instant::toString);
super(Instant.class, byteBufAllocator, TIMESTAMPTZ, TIMESTAMPTZ_ARRAY, it -> PostgresqlDateTimeFormatter.toString(it));
this.zoneIdSupplier = zoneIdSupplier;
}

Expand Down
Expand Up @@ -33,7 +33,7 @@
final class LocalDateCodec extends AbstractTemporalCodec<LocalDate> {

LocalDateCodec(ByteBufAllocator byteBufAllocator) {
super(LocalDate.class, byteBufAllocator, DATE, DATE_ARRAY, LocalDate::toString);
super(LocalDate.class, byteBufAllocator, DATE, DATE_ARRAY, PostgresqlDateTimeFormatter::toString);
}

@Override
Expand Down
Expand Up @@ -37,7 +37,7 @@ final class LocalDateTimeCodec extends AbstractTemporalCodec<LocalDateTime> {
private final Supplier<ZoneId> zoneIdSupplier;

LocalDateTimeCodec(ByteBufAllocator byteBufAllocator, Supplier<ZoneId> zoneIdSupplier) {
super(LocalDateTime.class, byteBufAllocator, TIMESTAMP, TIMESTAMP_ARRAY, LocalDateTime::toString);
super(LocalDateTime.class, byteBufAllocator, TIMESTAMP, TIMESTAMP_ARRAY, PostgresqlDateTimeFormatter::toString);
this.zoneIdSupplier = Assert.requireNonNull(zoneIdSupplier, "zoneIdSupplier must not be null");
}

Expand Down
Expand Up @@ -33,7 +33,7 @@
final class LocalTimeCodec extends AbstractTemporalCodec<LocalTime> {

LocalTimeCodec(ByteBufAllocator byteBufAllocator) {
super(LocalTime.class, byteBufAllocator, TIME, TIME_ARRAY, LocalTime::toString);
super(LocalTime.class, byteBufAllocator, TIME, TIME_ARRAY, PostgresqlTimeFormatter::toString);
}

@Override
Expand Down
Expand Up @@ -30,7 +30,7 @@
final class OffsetDateTimeCodec extends AbstractTemporalCodec<OffsetDateTime> {

OffsetDateTimeCodec(ByteBufAllocator byteBufAllocator) {
super(OffsetDateTime.class, byteBufAllocator, TIMESTAMPTZ, TIMESTAMPTZ_ARRAY, OffsetDateTime::toString);
super(OffsetDateTime.class, byteBufAllocator, TIMESTAMPTZ, TIMESTAMPTZ_ARRAY, PostgresqlDateTimeFormatter::toString);
}

@Override
Expand Down
Expand Up @@ -29,7 +29,7 @@
public class OffsetTimeCodec extends AbstractTemporalCodec<OffsetTime> {

OffsetTimeCodec(ByteBufAllocator byteBufAllocator) {
super(OffsetTime.class, byteBufAllocator, TIMETZ, TIMETZ_ARRAY, OffsetTime::toString);
super(OffsetTime.class, byteBufAllocator, TIMETZ, TIMETZ_ARRAY, PostgresqlTimeFormatter::toString);
}

@Override
Expand Down

0 comments on commit 1852777

Please sign in to comment.