Skip to content

Commit

Permalink
Polishing.
Browse files Browse the repository at this point in the history
Add support for offset representation variants (short and full).

[#509][resolves #510]

Signed-off-by: Mark Paluch <mpaluch@vmware.com>
  • Loading branch information
mp911de committed May 17, 2022
1 parent d748e92 commit ff21b5a
Show file tree
Hide file tree
Showing 4 changed files with 110 additions and 6 deletions.
Expand Up @@ -118,7 +118,7 @@ private Temporal decodeTemporal(ByteBuf buffer, PostgresqlObjectId dataType, @Nu
return EpochTime.fromLong(buffer.readLong()).toLocalDateTime();
}

return PostgresqlDateTimeFormatter.INSTANCE.parse(ByteBufUtils.decode(buffer), LocalDateTime::from);
return PostgresqlDateTimeFormatter.parse(ByteBufUtils.decode(buffer), LocalDateTime::from);
case DATE:
case DATE_ARRAY:
if (FORMAT_BINARY == format) {
Expand All @@ -139,7 +139,7 @@ private Temporal decodeTemporal(ByteBuf buffer, PostgresqlObjectId dataType, @Nu
return EpochTime.fromLong(buffer.readLong()).toInstant().atOffset(OffsetDateTime.now().getOffset());
}

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

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

throw new UnsupportedOperationException(String.format("Cannot decode value for type %s, format %s", dataType, format));
Expand Down
Expand Up @@ -18,7 +18,9 @@

import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeFormatterBuilder;
import java.time.format.DateTimeParseException;
import java.time.format.SignStyle;
import java.time.temporal.TemporalQuery;

import static java.time.temporal.ChronoField.DAY_OF_MONTH;
import static java.time.temporal.ChronoField.HOUR_OF_DAY;
Expand All @@ -30,7 +32,7 @@

class PostgresqlDateTimeFormatter {

static final DateTimeFormatter INSTANCE =
private static final DateTimeFormatter FULL_OFFSET =
new DateTimeFormatterBuilder()
.appendValue(YEAR, 4, 10, SignStyle.EXCEEDS_PAD)
.appendLiteral('-')
Expand All @@ -48,8 +50,58 @@ class PostgresqlDateTimeFormatter {
.appendFraction(NANO_OF_SECOND, 0, 9, true)
.optionalEnd()
.optionalStart()
.appendOffset("+HH:mm:ss", "+00:00:00")
.appendOffset("+HH:MM:ss", "+00:00:00")
.optionalEnd()
.toFormatter();

private static final DateTimeFormatter SHORT_OFFSET =
new DateTimeFormatterBuilder()
.appendValue(YEAR, 4, 10, SignStyle.EXCEEDS_PAD)
.appendLiteral('-')
.appendValue(MONTH_OF_YEAR, 2)
.appendLiteral('-')
.appendValue(DAY_OF_MONTH, 2)
.appendLiteral(' ')
.appendValue(HOUR_OF_DAY, 2)
.appendLiteral(':')
.appendValue(MINUTE_OF_HOUR, 2)
.optionalStart()
.appendLiteral(':')
.appendValue(SECOND_OF_MINUTE, 2)
.optionalStart()
.appendFraction(NANO_OF_SECOND, 0, 9, true)
.optionalEnd()
.optionalStart()
.appendOffset("+HH:mm", "+00:00")
.optionalEnd()
.toFormatter();

/**
* Fully parses the text producing an object of the specified type.
* Attempts to parse the text using {@link #SHORT_OFFSET} first, then {@link #FULL_OFFSET}.
* <p>
* Most applications should use this method for parsing.
* It parses the entire text to produce the required date-time.
* For example:
* <pre>
* LocalDateTime dt = parse(str, LocalDateTime::from);
* </pre>
* If the parse completes without reading the entire length of the text,
* or a problem occurs during parsing or merging, then an exception is thrown.
*
* @param <T> the type of the parsed date-time
* @param text the text to parse, not null
* @param query the query defining the type to parse to, not null
* @return the parsed date-time, not null
* @throws DateTimeParseException if unable to parse the requested result
*/
static <T> T parse(CharSequence text, TemporalQuery<T> query) {

try {
return SHORT_OFFSET.parse(text, query);
} catch (DateTimeParseException e) {
return FULL_OFFSET.parse(text, query);
}
}

}
Expand Up @@ -18,6 +18,8 @@

import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeFormatterBuilder;
import java.time.format.DateTimeParseException;
import java.time.temporal.TemporalQuery;

import static java.time.temporal.ChronoField.HOUR_OF_DAY;
import static java.time.temporal.ChronoField.MINUTE_OF_HOUR;
Expand All @@ -26,7 +28,7 @@

class PostgresqlTimeFormatter {

static final DateTimeFormatter INSTANCE =
private static final DateTimeFormatter SHORT_OFFSET =
new DateTimeFormatterBuilder()
.appendValue(HOUR_OF_DAY, 2)
.appendLiteral(':')
Expand All @@ -42,4 +44,48 @@ class PostgresqlTimeFormatter {
.optionalEnd()
.toFormatter();

private static final DateTimeFormatter FULL_OFFSET =
new DateTimeFormatterBuilder()
.appendValue(HOUR_OF_DAY, 2)
.appendLiteral(':')
.appendValue(MINUTE_OF_HOUR, 2)
.optionalStart()
.appendLiteral(':')
.appendValue(SECOND_OF_MINUTE, 2)
.optionalStart()
.appendFraction(NANO_OF_SECOND, 0, 9, true)
.optionalEnd()
.optionalStart()
.appendOffset("+HH:MM:ss", "+00:00")
.optionalEnd()
.toFormatter();

/**
* Fully parses the text producing an object of the specified type.
* Attempts to parse the text using {@link #SHORT_OFFSET} first, then {@link #FULL_OFFSET}.
* <p>
* Most applications should use this method for parsing.
* It parses the entire text to produce the required date-time.
* For example:
* <pre>
* OffsetTime dt = parse(str, OffsetTime::from);
* </pre>
* If the parse completes without reading the entire length of the text,
* or a problem occurs during parsing or merging, then an exception is thrown.
*
* @param <T> the type of the parsed date-time
* @param text the text to parse, not null
* @param query the query defining the type to parse to, not null
* @return the parsed date-time, not null
* @throws DateTimeParseException if unable to parse the requested result
*/
static <T> T parse(CharSequence text, TemporalQuery<T> query) {

try {
return SHORT_OFFSET.parse(text, query);
} catch (DateTimeParseException e) {
return FULL_OFFSET.parse(text, query);
}
}

}
Expand Up @@ -52,6 +52,12 @@ void decode() {

assertThat(new OffsetTimeCodec(TEST).decode(encode(TEST, "21:16:41.123456-09:00"), dataType, FORMAT_TEXT, OffsetTime.class))
.isEqualTo(offsetTime);

assertThat(new OffsetTimeCodec(TEST).decode(encode(TEST, "21:16:41.123456-09"), dataType, FORMAT_TEXT, OffsetTime.class))
.isEqualTo(offsetTime);

assertThat(new OffsetTimeCodec(TEST).decode(encode(TEST, "21:16:41.123456-09:00:00"), dataType, FORMAT_TEXT, OffsetTime.class))
.isEqualTo(offsetTime);
}

@Test
Expand Down

0 comments on commit ff21b5a

Please sign in to comment.