From 3b4639ef531e7415c2dbf3cd4ea97bd600d62f94 Mon Sep 17 00:00:00 2001 From: Emil Wihlander Date: Thu, 17 Nov 2022 09:53:35 +0100 Subject: [PATCH] Implement support for interval units. [#565] --- .../java/io/r2dbc/postgresql/codec/Interval.java | 16 ++++++++++++---- .../postgresql/codec/IntervalUnitTests.java | 6 ++++++ 2 files changed, 18 insertions(+), 4 deletions(-) diff --git a/src/main/java/io/r2dbc/postgresql/codec/Interval.java b/src/main/java/io/r2dbc/postgresql/codec/Interval.java index 95af08dee..c8d047638 100644 --- a/src/main/java/io/r2dbc/postgresql/codec/Interval.java +++ b/src/main/java/io/r2dbc/postgresql/codec/Interval.java @@ -828,16 +828,24 @@ private static Interval parsePostgresIntervalValue(String value) { token = st.nextToken(); - // This handles years, months, days for both, ISO and + // This handles millenniums, centuries, decades, years, months, weeks, days for both, ISO and // Non-ISO intervals. Hours, minutes, seconds and microseconds // are handled for Non-ISO intervals here. - if (token.startsWith("year") || token.startsWith("yr")) { - years = Integer.parseInt(valueToken); + if (token.startsWith("mill")) { + years = Math.addExact(years, Math.toIntExact(Math.multiplyExact(Integer.parseInt(valueToken), 1000))); + } else if (token.startsWith("cent") || token.equals("c")) { + years = Math.addExact(years, Math.toIntExact(Math.multiplyExact(Integer.parseInt(valueToken), 100))); + } else if (token.startsWith("dec")) { + years = Math.addExact(years, Math.toIntExact(Math.multiplyExact(Integer.parseInt(valueToken), 10))); + } else if (token.startsWith("year") || token.startsWith("yr")) { + years = Math.addExact(years, Math.toIntExact(Integer.parseInt(valueToken))); } else if (token.startsWith("mon")) { months = Integer.parseInt(valueToken); + } else if (token.startsWith("week") || token.equals("w")) { + days = Math.addExact(days, Math.toIntExact(Math.multiplyExact(Integer.parseInt(valueToken), 7))); } else if (token.startsWith("day")) { - days = Integer.parseInt(valueToken); + days = Math.addExact(days, Math.toIntExact(Integer.parseInt(valueToken))); } else if (token.startsWith("hour") || token.startsWith("hr")) { hours = Integer.parseInt(valueToken); } else if (token.startsWith("min")) { diff --git a/src/test/java/io/r2dbc/postgresql/codec/IntervalUnitTests.java b/src/test/java/io/r2dbc/postgresql/codec/IntervalUnitTests.java index f32af4f14..325f0707d 100644 --- a/src/test/java/io/r2dbc/postgresql/codec/IntervalUnitTests.java +++ b/src/test/java/io/r2dbc/postgresql/codec/IntervalUnitTests.java @@ -63,6 +63,12 @@ static Stream parseValues() { new Object[]{"8 years 2 mons 3 days 04:05", Interval.of(8, 2, 3, 4, 5, 0, 0)}, new Object[]{"00:00:00", Interval.ZERO}, new Object[]{"-1 years -2 mons +3 days -04:05:06", Interval.of(-1, -2, 3, -4, -5, -6, 0)}, + new Object[]{"4 weeks", Interval.of(0, 0, 28, 0, 0, 0.0)}, + new Object[]{"1 w 3 days", Interval.of(0, 0, 10, 0, 0, 0.0)}, + new Object[]{"2 millenniums 4 years", Interval.of(2004, 0, 0, 0, 0, 0.0)}, + new Object[]{"1 dec 8 yrs", Interval.of(18, 0, 0, 0, 0, 0.0)}, + new Object[]{"2 c 2 decade", Interval.of(220, 0, 0, 0, 0, 0.0)}, + new Object[]{"1 century 4 days", Interval.of(100, 0, 4, 0, 0, 0.0)}, // intervalstyle=postgres_verbose new Object[]{"@ 3 days 4 hours 5 mins 6 secs", Interval.of(0, 0, 3, 4, 5, 6, 0)},