From 96d3b25d02f7d90bde885d91730dcbf821e09458 Mon Sep 17 00:00:00 2001 From: lutovich Date: Fri, 20 Apr 2018 23:29:18 +0200 Subject: [PATCH] Simplified toString() for duration Previously it normalized duration in order to expose a more human-friendly string. For example, 7 days would become a week, 12 months would become a year. It seems nice but might create a false impression that it is possible to retrieve weeks and years from an `IsoDuration` object. However, it only supports months, days, seconds and nanoseconds. Also, other drivers do not normalize durations. This commit makes `IsoDuration#toString()` simply concatenate all values into a string as is. Resulting string will only contain months, days, seconds and nanoseconds. Zero values are not filtered out. So returned ISO strings represent exactly same durations but in different format. --- .../driver/internal/InternalIsoDuration.java | 63 +------------------ .../internal/InternalIsoDurationTest.java | 16 +++-- 2 files changed, 11 insertions(+), 68 deletions(-) diff --git a/driver/src/main/java/org/neo4j/driver/internal/InternalIsoDuration.java b/driver/src/main/java/org/neo4j/driver/internal/InternalIsoDuration.java index 8dd8761fac..d3f7dceb64 100644 --- a/driver/src/main/java/org/neo4j/driver/internal/InternalIsoDuration.java +++ b/driver/src/main/java/org/neo4j/driver/internal/InternalIsoDuration.java @@ -38,8 +38,6 @@ public class InternalIsoDuration implements IsoDuration { private static final List SUPPORTED_UNITS = unmodifiableList( asList( MONTHS, DAYS, SECONDS, NANOS ) ); - private static final InternalIsoDuration ZERO = new InternalIsoDuration( 0, 0, 0, 0 ); - public static final long NANOS_PER_SECOND = 1_000_000_000L; private final long months; private final long days; @@ -195,65 +193,6 @@ public int hashCode() @Override public String toString() { - // print the duration in iso standard format. - if ( this.equals( ZERO ) ) - { - return "PT0S"; // no need to allocate a string builder if we know the result - } - StringBuilder str = new StringBuilder().append( "P" ); - append( str, months / 12, 'Y' ); - append( str, months % 12, 'M' ); - append( str, days / 7, 'W' ); - append( str, days % 7, 'D' ); - if ( seconds != 0 || nanoseconds != 0 ) - { - str.append( 'T' ); - long s = seconds % 3600; - append( str, seconds / 3600, 'H' ); - append( str, s / 60, 'M' ); - s %= 60; - if ( s != 0 ) - { - str.append( s ); - if ( nanoseconds != 0 ) - { - nanos( str ); - } - str.append( 'S' ); - } - else if ( nanoseconds != 0 ) - { - if ( nanoseconds < 0 ) - { - str.append( '-' ); - } - str.append( '0' ); - nanos( str ); - str.append( 'S' ); - } - } - if ( str.length() == 1 ) - { // this was all zeros (but not ZERO for some reason), ensure well formed output: - str.append( "T0S" ); - } - return str.toString(); - } - - private static void append( StringBuilder str, long quantity, char unit ) - { - if ( quantity != 0 ) - { - str.append( quantity ).append( unit ); - } - } - - private void nanos( StringBuilder str ) - { - str.append( '.' ); - int n = nanoseconds < 0 ? -nanoseconds : nanoseconds; - for ( int mod = (int)NANOS_PER_SECOND; mod > 1 && n > 0; n %= mod ) - { - str.append( n / (mod /= 10) ); - } + return String.format( "P%sM%sDT%s.%sS", months, days, seconds, String.format( "%09d", nanoseconds ) ); } } diff --git a/driver/src/test/java/org/neo4j/driver/internal/InternalIsoDurationTest.java b/driver/src/test/java/org/neo4j/driver/internal/InternalIsoDurationTest.java index 506b247780..9a9aa13e24 100644 --- a/driver/src/test/java/org/neo4j/driver/internal/InternalIsoDurationTest.java +++ b/driver/src/test/java/org/neo4j/driver/internal/InternalIsoDurationTest.java @@ -156,13 +156,17 @@ public void shouldCreateFromDuration() @Test public void toStringShouldPrintInIsoStandardFormat() throws Throwable { - assertThat( new InternalIsoDuration( 0, 0, 0, 0 ).toString(), equalTo( "PT0S" ) ); - assertThat( new InternalIsoDuration( Period.parse( "P356D" ) ).toString(), equalTo( "P50W6D" ) ); - assertThat( new InternalIsoDuration( Duration.parse( "PT45S" ) ).toString(), equalTo( "PT45S" ) ); + assertThat( new InternalIsoDuration( 0, 0, 0, 0 ).toString(), equalTo( "P0M0DT0.000000000S" ) ); + assertThat( new InternalIsoDuration( 2, 45, 59, 11 ).toString(), equalTo( "P2M45DT59.000000011S" ) ); + assertThat( new InternalIsoDuration( 4, -101, 1, 999 ).toString(), equalTo( "P4M-101DT1.000000999S" ) ); + assertThat( new InternalIsoDuration( -1, 12, -19, 1 ).toString(), equalTo( "P-1M12DT-19.000000001S" ) ); - assertThat( new InternalIsoDuration( Period.parse( "P14D" ), Duration.parse( "PT16H12M" ) ).toString(), equalTo( "P2WT16H12M" ) ); - assertThat( new InternalIsoDuration( Period.parse( "P5M1D" ), Duration.parse( "PT12H" ) ).toString(), equalTo( "P5M1DT12H" ) ); - assertThat( new InternalIsoDuration( Period.parse( "P2W3D" ), Duration.parse( "PT12H" ) ).toString(), equalTo( "P2W3DT12H" ) ); + assertThat( new InternalIsoDuration( Period.parse( "P356D" ) ).toString(), equalTo( "P0M356DT0.000000000S" ) ); + assertThat( new InternalIsoDuration( Duration.parse( "PT45S" ) ).toString(), equalTo( "P0M0DT45.000000000S" ) ); + + assertThat( new InternalIsoDuration( Period.parse( "P14D" ), Duration.parse( "PT16H12M" ) ).toString(), equalTo( "P0M14DT58320.000000000S" ) ); + assertThat( new InternalIsoDuration( Period.parse( "P5M1D" ), Duration.parse( "PT12H" ) ).toString(), equalTo( "P5M1DT43200.000000000S" ) ); + assertThat( new InternalIsoDuration( Period.parse( "P2W3D" ), Duration.parse( "PT2H0.111222333S" ) ).toString(), equalTo( "P0M17DT7200.111222333S" ) ); } private static IsoDuration newDuration( long months, long days, long seconds, int nanoseconds )