diff --git a/community/kernel/src/main/java/org/neo4j/kernel/impl/proc/temporal/TemporalFunction.java b/community/kernel/src/main/java/org/neo4j/kernel/impl/proc/temporal/TemporalFunction.java index 72fa6bc420c12..a2246478506f4 100644 --- a/community/kernel/src/main/java/org/neo4j/kernel/impl/proc/temporal/TemporalFunction.java +++ b/community/kernel/src/main/java/org/neo4j/kernel/impl/proc/temporal/TemporalFunction.java @@ -292,7 +292,7 @@ public T apply( Context ctx, AnyValue[] args ) throws ProcedureException { AnyValue unit = args[0]; AnyValue input = args[1]; - AnyValue fields = args.length == 3 ? args[2] : EMPTY_MAP; + AnyValue fields = args.length == 2 || args[2] == NO_VALUE ? EMPTY_MAP : args[2]; if ( unit instanceof TextValue && input instanceof TemporalValue && fields instanceof MapValue ) { return function.truncate( diff --git a/community/values/src/main/java/org/neo4j/values/storable/DateTimeValue.java b/community/values/src/main/java/org/neo4j/values/storable/DateTimeValue.java index feecd26171da1..eeb13b8527282 100644 --- a/community/values/src/main/java/org/neo4j/values/storable/DateTimeValue.java +++ b/community/values/src/main/java/org/neo4j/values/storable/DateTimeValue.java @@ -35,14 +35,18 @@ import java.time.temporal.IsoFields; import java.time.temporal.TemporalQueries; import java.time.temporal.TemporalUnit; +import java.util.HashMap; +import java.util.Map; import java.util.function.Supplier; import java.util.regex.Matcher; import java.util.regex.Pattern; +import org.neo4j.helpers.collection.Pair; import org.neo4j.values.AnyValue; import org.neo4j.values.StructureBuilder; import org.neo4j.values.ValueMapper; import org.neo4j.values.virtual.MapValue; +import org.neo4j.values.virtual.VirtualValues; import static java.time.Instant.ofEpochMilli; import static java.time.Instant.ofEpochSecond; @@ -152,7 +156,58 @@ public static DateTimeValue truncate( MapValue fields, Supplier defaultZone ) { - throw new UnsupportedOperationException( "not implemented" ); + if ( unit.isTimeBased() && !(input instanceof DateTimeValue || input instanceof LocalDateTimeValue) ) + { + throw new IllegalArgumentException( "Cannot truncate " + input + " to date time with a time based unit." ); + } + LocalDate localDate = input.getDatePart(); + LocalTime localTime = input.hasTime() ? input.getLocalTimePart() : LocalTimeValue.DEFAULT_LOCAL_TIME; + ZoneId zoneId = input.hasTimeZone() ? input.getZoneId( defaultZone ) : defaultZone.get(); + + LocalTime truncatedTime; + LocalDate truncatedDate; + if ( unit.isDateBased() ) + { + truncatedDate = DateValue.truncateTo( localDate, unit ); + truncatedTime = LocalTimeValue.DEFAULT_LOCAL_TIME; + } + else + { + truncatedDate = localDate; + truncatedTime = localTime.truncatedTo( unit ); + } + + ZonedDateTime truncatedZDT = ZonedDateTime.of( truncatedDate, truncatedTime, zoneId ); + + if ( fields.size() == 0 ) + { + return datetime( truncatedZDT ); + } + else + { + // Timezone needs some special handling, since the builder will shift keeping the instant instead of the local time + Map updatedFields = new HashMap<>( fields.size() + 1 ); + for ( Map.Entry entry : fields.entrySet() ) + { + if ( "timezone".equals( entry.getKey() ) ) + { + truncatedZDT = truncatedZDT.withZoneSameLocal( timezoneOf( entry.getValue() ) ); + } + else + { + updatedFields.put( entry.getKey(), entry.getValue() ); + } + } + + truncatedZDT = updateFieldMapWithConflictingSubseconds( updatedFields, unit, truncatedZDT ); + + if ( updatedFields.size() == 0 ) + { + return datetime( truncatedZDT ); + } + updatedFields.put( "datetime", datetime( truncatedZDT ) ); + return build( VirtualValues.map( updatedFields ), defaultZone ); + } } static DateTimeBuilder builder( Supplier defaultZone ) @@ -344,6 +399,12 @@ public boolean hasTimeZone() return true; } + @Override + boolean hasTime() + { + return true; + } + @Override public boolean equals( Value other ) { diff --git a/community/values/src/main/java/org/neo4j/values/storable/DateValue.java b/community/values/src/main/java/org/neo4j/values/storable/DateValue.java index 92f9f56a26508..c8438e20dd36a 100644 --- a/community/values/src/main/java/org/neo4j/values/storable/DateValue.java +++ b/community/values/src/main/java/org/neo4j/values/storable/DateValue.java @@ -21,21 +21,27 @@ import java.time.Clock; import java.time.DateTimeException; +import java.time.DayOfWeek; import java.time.LocalDate; import java.time.LocalTime; import java.time.OffsetTime; import java.time.ZoneId; import java.time.format.DateTimeFormatter; import java.time.temporal.ChronoField; +import java.time.temporal.ChronoUnit; import java.time.temporal.IsoFields; +import java.time.temporal.TemporalAdjusters; import java.time.temporal.TemporalUnit; +import java.time.temporal.UnsupportedTemporalTypeException; import java.util.function.Supplier; import java.util.regex.Matcher; import java.util.regex.Pattern; +import org.neo4j.helpers.collection.Pair; import org.neo4j.values.StructureBuilder; import org.neo4j.values.ValueMapper; import org.neo4j.values.virtual.MapValue; +import org.neo4j.values.virtual.VirtualValues; import static java.lang.Integer.parseInt; import static java.util.Objects.requireNonNull; @@ -111,7 +117,57 @@ public static DateValue truncate( MapValue fields, Supplier defaultZone ) { - throw new UnsupportedOperationException( "not implemented" ); + LocalDate localDate = input.getDatePart(); + DateValue truncated = date( truncateTo( localDate, unit ) ); + if ( fields.size() == 0 ) + { + return truncated; + } + else + { + MapValue updatedFields = VirtualValues.copy( fields, Pair.of( "date", truncated ) ); + return build( updatedFields, defaultZone ); + } + } + + static LocalDate truncateTo( LocalDate value, TemporalUnit unit ) + { + if ( unit == ChronoUnit.MILLENNIA ) + { + return value.with( Neo4JTemporalField.YEAR_OF_MILLENNIUM, 0 ); + } + else if ( unit == ChronoUnit.CENTURIES ) + { + return value.with( Neo4JTemporalField.YEAR_OF_CENTURY, 0 ); + } + else if ( unit == ChronoUnit.DECADES ) + { + return value.with( Neo4JTemporalField.YEAR_OF_DECADE, 0 ); + } + else if ( unit == ChronoUnit.YEARS ) + { + return value.with( TemporalAdjusters.firstDayOfYear() ); + } + else if ( unit == IsoFields.QUARTER_YEARS ) + { + return value.with( IsoFields.DAY_OF_QUARTER, 1 ); + } + else if ( unit == ChronoUnit.MONTHS ) + { + return value.with( TemporalAdjusters.firstDayOfMonth() ); + } + else if ( unit == ChronoUnit.WEEKS ) + { + return value.with( TemporalAdjusters.previousOrSame( DayOfWeek.MONDAY ) ); + } + else if ( unit == ChronoUnit.DAYS ) + { + return value; + } + else + { + throw new UnsupportedTemporalTypeException( "Unit too small for truncation: " + unit ); + } } static DateBuilder builder( Supplier defaultZone ) @@ -169,6 +225,12 @@ public boolean hasTimeZone() return false; } + @Override + boolean hasTime() + { + return false; + } + @Override public boolean equals( Value other ) { diff --git a/community/values/src/main/java/org/neo4j/values/storable/IntegralValue.java b/community/values/src/main/java/org/neo4j/values/storable/IntegralValue.java index d76e321fa2f64..047d057c70168 100644 --- a/community/values/src/main/java/org/neo4j/values/storable/IntegralValue.java +++ b/community/values/src/main/java/org/neo4j/values/storable/IntegralValue.java @@ -26,7 +26,7 @@ public abstract class IntegralValue extends NumberValue { public static long safeCastIntegral( String name, AnyValue value, long defaultValue ) { - if ( value == null ) + if ( value == null || value == Values.NO_VALUE ) { return defaultValue; } diff --git a/community/values/src/main/java/org/neo4j/values/storable/LocalDateTimeValue.java b/community/values/src/main/java/org/neo4j/values/storable/LocalDateTimeValue.java index b2ad56b8fd662..ea936fb2ce1ed 100644 --- a/community/values/src/main/java/org/neo4j/values/storable/LocalDateTimeValue.java +++ b/community/values/src/main/java/org/neo4j/values/storable/LocalDateTimeValue.java @@ -32,14 +32,17 @@ import java.time.temporal.ChronoField; import java.time.temporal.IsoFields; import java.time.temporal.TemporalUnit; +import java.util.Map; import java.util.function.Supplier; import java.util.regex.Matcher; import java.util.regex.Pattern; +import org.neo4j.helpers.collection.Pair; import org.neo4j.values.AnyValue; import org.neo4j.values.StructureBuilder; import org.neo4j.values.ValueMapper; import org.neo4j.values.virtual.MapValue; +import org.neo4j.values.virtual.VirtualValues; import static java.time.Instant.ofEpochSecond; import static java.time.LocalDateTime.ofInstant; @@ -116,7 +119,42 @@ public static LocalDateTimeValue truncate( MapValue fields, Supplier defaultZone ) { - throw new UnsupportedOperationException( "not implemented" ); + if ( unit.isTimeBased() && !(input instanceof DateTimeValue || input instanceof LocalDateTimeValue) ) + { + throw new IllegalArgumentException( "Cannot truncate " + input + " to local date time with a time based unit." ); + } + LocalTime localTime = input.hasTime() ? input.getLocalTimePart() : LocalTimeValue.DEFAULT_LOCAL_TIME; + LocalDate localDate = input.getDatePart(); + + LocalTime truncatedTime; + LocalDate truncatedDate; + if ( unit.isDateBased() ) + { + truncatedDate = DateValue.truncateTo( localDate, unit ); + truncatedTime = LocalTimeValue.DEFAULT_LOCAL_TIME; + } + else + { + truncatedDate = localDate; + truncatedTime = localTime.truncatedTo( unit ); + } + + LocalDateTime truncatedLDT = LocalDateTime.of( truncatedDate, truncatedTime ); + if ( fields.size() == 0 ) + { + return localDateTime( truncatedLDT ); + } + else + { + Map updatedFields = fields.getMapCopy(); + truncatedLDT = updateFieldMapWithConflictingSubseconds( updatedFields, unit, truncatedLDT ); + if ( updatedFields.size() == 0 ) + { + return localDateTime( truncatedLDT ); + } + updatedFields.put( "datetime", localDateTime( truncatedLDT ) ); + return build( VirtualValues.map( updatedFields ), defaultZone ); + } } static final LocalDateTime DEFAULT_LOCAL_DATE_TIME = @@ -285,6 +323,12 @@ public boolean hasTimeZone() return false; } + @Override + boolean hasTime() + { + return true; + } + @Override public boolean equals( Value other ) { diff --git a/community/values/src/main/java/org/neo4j/values/storable/LocalTimeValue.java b/community/values/src/main/java/org/neo4j/values/storable/LocalTimeValue.java index 0e90c08e49e46..8dfaddb1107bb 100644 --- a/community/values/src/main/java/org/neo4j/values/storable/LocalTimeValue.java +++ b/community/values/src/main/java/org/neo4j/values/storable/LocalTimeValue.java @@ -30,14 +30,17 @@ import java.time.format.DateTimeFormatter; import java.time.temporal.ChronoField; import java.time.temporal.TemporalUnit; +import java.util.Map; import java.util.function.Supplier; import java.util.regex.Matcher; import java.util.regex.Pattern; +import org.neo4j.helpers.collection.Pair; import org.neo4j.values.AnyValue; import org.neo4j.values.StructureBuilder; import org.neo4j.values.ValueMapper; import org.neo4j.values.virtual.MapValue; +import org.neo4j.values.virtual.VirtualValues; import static java.lang.Integer.parseInt; import static java.time.ZoneOffset.UTC; @@ -102,7 +105,23 @@ public static LocalTimeValue truncate( MapValue fields, Supplier defaultZone ) { - throw new UnsupportedOperationException( "not implemented" ); + LocalTime localTime = input.getLocalTimePart(); + LocalTime truncatedLT = localTime.truncatedTo( unit ); + if ( fields.size() == 0 ) + { + return localTime( truncatedLT ); + } + else + { + Map updatedFields = fields.getMapCopy(); + truncatedLT = updateFieldMapWithConflictingSubseconds( updatedFields, unit, truncatedLT ); + if ( updatedFields.size() == 0 ) + { + return localTime( truncatedLT ); + } + updatedFields.put( "time", localTime( truncatedLT ) ); + return build( VirtualValues.map( updatedFields ), defaultZone ); + } } static final LocalTime DEFAULT_LOCAL_TIME = LocalTime.of( Field.hour.defaultValue, Field.minute.defaultValue ); @@ -206,6 +225,12 @@ public boolean hasTimeZone() return false; } + @Override + boolean hasTime() + { + return true; + } + @Override public boolean equals( Value other ) { diff --git a/community/values/src/main/java/org/neo4j/values/storable/Neo4JTemporalField.java b/community/values/src/main/java/org/neo4j/values/storable/Neo4JTemporalField.java new file mode 100644 index 0000000000000..2b274983e01bc --- /dev/null +++ b/community/values/src/main/java/org/neo4j/values/storable/Neo4JTemporalField.java @@ -0,0 +1,131 @@ +/* + * Copyright (c) 2002-2018 "Neo Technology," + * Network Engine for Objects in Lund AB [http://neotechnology.com] + * + * This file is part of Neo4j. + * + * Neo4j is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package org.neo4j.values.storable; + +import java.time.Year; +import java.time.temporal.ChronoField; +import java.time.temporal.Temporal; +import java.time.temporal.TemporalAccessor; +import java.time.temporal.TemporalAdjusters; +import java.time.temporal.TemporalField; +import java.time.temporal.TemporalUnit; +import java.time.temporal.UnsupportedTemporalTypeException; +import java.time.temporal.ValueRange; +import java.util.Locale; + +import static java.time.temporal.ChronoUnit.CENTURIES; +import static java.time.temporal.ChronoUnit.DECADES; +import static java.time.temporal.ChronoUnit.MILLENNIA; +import static java.time.temporal.ChronoUnit.YEARS; + +public enum Neo4JTemporalField implements TemporalField +{ + + YEAR_OF_DECADE( "Year of decade", YEARS, DECADES, 10 ), + YEAR_OF_CENTURY( "Year of century", YEARS, CENTURIES, 100 ), + YEAR_OF_MILLENNIUM( "Millennium", YEARS, MILLENNIA, 1000 ); + + private final String name; + private final TemporalUnit baseUnit; + private final TemporalUnit rangeUnit; + private final int years; + private final ValueRange range; + + Neo4JTemporalField( String name, TemporalUnit baseUnit, TemporalUnit rangeUnit, int years ) + { + this.name = name; + this.baseUnit = baseUnit; + this.rangeUnit = rangeUnit; + this.years = years; + this.range = ValueRange.of( Year.MIN_VALUE / years, Year.MAX_VALUE / years ); + } + + @Override + public String getDisplayName( Locale locale ) + { + return name; + } + + @Override + public TemporalUnit getBaseUnit() + { + return baseUnit; + } + + @Override + public TemporalUnit getRangeUnit() + { + return rangeUnit; + } + + @Override + public ValueRange range() + { + return range; + } + + @Override + public boolean isDateBased() + { + return true; + } + + @Override + public boolean isTimeBased() + { + return false; + } + + @Override + public boolean isSupportedBy( TemporalAccessor temporal ) + { + return false; + } + + @Override + public ValueRange rangeRefinedBy( TemporalAccessor temporal ) + { + // Always identical + return range(); + } + + @Override + public long getFrom( TemporalAccessor temporal ) + { + throw new UnsupportedTemporalTypeException( "We don't support anything." ); + } + + @SuppressWarnings( "unchecked" ) + @Override + public R adjustInto( R temporal, long newValue ) + { + int newVal = range.checkValidIntValue( newValue, this ); + int oldYear = temporal.get( ChronoField.YEAR ); + return (R) temporal.with( ChronoField.YEAR, (oldYear / years) * years + newVal ) + .with( TemporalAdjusters.firstDayOfYear() ); + } + + @Override + public String toString() + { + return name; + } + +} diff --git a/community/values/src/main/java/org/neo4j/values/storable/TemporalValue.java b/community/values/src/main/java/org/neo4j/values/storable/TemporalValue.java index 39c4ac7b51db2..b17d9e503e163 100644 --- a/community/values/src/main/java/org/neo4j/values/storable/TemporalValue.java +++ b/community/values/src/main/java/org/neo4j/values/storable/TemporalValue.java @@ -25,6 +25,7 @@ import java.time.ZoneId; import java.time.format.DateTimeParseException; import java.time.temporal.ChronoField; +import java.time.temporal.ChronoUnit; import java.time.temporal.IsoFields; import java.time.temporal.Temporal; import java.time.temporal.TemporalAdjuster; @@ -78,6 +79,8 @@ public abstract class TemporalValue Temp assignAllFields( Temp temp ) return result; } - static int validNano( AnyValue millisecond, AnyValue microsecond, AnyValue nanosecond ) - { - long ms = safeCastIntegral( "millisecond", millisecond, Field.millisecond.defaultValue ); - long us = safeCastIntegral( "microsecond", microsecond, Field.microsecond.defaultValue ); - long ns = safeCastIntegral( "nanosecond", nanosecond, Field.nanosecond.defaultValue ); - if ( ms < 0 || ms >= 1000 ) - { - throw new IllegalArgumentException( "Invalid millisecond: " + ms ); - } - if ( us < 0 || us >= (millisecond != null || nanosecond != null ? 1000 : 1000_000) ) - { - throw new IllegalArgumentException( "Invalid microsecond: " + us ); - } - if ( ns < 0 || ns >= ((millisecond != null || microsecond != null) ? 1000 : 1000_000_000) ) - { - throw new IllegalArgumentException( "Invalid nanosecond: " + ns ); - } - return (int) (ms * 1000_000 + us * 1000 + ns); - } - @Override public final StructureBuilder add( String fieldName, AnyValue value ) { @@ -401,15 +384,6 @@ protected final ZoneId timezone() return timezone( timezone ); } - protected final ZoneId timezoneOf( AnyValue timezone ) - { - if ( timezone instanceof TextValue ) - { - return parseZoneName( ((TextValue) timezone).stringValue() ); - } - throw new UnsupportedOperationException( "Cannot convert to ZoneId: " + timezone ); - } - } protected enum Field @@ -1106,4 +1080,68 @@ static org.neo4j.values.AnyValue oneOf( org.neo4j.values.AnyValue a, org.neo4j.v { return a != null ? a : b != null ? b : c; } + + static ZoneId timezoneOf( AnyValue timezone ) + { + if ( timezone instanceof TextValue ) + { + return parseZoneName( ((TextValue) timezone).stringValue() ); + } + throw new UnsupportedOperationException( "Cannot convert to ZoneId: " + timezone ); + } + + static int validNano( AnyValue millisecond, AnyValue microsecond, AnyValue nanosecond ) + { + long ms = safeCastIntegral( "millisecond", millisecond, Field.millisecond.defaultValue ); + long us = safeCastIntegral( "microsecond", microsecond, Field.microsecond.defaultValue ); + long ns = safeCastIntegral( "nanosecond", nanosecond, Field.nanosecond.defaultValue ); + if ( ms < 0 || ms >= 1000 ) + { + throw new IllegalArgumentException( "Invalid millisecond: " + ms ); + } + if ( us < 0 || us >= (millisecond != null ? 1000 : 1000_000) ) + { + throw new IllegalArgumentException( "Invalid microsecond: " + us ); + } + if ( ns < 0 || ns >= ( microsecond != null ? 1000 : millisecond != null ? 1000_000 : 1000_000_000 ) ) + { + throw new IllegalArgumentException( "Invalid nanosecond: " + ns ); + } + return (int) (ms * 1000_000 + us * 1000 + ns); + } + + static TEMP updateFieldMapWithConflictingSubseconds( Map fields, TemporalUnit unit, TEMP truncated ) + { + boolean conflictingMilliSeconds = false; + boolean conflictingMicroSeconds = false; + + for ( Map.Entry entry : fields.entrySet() ) + { + if ( unit == ChronoUnit.MILLIS && ( "microsecond".equals( entry.getKey() ) || "nanosecond".equals( entry.getKey() ) ) ) + { + conflictingMilliSeconds = true; + } + else if ( unit == ChronoUnit.MICROS && "nanosecond".equals( entry.getKey() ) ) + { + conflictingMicroSeconds = true; + } + } + + if( conflictingMilliSeconds ) + { + AnyValue millis = Values.intValue( truncated.get( ChronoField.MILLI_OF_SECOND ) ); + AnyValue micros = fields.remove( "microsecond" ); + AnyValue nanos = fields.remove( "nanosecond" ); + int newNanos = validNano( millis, micros, nanos ); + truncated = (TEMP) truncated.with( ChronoField.NANO_OF_SECOND, newNanos ); + } + else if ( conflictingMicroSeconds ) + { + AnyValue micros = Values.intValue( truncated.get( ChronoField.MICRO_OF_SECOND ) ); + AnyValue nanos = fields.remove( "nanosecond" ); + int newNanos = validNano( null, micros, nanos ); + truncated = (TEMP) truncated.with( ChronoField.NANO_OF_SECOND, newNanos ); + } + return truncated; + } } diff --git a/community/values/src/main/java/org/neo4j/values/storable/TimeValue.java b/community/values/src/main/java/org/neo4j/values/storable/TimeValue.java index ffa277e18c467..6f422a5cbef3e 100644 --- a/community/values/src/main/java/org/neo4j/values/storable/TimeValue.java +++ b/community/values/src/main/java/org/neo4j/values/storable/TimeValue.java @@ -29,15 +29,20 @@ import java.time.ZonedDateTime; import java.time.format.DateTimeFormatter; import java.time.temporal.ChronoField; +import java.time.temporal.ChronoUnit; import java.time.temporal.TemporalUnit; +import java.util.HashMap; +import java.util.Map; import java.util.function.Supplier; import java.util.regex.Matcher; import java.util.regex.Pattern; +import org.neo4j.helpers.collection.Pair; import org.neo4j.values.AnyValue; import org.neo4j.values.StructureBuilder; import org.neo4j.values.ValueMapper; import org.neo4j.values.virtual.MapValue; +import org.neo4j.values.virtual.VirtualValues; import static java.lang.Integer.parseInt; import static java.time.ZoneOffset.UTC; @@ -100,13 +105,51 @@ public static TimeValue select( AnyValue from, Supplier defaultZone ) return builder( defaultZone ).selectTime( from ); } + @Override + boolean hasTime() + { + return true; + } + public static TimeValue truncate( TemporalUnit unit, TemporalValue input, MapValue fields, Supplier defaultZone ) { - throw new UnsupportedOperationException( "not implemented" ); + OffsetTime time = input.getTimePart( defaultZone ); + OffsetTime truncatedOT = time.truncatedTo( unit ); + + if ( fields.size() == 0 ) + { + return time( truncatedOT ); + } + else + { + // Timezone needs some special handling, since the builder will shift keeping the instant instead of the local time + Map updatedFields = new HashMap<>( fields.size() + 1 ); + for ( Map.Entry entry : fields.entrySet() ) + { + if ( "timezone".equals( entry.getKey() ) ) + { + ZoneOffset currentOffset = ZonedDateTime.ofInstant( Instant.now(), timezoneOf( entry.getValue() ) ).getOffset(); + truncatedOT = truncatedOT.withOffsetSameLocal( currentOffset ); + } + else + { + updatedFields.put( entry.getKey(), entry.getValue() ); + } + } + + truncatedOT = updateFieldMapWithConflictingSubseconds( updatedFields, unit, truncatedOT ); + + if ( updatedFields.size() == 0 ) + { + return time( truncatedOT ); + } + updatedFields.put( "time", time( truncatedOT ) ); + return build( VirtualValues.map( updatedFields ), defaultZone ); + } } static OffsetTime defaultTime( ZoneId zoneId ) diff --git a/community/values/src/main/java/org/neo4j/values/virtual/MapValue.java b/community/values/src/main/java/org/neo4j/values/virtual/MapValue.java index b416851a11021..ad9c743385776 100644 --- a/community/values/src/main/java/org/neo4j/values/virtual/MapValue.java +++ b/community/values/src/main/java/org/neo4j/values/virtual/MapValue.java @@ -21,6 +21,7 @@ import java.util.Arrays; import java.util.Comparator; +import java.util.HashMap; import java.util.Map; import java.util.Set; import java.util.function.BiConsumer; @@ -198,6 +199,11 @@ public AnyValue get( String key ) return map.getOrDefault( key, NO_VALUE ); } + public Map getMapCopy() + { + return new HashMap<>( map ); + } + @Override public String toString() { diff --git a/community/values/src/main/java/org/neo4j/values/virtual/VirtualValues.java b/community/values/src/main/java/org/neo4j/values/virtual/VirtualValues.java index 31c9e4f30e7ef..31342dee5196c 100644 --- a/community/values/src/main/java/org/neo4j/values/virtual/VirtualValues.java +++ b/community/values/src/main/java/org/neo4j/values/virtual/VirtualValues.java @@ -25,6 +25,7 @@ import java.util.Map; import java.util.function.Function; +import org.neo4j.helpers.collection.Pair; import org.neo4j.values.AnyValue; import org.neo4j.values.storable.ArrayValue; import org.neo4j.values.storable.TextArray; @@ -156,13 +157,18 @@ public static MapValue map( Map map ) return new MapValue( map ); } - public static MapValue copy( MapValue map ) + @SafeVarargs + public static MapValue copy( MapValue map, Pair... moreEntries ) { HashMap hashMap = new HashMap<>( map.size() ); for ( Map.Entry entry : map.entrySet() ) { hashMap.put( entry.getKey(), entry.getValue() ); } + for ( Pair entry : moreEntries ) + { + hashMap.put( entry.first(), entry.other() ); + } return new MapValue( hashMap ); } diff --git a/enterprise/cypher/acceptance-spec-suite/src/test/resources/blacklists/compatibility-23.txt b/enterprise/cypher/acceptance-spec-suite/src/test/resources/blacklists/compatibility-23.txt index 76fdca220705c..1de0e0d10c977 100644 --- a/enterprise/cypher/acceptance-spec-suite/src/test/resources/blacklists/compatibility-23.txt +++ b/enterprise/cypher/acceptance-spec-suite/src/test/resources/blacklists/compatibility-23.txt @@ -113,6 +113,7 @@ Feature "TemporalTruncateAcceptance": Scenario "Should truncate to month with ti Feature "TemporalTruncateAcceptance": Scenario "Should truncate to week" Feature "TemporalTruncateAcceptance": Scenario "Should truncate to week with time zone" Feature "TemporalTruncateAcceptance": Scenario "Should truncate to day" +Feature "TemporalTruncateAcceptance": Scenario "Should truncate time to day" Feature "TemporalTruncateAcceptance": Scenario "Should truncate to day with time zone" Feature "TemporalTruncateAcceptance": Scenario "Should truncate datetime to hour" Feature "TemporalTruncateAcceptance": Scenario "Should truncate localdatetime to hour" diff --git a/enterprise/cypher/acceptance-spec-suite/src/test/resources/blacklists/compatibility-31.txt b/enterprise/cypher/acceptance-spec-suite/src/test/resources/blacklists/compatibility-31.txt index 3f040d19b42e4..5a30e4ad190f3 100644 --- a/enterprise/cypher/acceptance-spec-suite/src/test/resources/blacklists/compatibility-31.txt +++ b/enterprise/cypher/acceptance-spec-suite/src/test/resources/blacklists/compatibility-31.txt @@ -36,42 +36,6 @@ Feature "TemporalAccessorAcceptance": Scenario "Should provide accessors for tim Feature "TemporalAccessorAcceptance": Scenario "Should provide accessors for local date time" Feature "TemporalAccessorAcceptance": Scenario "Should provide accessors for date time" Feature "TemporalAccessorAcceptance": Scenario "Should provide accessors for duration" -Feature "TemporalTruncateAcceptance": Scenario "Should truncate to millennium" -Feature "TemporalTruncateAcceptance": Scenario "Should truncate to millennium with time zone" -Feature "TemporalTruncateAcceptance": Scenario "Should truncate to century" -Feature "TemporalTruncateAcceptance": Scenario "Should truncate to century with time zone" -Feature "TemporalTruncateAcceptance": Scenario "Should truncate to decade" -Feature "TemporalTruncateAcceptance": Scenario "Should truncate to decade with time zone" -Feature "TemporalTruncateAcceptance": Scenario "Should truncate to year" -Feature "TemporalTruncateAcceptance": Scenario "Should truncate to year with time zone" -Feature "TemporalTruncateAcceptance": Scenario "Should truncate to quarter" -Feature "TemporalTruncateAcceptance": Scenario "Should truncate to quarter with time zone" -Feature "TemporalTruncateAcceptance": Scenario "Should truncate to month" -Feature "TemporalTruncateAcceptance": Scenario "Should truncate to month with time zone" -Feature "TemporalTruncateAcceptance": Scenario "Should truncate to week" -Feature "TemporalTruncateAcceptance": Scenario "Should truncate to week with time zone" -Feature "TemporalTruncateAcceptance": Scenario "Should truncate to day" -Feature "TemporalTruncateAcceptance": Scenario "Should truncate to day with time zone" -Feature "TemporalTruncateAcceptance": Scenario "Should truncate datetime to hour" -Feature "TemporalTruncateAcceptance": Scenario "Should truncate localdatetime to hour" -Feature "TemporalTruncateAcceptance": Scenario "Should truncate time to hour" -Feature "TemporalTruncateAcceptance": Scenario "Should truncate localtime to hour" -Feature "TemporalTruncateAcceptance": Scenario "Should truncate datetime to minute" -Feature "TemporalTruncateAcceptance": Scenario "Should truncate localdatetime to minute" -Feature "TemporalTruncateAcceptance": Scenario "Should truncate time to minute" -Feature "TemporalTruncateAcceptance": Scenario "Should truncate localtime to minute" -Feature "TemporalTruncateAcceptance": Scenario "Should truncate datetime to second" -Feature "TemporalTruncateAcceptance": Scenario "Should truncate localdatetime to second" -Feature "TemporalTruncateAcceptance": Scenario "Should truncate time to second" -Feature "TemporalTruncateAcceptance": Scenario "Should truncate localtime to second" -Feature "TemporalTruncateAcceptance": Scenario "Should truncate datetime to millisecond" -Feature "TemporalTruncateAcceptance": Scenario "Should truncate localdatetime to millisecond" -Feature "TemporalTruncateAcceptance": Scenario "Should truncate time to millisecond" -Feature "TemporalTruncateAcceptance": Scenario "Should truncate localtime to millisecond" -Feature "TemporalTruncateAcceptance": Scenario "Should truncate datetime to microsecond" -Feature "TemporalTruncateAcceptance": Scenario "Should truncate localdatetime to microsecond" -Feature "TemporalTruncateAcceptance": Scenario "Should truncate time to microsecond" -Feature "TemporalTruncateAcceptance": Scenario "Should truncate localtime to microsecond" Feature "TemporalArithmeticAcceptance": Scenario "Should add or subtract duration to or from date" Feature "TemporalArithmeticAcceptance": Scenario "Should add or subtract duration to or from local time" Feature "TemporalArithmeticAcceptance": Scenario "Should add or subtract duration to or from time" diff --git a/enterprise/cypher/acceptance-spec-suite/src/test/resources/blacklists/compatibility-33.txt b/enterprise/cypher/acceptance-spec-suite/src/test/resources/blacklists/compatibility-33.txt index cf869cab11ba9..21827a6411da0 100644 --- a/enterprise/cypher/acceptance-spec-suite/src/test/resources/blacklists/compatibility-33.txt +++ b/enterprise/cypher/acceptance-spec-suite/src/test/resources/blacklists/compatibility-33.txt @@ -20,42 +20,6 @@ Feature "TemporalAccessorAcceptance": Scenario "Should provide accessors for tim Feature "TemporalAccessorAcceptance": Scenario "Should provide accessors for local date time" Feature "TemporalAccessorAcceptance": Scenario "Should provide accessors for date time" Feature "TemporalAccessorAcceptance": Scenario "Should provide accessors for duration" -Feature "TemporalTruncateAcceptance": Scenario "Should truncate to millennium" -Feature "TemporalTruncateAcceptance": Scenario "Should truncate to millennium with time zone" -Feature "TemporalTruncateAcceptance": Scenario "Should truncate to century" -Feature "TemporalTruncateAcceptance": Scenario "Should truncate to century with time zone" -Feature "TemporalTruncateAcceptance": Scenario "Should truncate to decade" -Feature "TemporalTruncateAcceptance": Scenario "Should truncate to decade with time zone" -Feature "TemporalTruncateAcceptance": Scenario "Should truncate to year" -Feature "TemporalTruncateAcceptance": Scenario "Should truncate to year with time zone" -Feature "TemporalTruncateAcceptance": Scenario "Should truncate to quarter" -Feature "TemporalTruncateAcceptance": Scenario "Should truncate to quarter with time zone" -Feature "TemporalTruncateAcceptance": Scenario "Should truncate to month" -Feature "TemporalTruncateAcceptance": Scenario "Should truncate to month with time zone" -Feature "TemporalTruncateAcceptance": Scenario "Should truncate to week" -Feature "TemporalTruncateAcceptance": Scenario "Should truncate to week with time zone" -Feature "TemporalTruncateAcceptance": Scenario "Should truncate to day" -Feature "TemporalTruncateAcceptance": Scenario "Should truncate to day with time zone" -Feature "TemporalTruncateAcceptance": Scenario "Should truncate datetime to hour" -Feature "TemporalTruncateAcceptance": Scenario "Should truncate localdatetime to hour" -Feature "TemporalTruncateAcceptance": Scenario "Should truncate time to hour" -Feature "TemporalTruncateAcceptance": Scenario "Should truncate localtime to hour" -Feature "TemporalTruncateAcceptance": Scenario "Should truncate datetime to minute" -Feature "TemporalTruncateAcceptance": Scenario "Should truncate localdatetime to minute" -Feature "TemporalTruncateAcceptance": Scenario "Should truncate time to minute" -Feature "TemporalTruncateAcceptance": Scenario "Should truncate localtime to minute" -Feature "TemporalTruncateAcceptance": Scenario "Should truncate datetime to second" -Feature "TemporalTruncateAcceptance": Scenario "Should truncate localdatetime to second" -Feature "TemporalTruncateAcceptance": Scenario "Should truncate time to second" -Feature "TemporalTruncateAcceptance": Scenario "Should truncate localtime to second" -Feature "TemporalTruncateAcceptance": Scenario "Should truncate datetime to millisecond" -Feature "TemporalTruncateAcceptance": Scenario "Should truncate localdatetime to millisecond" -Feature "TemporalTruncateAcceptance": Scenario "Should truncate time to millisecond" -Feature "TemporalTruncateAcceptance": Scenario "Should truncate localtime to millisecond" -Feature "TemporalTruncateAcceptance": Scenario "Should truncate datetime to microsecond" -Feature "TemporalTruncateAcceptance": Scenario "Should truncate localdatetime to microsecond" -Feature "TemporalTruncateAcceptance": Scenario "Should truncate time to microsecond" -Feature "TemporalTruncateAcceptance": Scenario "Should truncate localtime to microsecond" Feature "DurationBetweenAcceptance": Scenario "Should compute duration between two temporals" Feature "DurationBetweenAcceptance": Scenario "Should compute duration between two temporals in years" Feature "DurationBetweenAcceptance": Scenario "Should compute duration between two temporals in quarters" @@ -64,4 +28,4 @@ Feature "DurationBetweenAcceptance": Scenario "Should compute duration between t Feature "DurationBetweenAcceptance": Scenario "Should compute duration between two temporals in days" Feature "DurationBetweenAcceptance": Scenario "Should compute duration between two temporals in hours" Feature "DurationBetweenAcceptance": Scenario "Should compute duration between two temporals in minutes" -Feature "DurationBetweenAcceptance": Scenario "Should compute duration between two temporals in seconds" \ No newline at end of file +Feature "DurationBetweenAcceptance": Scenario "Should compute duration between two temporals in seconds" diff --git a/enterprise/cypher/acceptance-spec-suite/src/test/resources/blacklists/cost-compiled.txt b/enterprise/cypher/acceptance-spec-suite/src/test/resources/blacklists/cost-compiled.txt index 103a5e8c33809..a99bf3edac74a 100644 --- a/enterprise/cypher/acceptance-spec-suite/src/test/resources/blacklists/cost-compiled.txt +++ b/enterprise/cypher/acceptance-spec-suite/src/test/resources/blacklists/cost-compiled.txt @@ -251,6 +251,7 @@ Feature "TemporalTruncateAcceptance": Scenario "Should truncate to month with ti Feature "TemporalTruncateAcceptance": Scenario "Should truncate to week" Feature "TemporalTruncateAcceptance": Scenario "Should truncate to week with time zone" Feature "TemporalTruncateAcceptance": Scenario "Should truncate to day" +Feature "TemporalTruncateAcceptance": Scenario "Should truncate time to day" Feature "TemporalTruncateAcceptance": Scenario "Should truncate to day with time zone" Feature "TemporalTruncateAcceptance": Scenario "Should truncate datetime to hour" Feature "TemporalTruncateAcceptance": Scenario "Should truncate localdatetime to hour" diff --git a/enterprise/cypher/acceptance-spec-suite/src/test/resources/blacklists/cost-interpreted.txt b/enterprise/cypher/acceptance-spec-suite/src/test/resources/blacklists/cost-interpreted.txt index 60c7506ed5bbd..ff46e7e0f638a 100644 --- a/enterprise/cypher/acceptance-spec-suite/src/test/resources/blacklists/cost-interpreted.txt +++ b/enterprise/cypher/acceptance-spec-suite/src/test/resources/blacklists/cost-interpreted.txt @@ -15,42 +15,6 @@ Feature "TemporalAccessorAcceptance": Scenario "Should provide accessors for tim Feature "TemporalAccessorAcceptance": Scenario "Should provide accessors for local date time" Feature "TemporalAccessorAcceptance": Scenario "Should provide accessors for date time" Feature "TemporalAccessorAcceptance": Scenario "Should provide accessors for duration" -Feature "TemporalTruncateAcceptance": Scenario "Should truncate to millennium" -Feature "TemporalTruncateAcceptance": Scenario "Should truncate to millennium with time zone" -Feature "TemporalTruncateAcceptance": Scenario "Should truncate to century" -Feature "TemporalTruncateAcceptance": Scenario "Should truncate to century with time zone" -Feature "TemporalTruncateAcceptance": Scenario "Should truncate to decade" -Feature "TemporalTruncateAcceptance": Scenario "Should truncate to decade with time zone" -Feature "TemporalTruncateAcceptance": Scenario "Should truncate to year" -Feature "TemporalTruncateAcceptance": Scenario "Should truncate to year with time zone" -Feature "TemporalTruncateAcceptance": Scenario "Should truncate to quarter" -Feature "TemporalTruncateAcceptance": Scenario "Should truncate to quarter with time zone" -Feature "TemporalTruncateAcceptance": Scenario "Should truncate to month" -Feature "TemporalTruncateAcceptance": Scenario "Should truncate to month with time zone" -Feature "TemporalTruncateAcceptance": Scenario "Should truncate to week" -Feature "TemporalTruncateAcceptance": Scenario "Should truncate to week with time zone" -Feature "TemporalTruncateAcceptance": Scenario "Should truncate to day" -Feature "TemporalTruncateAcceptance": Scenario "Should truncate to day with time zone" -Feature "TemporalTruncateAcceptance": Scenario "Should truncate datetime to hour" -Feature "TemporalTruncateAcceptance": Scenario "Should truncate localdatetime to hour" -Feature "TemporalTruncateAcceptance": Scenario "Should truncate time to hour" -Feature "TemporalTruncateAcceptance": Scenario "Should truncate localtime to hour" -Feature "TemporalTruncateAcceptance": Scenario "Should truncate datetime to minute" -Feature "TemporalTruncateAcceptance": Scenario "Should truncate localdatetime to minute" -Feature "TemporalTruncateAcceptance": Scenario "Should truncate time to minute" -Feature "TemporalTruncateAcceptance": Scenario "Should truncate localtime to minute" -Feature "TemporalTruncateAcceptance": Scenario "Should truncate datetime to second" -Feature "TemporalTruncateAcceptance": Scenario "Should truncate localdatetime to second" -Feature "TemporalTruncateAcceptance": Scenario "Should truncate time to second" -Feature "TemporalTruncateAcceptance": Scenario "Should truncate localtime to second" -Feature "TemporalTruncateAcceptance": Scenario "Should truncate datetime to millisecond" -Feature "TemporalTruncateAcceptance": Scenario "Should truncate localdatetime to millisecond" -Feature "TemporalTruncateAcceptance": Scenario "Should truncate time to millisecond" -Feature "TemporalTruncateAcceptance": Scenario "Should truncate localtime to millisecond" -Feature "TemporalTruncateAcceptance": Scenario "Should truncate datetime to microsecond" -Feature "TemporalTruncateAcceptance": Scenario "Should truncate localdatetime to microsecond" -Feature "TemporalTruncateAcceptance": Scenario "Should truncate time to microsecond" -Feature "TemporalTruncateAcceptance": Scenario "Should truncate localtime to microsecond" Feature "DurationBetweenAcceptance": Scenario "Should compute duration between two temporals" Feature "DurationBetweenAcceptance": Scenario "Should compute duration between two temporals in years" Feature "DurationBetweenAcceptance": Scenario "Should compute duration between two temporals in quarters" @@ -59,4 +23,4 @@ Feature "DurationBetweenAcceptance": Scenario "Should compute duration between t Feature "DurationBetweenAcceptance": Scenario "Should compute duration between two temporals in days" Feature "DurationBetweenAcceptance": Scenario "Should compute duration between two temporals in hours" Feature "DurationBetweenAcceptance": Scenario "Should compute duration between two temporals in minutes" -Feature "DurationBetweenAcceptance": Scenario "Should compute duration between two temporals in seconds" \ No newline at end of file +Feature "DurationBetweenAcceptance": Scenario "Should compute duration between two temporals in seconds" diff --git a/enterprise/cypher/acceptance-spec-suite/src/test/resources/blacklists/cost-slotted.txt b/enterprise/cypher/acceptance-spec-suite/src/test/resources/blacklists/cost-slotted.txt index 43f82db0e63c2..ff69149ca8217 100644 --- a/enterprise/cypher/acceptance-spec-suite/src/test/resources/blacklists/cost-slotted.txt +++ b/enterprise/cypher/acceptance-spec-suite/src/test/resources/blacklists/cost-slotted.txt @@ -14,42 +14,6 @@ Feature "TemporalAccessorAcceptance": Scenario "Should provide accessors for tim Feature "TemporalAccessorAcceptance": Scenario "Should provide accessors for local date time" Feature "TemporalAccessorAcceptance": Scenario "Should provide accessors for date time" Feature "TemporalAccessorAcceptance": Scenario "Should provide accessors for duration" -Feature "TemporalTruncateAcceptance": Scenario "Should truncate to millennium" -Feature "TemporalTruncateAcceptance": Scenario "Should truncate to millennium with time zone" -Feature "TemporalTruncateAcceptance": Scenario "Should truncate to century" -Feature "TemporalTruncateAcceptance": Scenario "Should truncate to century with time zone" -Feature "TemporalTruncateAcceptance": Scenario "Should truncate to decade" -Feature "TemporalTruncateAcceptance": Scenario "Should truncate to decade with time zone" -Feature "TemporalTruncateAcceptance": Scenario "Should truncate to year" -Feature "TemporalTruncateAcceptance": Scenario "Should truncate to year with time zone" -Feature "TemporalTruncateAcceptance": Scenario "Should truncate to quarter" -Feature "TemporalTruncateAcceptance": Scenario "Should truncate to quarter with time zone" -Feature "TemporalTruncateAcceptance": Scenario "Should truncate to month" -Feature "TemporalTruncateAcceptance": Scenario "Should truncate to month with time zone" -Feature "TemporalTruncateAcceptance": Scenario "Should truncate to week" -Feature "TemporalTruncateAcceptance": Scenario "Should truncate to week with time zone" -Feature "TemporalTruncateAcceptance": Scenario "Should truncate to day" -Feature "TemporalTruncateAcceptance": Scenario "Should truncate to day with time zone" -Feature "TemporalTruncateAcceptance": Scenario "Should truncate datetime to hour" -Feature "TemporalTruncateAcceptance": Scenario "Should truncate localdatetime to hour" -Feature "TemporalTruncateAcceptance": Scenario "Should truncate time to hour" -Feature "TemporalTruncateAcceptance": Scenario "Should truncate localtime to hour" -Feature "TemporalTruncateAcceptance": Scenario "Should truncate datetime to minute" -Feature "TemporalTruncateAcceptance": Scenario "Should truncate localdatetime to minute" -Feature "TemporalTruncateAcceptance": Scenario "Should truncate time to minute" -Feature "TemporalTruncateAcceptance": Scenario "Should truncate localtime to minute" -Feature "TemporalTruncateAcceptance": Scenario "Should truncate datetime to second" -Feature "TemporalTruncateAcceptance": Scenario "Should truncate localdatetime to second" -Feature "TemporalTruncateAcceptance": Scenario "Should truncate time to second" -Feature "TemporalTruncateAcceptance": Scenario "Should truncate localtime to second" -Feature "TemporalTruncateAcceptance": Scenario "Should truncate datetime to millisecond" -Feature "TemporalTruncateAcceptance": Scenario "Should truncate localdatetime to millisecond" -Feature "TemporalTruncateAcceptance": Scenario "Should truncate time to millisecond" -Feature "TemporalTruncateAcceptance": Scenario "Should truncate localtime to millisecond" -Feature "TemporalTruncateAcceptance": Scenario "Should truncate datetime to microsecond" -Feature "TemporalTruncateAcceptance": Scenario "Should truncate localdatetime to microsecond" -Feature "TemporalTruncateAcceptance": Scenario "Should truncate time to microsecond" -Feature "TemporalTruncateAcceptance": Scenario "Should truncate localtime to microsecond" Feature "DurationBetweenAcceptance": Scenario "Should compute duration between two temporals" Feature "DurationBetweenAcceptance": Scenario "Should compute duration between two temporals in years" Feature "DurationBetweenAcceptance": Scenario "Should compute duration between two temporals in quarters" diff --git a/enterprise/cypher/acceptance-spec-suite/src/test/resources/blacklists/default.txt b/enterprise/cypher/acceptance-spec-suite/src/test/resources/blacklists/default.txt index fa379d105ef7a..73dc0d7174847 100644 --- a/enterprise/cypher/acceptance-spec-suite/src/test/resources/blacklists/default.txt +++ b/enterprise/cypher/acceptance-spec-suite/src/test/resources/blacklists/default.txt @@ -17,42 +17,6 @@ Feature "TemporalAccessorAcceptance": Scenario "Should provide accessors for tim Feature "TemporalAccessorAcceptance": Scenario "Should provide accessors for local date time" Feature "TemporalAccessorAcceptance": Scenario "Should provide accessors for date time" Feature "TemporalAccessorAcceptance": Scenario "Should provide accessors for duration" -Feature "TemporalTruncateAcceptance": Scenario "Should truncate to millennium" -Feature "TemporalTruncateAcceptance": Scenario "Should truncate to millennium with time zone" -Feature "TemporalTruncateAcceptance": Scenario "Should truncate to century" -Feature "TemporalTruncateAcceptance": Scenario "Should truncate to century with time zone" -Feature "TemporalTruncateAcceptance": Scenario "Should truncate to decade" -Feature "TemporalTruncateAcceptance": Scenario "Should truncate to decade with time zone" -Feature "TemporalTruncateAcceptance": Scenario "Should truncate to year" -Feature "TemporalTruncateAcceptance": Scenario "Should truncate to year with time zone" -Feature "TemporalTruncateAcceptance": Scenario "Should truncate to quarter" -Feature "TemporalTruncateAcceptance": Scenario "Should truncate to quarter with time zone" -Feature "TemporalTruncateAcceptance": Scenario "Should truncate to month" -Feature "TemporalTruncateAcceptance": Scenario "Should truncate to month with time zone" -Feature "TemporalTruncateAcceptance": Scenario "Should truncate to week" -Feature "TemporalTruncateAcceptance": Scenario "Should truncate to week with time zone" -Feature "TemporalTruncateAcceptance": Scenario "Should truncate to day" -Feature "TemporalTruncateAcceptance": Scenario "Should truncate to day with time zone" -Feature "TemporalTruncateAcceptance": Scenario "Should truncate datetime to hour" -Feature "TemporalTruncateAcceptance": Scenario "Should truncate localdatetime to hour" -Feature "TemporalTruncateAcceptance": Scenario "Should truncate time to hour" -Feature "TemporalTruncateAcceptance": Scenario "Should truncate localtime to hour" -Feature "TemporalTruncateAcceptance": Scenario "Should truncate datetime to minute" -Feature "TemporalTruncateAcceptance": Scenario "Should truncate localdatetime to minute" -Feature "TemporalTruncateAcceptance": Scenario "Should truncate time to minute" -Feature "TemporalTruncateAcceptance": Scenario "Should truncate localtime to minute" -Feature "TemporalTruncateAcceptance": Scenario "Should truncate datetime to second" -Feature "TemporalTruncateAcceptance": Scenario "Should truncate localdatetime to second" -Feature "TemporalTruncateAcceptance": Scenario "Should truncate time to second" -Feature "TemporalTruncateAcceptance": Scenario "Should truncate localtime to second" -Feature "TemporalTruncateAcceptance": Scenario "Should truncate datetime to millisecond" -Feature "TemporalTruncateAcceptance": Scenario "Should truncate localdatetime to millisecond" -Feature "TemporalTruncateAcceptance": Scenario "Should truncate time to millisecond" -Feature "TemporalTruncateAcceptance": Scenario "Should truncate localtime to millisecond" -Feature "TemporalTruncateAcceptance": Scenario "Should truncate datetime to microsecond" -Feature "TemporalTruncateAcceptance": Scenario "Should truncate localdatetime to microsecond" -Feature "TemporalTruncateAcceptance": Scenario "Should truncate time to microsecond" -Feature "TemporalTruncateAcceptance": Scenario "Should truncate localtime to microsecond" Feature "DurationBetweenAcceptance": Scenario "Should compute duration between two temporals" Feature "DurationBetweenAcceptance": Scenario "Should compute duration between two temporals in years" Feature "DurationBetweenAcceptance": Scenario "Should compute duration between two temporals in quarters" diff --git a/enterprise/cypher/acceptance-spec-suite/src/test/resources/cypher/features/TemporalTruncateAcceptance.feature b/enterprise/cypher/acceptance-spec-suite/src/test/resources/cypher/features/TemporalTruncateAcceptance.feature index b1fbeb2924e10..8a4ea6bb9d4dd 100644 --- a/enterprise/cypher/acceptance-spec-suite/src/test/resources/cypher/features/TemporalTruncateAcceptance.feature +++ b/enterprise/cypher/acceptance-spec-suite/src/test/resources/cypher/features/TemporalTruncateAcceptance.feature @@ -24,27 +24,38 @@ Feature: TemporalTruncateAcceptance Given an empty graph When executing query: """ - UNWIND [datetime({year:1984, month:10, day:11, hour:12, minute:31, second:14, nanosecond: 645876123, timezone: '+01:00'}), - localdatetime({year:1984, month:10, day:11, hour:12, minute:31, second:14, nanosecond: 645876123}), - date({year:1984, month:10, day:11})] as d - RETURN datetime.truncate('millennium', d), datetime.truncate('millennium', d, {day:2}), - localdatetime.truncate('millennium', d), localdatetime.truncate('millennium', d, {day:2}), - date.truncate('millennium', d), date.truncate('millennium', d, {day:2}) + UNWIND [datetime({year:2017, month:10, day:11, hour:12, minute:31, second:14, nanosecond: 645876123, timezone: '+01:00'}), + localdatetime({year:2017, month:10, day:11, hour:12, minute:31, second:14, nanosecond: 645876123}), + date({year:2017, month:10, day:11})] as d + RETURN datetime.truncate('millennium', d) as d1, + datetime.truncate('millennium', d, {day:2}) as d2, + localdatetime.truncate('millennium', d) as d3, + localdatetime.truncate('millennium', d, {day:2}) as d4, + date.truncate('millennium', d) as d5, + date.truncate('millennium', d, {day:2}) as d6 """ Then the result should be, in order: - | d | + | d1 | d2 | d3 | d4 | d5 | d6 | + | '2000-01-01T00:00+01:00' | '2000-01-02T00:00+01:00' | '2000-01-01T00:00' | '2000-01-02T00:00' |'2000-01-01' | '2000-01-02' | + | '2000-01-01T00:00Z' | '2000-01-02T00:00Z' | '2000-01-01T00:00' | '2000-01-02T00:00' |'2000-01-01' | '2000-01-02' | + | '2000-01-01T00:00Z' | '2000-01-02T00:00Z' | '2000-01-01T00:00' | '2000-01-02T00:00' |'2000-01-01' | '2000-01-02' | + And no side effects Scenario: Should truncate to millennium with time zone Given an empty graph When executing query: """ - UNWIND [localdatetime({year:1984, month:10, day:11, hour:12, minute:31, second:14, nanosecond: 645876123}), - date({year:1984, month:10, day:11})] as d - RETURN datetime.truncate('millennium', d, {timezone:'Europe/Stockholm'}) + UNWIND [datetime({year:2017, month:10, day:11, hour:12, minute:31, second:14, nanosecond: 645876123, timezone: '-01:00'}), + localdatetime({year:2017, month:10, day:11, hour:12, minute:31, second:14, nanosecond: 645876123}), + date({year:2017, month:10, day:11})] as d + RETURN datetime.truncate('millennium', d, {timezone:'Europe/Stockholm'}) as d1 """ Then the result should be, in order: - | d | + | d1 | + | '2000-01-01T00:00+01:00[Europe/Stockholm]' | + | '2000-01-01T00:00+01:00[Europe/Stockholm]' | + | '2000-01-01T00:00+01:00[Europe/Stockholm]' | And no side effects Scenario: Should truncate to century @@ -54,24 +65,34 @@ Feature: TemporalTruncateAcceptance UNWIND [datetime({year:1984, month:10, day:11, hour:12, minute:31, second:14, nanosecond: 645876123, timezone: '+01:00'}), localdatetime({year:1984, month:10, day:11, hour:12, minute:31, second:14, nanosecond: 645876123}), date({year:1984, month:10, day:11})] as d - RETURN datetime.truncate('century', d), datetime.truncate('century', d, {day:2}), - localdatetime.truncate('century', d), localdatetime.truncate('century', d, {day:2}), - date.truncate('century', d), date.truncate('century', d, {day:2}) + RETURN datetime.truncate('century', d) as d1, + datetime.truncate('century', d, {day:2}) as d2, + localdatetime.truncate('century', d) as d3, + localdatetime.truncate('century', d, {day:2}) as d4, + date.truncate('century', d) as d5, + date.truncate('century', d, {day:2}) as d6 """ Then the result should be, in order: - | d | + | d1 | d2 | d3 | d4 | d5 | d6 | + | '1900-01-01T00:00+01:00' | '1900-01-02T00:00+01:00' | '1900-01-01T00:00' | '1900-01-02T00:00' |'1900-01-01' | '1900-01-02' | + | '1900-01-01T00:00Z' | '1900-01-02T00:00Z' | '1900-01-01T00:00' | '1900-01-02T00:00' |'1900-01-01' | '1900-01-02' | + | '1900-01-01T00:00Z' | '1900-01-02T00:00Z' | '1900-01-01T00:00' | '1900-01-02T00:00' |'1900-01-01' | '1900-01-02' | And no side effects Scenario: Should truncate to century with time zone Given an empty graph When executing query: """ - UNWIND [localdatetime({year:1984, month:10, day:11, hour:12, minute:31, second:14, nanosecond: 645876123}), - date({year:1984, month:10, day:11})] as d - RETURN datetime.truncate('century', d, {timezone:'Europe/Stockholm'}) + UNWIND [datetime({year:2017, month:10, day:11, hour:12, minute:31, second:14, nanosecond: 645876123, timezone: '-01:00'}), + localdatetime({year:2017, month:10, day:11, hour:12, minute:31, second:14, nanosecond: 645876123}), + date({year:2017, month:10, day:11})] as d + RETURN datetime.truncate('century', d, {timezone:'Europe/Stockholm'}) as d1 """ Then the result should be, in order: - | d | + | d1 | + | '2000-01-01T00:00+01:00[Europe/Stockholm]' | + | '2000-01-01T00:00+01:00[Europe/Stockholm]' | + | '2000-01-01T00:00+01:00[Europe/Stockholm]' | And no side effects Scenario: Should truncate to decade @@ -81,24 +102,34 @@ Feature: TemporalTruncateAcceptance UNWIND [datetime({year:1984, month:10, day:11, hour:12, minute:31, second:14, nanosecond: 645876123, timezone: '+01:00'}), localdatetime({year:1984, month:10, day:11, hour:12, minute:31, second:14, nanosecond: 645876123}), date({year:1984, month:10, day:11})] as d - RETURN datetime.truncate('decade', d), datetime.truncate('decade', d, {day:2}), - localdatetime.truncate('decade', d), localdatetime.truncate('decade', d, {day:2}), - date.truncate('decade', d), date.truncate('decade', d, {day:2}) + RETURN datetime.truncate('decade', d) as d1, + datetime.truncate('decade', d, {day:2}) as d2, + localdatetime.truncate('decade', d) as d3, + localdatetime.truncate('decade', d, {day:2}) as d4, + date.truncate('decade', d) as d5, + date.truncate('decade', d, {day:2}) as d6 """ Then the result should be, in order: - | d | + | d1 | d2 | d3 | d4 | d5 | d6 | + | '1980-01-01T00:00+01:00' | '1980-01-02T00:00+01:00' | '1980-01-01T00:00' | '1980-01-02T00:00' |'1980-01-01' | '1980-01-02' | + | '1980-01-01T00:00Z' | '1980-01-02T00:00Z' | '1980-01-01T00:00' | '1980-01-02T00:00' |'1980-01-01' | '1980-01-02' | + | '1980-01-01T00:00Z' | '1980-01-02T00:00Z' | '1980-01-01T00:00' | '1980-01-02T00:00' |'1980-01-01' | '1980-01-02' | And no side effects Scenario: Should truncate to decade with time zone Given an empty graph When executing query: """ - UNWIND [localdatetime({year:1984, month:10, day:11, hour:12, minute:31, second:14, nanosecond: 645876123}), + UNWIND [datetime({year:1984, month:10, day:11, hour:12, minute:31, second:14, nanosecond: 645876123, timezone: '-01:00'}), + localdatetime({year:1984, month:10, day:11, hour:12, minute:31, second:14, nanosecond: 645876123}), date({year:1984, month:10, day:11})] as d - RETURN datetime.truncate('decade', d, {timezone:'Europe/Stockholm'}) + RETURN datetime.truncate('decade', d, {timezone:'Europe/Stockholm'}) as d1 """ Then the result should be, in order: - | d | + | d1 | + | '1980-01-01T00:00+01:00[Europe/Stockholm]' | + | '1980-01-01T00:00+01:00[Europe/Stockholm]' | + | '1980-01-01T00:00+01:00[Europe/Stockholm]' | And no side effects Scenario: Should truncate to year @@ -108,51 +139,71 @@ Feature: TemporalTruncateAcceptance UNWIND [datetime({year:1984, month:10, day:11, hour:12, minute:31, second:14, nanosecond: 645876123, timezone: '+01:00'}), localdatetime({year:1984, month:10, day:11, hour:12, minute:31, second:14, nanosecond: 645876123}), date({year:1984, month:10, day:11})] as d - RETURN datetime.truncate('year', d), datetime.truncate('year', d, {day:2}), - localdatetime.truncate('year', d), localdatetime.truncate('year', d, {day:2}), - date.truncate('year', d), date.truncate('year', d, {day:2}) + RETURN datetime.truncate('year', d) as d1, + datetime.truncate('year', d, {day:2}) as d2, + localdatetime.truncate('year', d) as d3, + localdatetime.truncate('year', d, {day:2}) as d4, + date.truncate('year', d) as d5, + date.truncate('year', d, {day:2}) as d6 """ Then the result should be, in order: - | d | + | d1 | d2 | d3 | d4 | d5 | d6 | + | '1984-01-01T00:00+01:00' | '1984-01-02T00:00+01:00' | '1984-01-01T00:00' | '1984-01-02T00:00' |'1984-01-01' | '1984-01-02' | + | '1984-01-01T00:00Z' | '1984-01-02T00:00Z' | '1984-01-01T00:00' | '1984-01-02T00:00' |'1984-01-01' | '1984-01-02' | + | '1984-01-01T00:00Z' | '1984-01-02T00:00Z' | '1984-01-01T00:00' | '1984-01-02T00:00' |'1984-01-01' | '1984-01-02' | And no side effects Scenario: Should truncate to year with time zone Given an empty graph When executing query: """ - UNWIND [localdatetime({year:1984, month:10, day:11, hour:12, minute:31, second:14, nanosecond: 645876123}), + UNWIND [datetime({year:1984, month:10, day:11, hour:12, minute:31, second:14, nanosecond: 645876123, timezone: '-01:00'}), + localdatetime({year:1984, month:10, day:11, hour:12, minute:31, second:14, nanosecond: 645876123}), date({year:1984, month:10, day:11})] as d - RETURN datetime.truncate('year', d, {timezone:'Europe/Stockholm'}) + RETURN datetime.truncate('year', d, {timezone:'Europe/Stockholm'}) as d1 """ Then the result should be, in order: - | d | + | d1 | + | '1984-01-01T00:00+01:00[Europe/Stockholm]' | + | '1984-01-01T00:00+01:00[Europe/Stockholm]' | + | '1984-01-01T00:00+01:00[Europe/Stockholm]' | And no side effects Scenario: Should truncate to quarter Given an empty graph When executing query: """ - UNWIND [datetime({year:1984, month:10, day:11, hour:12, minute:31, second:14, nanosecond: 645876123, timezone: '+01:00'}), - localdatetime({year:1984, month:10, day:11, hour:12, minute:31, second:14, nanosecond: 645876123}), - date({year:1984, month:10, day:11})] as d - RETURN datetime.truncate('quarter', d), datetime.truncate('quarter', d, {day:2}), - localdatetime.truncate('quarter', d), localdatetime.truncate('quarter', d, {day:2}), - date.truncate('quarter', d), date.truncate('quarter', d, {day:2}) + UNWIND [datetime({year:1984, month:11, day:11, hour:12, minute:31, second:14, nanosecond: 645876123, timezone: '+01:00'}), + localdatetime({year:1984, month:11, day:11, hour:12, minute:31, second:14, nanosecond: 645876123}), + date({year:1984, month:11, day:11})] as d + RETURN datetime.truncate('quarter', d) as d1, + datetime.truncate('quarter', d, {day:2}) as d2, + localdatetime.truncate('quarter', d) as d3, + localdatetime.truncate('quarter', d, {day:2}) as d4, + date.truncate('quarter', d) as d5, + date.truncate('quarter', d, {day:2}) as d6 """ Then the result should be, in order: - | d | + | d1 | d2 | d3 | d4 | d5 | d6 | + | '1984-10-01T00:00+01:00' | '1984-10-02T00:00+01:00' | '1984-10-01T00:00' | '1984-10-02T00:00' |'1984-10-01' | '1984-10-02' | + | '1984-10-01T00:00Z' | '1984-10-02T00:00Z' | '1984-10-01T00:00' | '1984-10-02T00:00' |'1984-10-01' | '1984-10-02' | + | '1984-10-01T00:00Z' | '1984-10-02T00:00Z' | '1984-10-01T00:00' | '1984-10-02T00:00' |'1984-10-01' | '1984-10-02' | And no side effects Scenario: Should truncate to quarter with time zone Given an empty graph When executing query: """ - UNWIND [localdatetime({year:1984, month:10, day:11, hour:12, minute:31, second:14, nanosecond: 645876123}), - date({year:1984, month:10, day:11})] as d - RETURN datetime.truncate('quarter', d, {timezone:'Europe/Stockholm'}) + UNWIND [datetime({year:1984, month:11, day:11, hour:12, minute:31, second:14, nanosecond: 645876123, timezone: '-01:00'}), + localdatetime({year:1984, month:11, day:11, hour:12, minute:31, second:14, nanosecond: 645876123}), + date({year:1984, month:11, day:11})] as d + RETURN datetime.truncate('quarter', d, {timezone:'Europe/Stockholm'}) as d1 """ Then the result should be, in order: - | d | + | d1 | + | '1984-10-01T00:00+01:00[Europe/Stockholm]' | + | '1984-10-01T00:00+01:00[Europe/Stockholm]' | + | '1984-10-01T00:00+01:00[Europe/Stockholm]' | And no side effects Scenario: Should truncate to month @@ -162,24 +213,34 @@ Feature: TemporalTruncateAcceptance UNWIND [datetime({year:1984, month:10, day:11, hour:12, minute:31, second:14, nanosecond: 645876123, timezone: '+01:00'}), localdatetime({year:1984, month:10, day:11, hour:12, minute:31, second:14, nanosecond: 645876123}), date({year:1984, month:10, day:11})] as d - RETURN datetime.truncate('month', d), datetime.truncate('month', d, {day:2}), - localdatetime.truncate('month', d), localdatetime.truncate('month', d, {day:2}), - date.truncate('month', d), date.truncate('month', d, {day:2}) + RETURN datetime.truncate('month', d) as d1, + datetime.truncate('month', d, {day:2}) as d2, + localdatetime.truncate('month', d) as d3, + localdatetime.truncate('month', d, {day:2}) as d4, + date.truncate('month', d) as d5, + date.truncate('month', d, {day:2}) as d6 """ Then the result should be, in order: - | d | + | d1 | d2 | d3 | d4 | d5 | d6 | + | '1984-10-01T00:00+01:00' | '1984-10-02T00:00+01:00' | '1984-10-01T00:00' | '1984-10-02T00:00' |'1984-10-01' | '1984-10-02' | + | '1984-10-01T00:00Z' | '1984-10-02T00:00Z' | '1984-10-01T00:00' | '1984-10-02T00:00' |'1984-10-01' | '1984-10-02' | + | '1984-10-01T00:00Z' | '1984-10-02T00:00Z' | '1984-10-01T00:00' | '1984-10-02T00:00' |'1984-10-01' | '1984-10-02' | And no side effects Scenario: Should truncate to month with time zone Given an empty graph When executing query: """ - UNWIND [localdatetime({year:1984, month:10, day:11, hour:12, minute:31, second:14, nanosecond: 645876123}), + UNWIND [datetime({year:1984, month:10, day:11, hour:12, minute:31, second:14, nanosecond: 645876123, timezone: '-01:00'}), + localdatetime({year:1984, month:10, day:11, hour:12, minute:31, second:14, nanosecond: 645876123}), date({year:1984, month:10, day:11})] as d - RETURN datetime.truncate('month', d, {timezone:'Europe/Stockholm'}) + RETURN datetime.truncate('month', d, {timezone:'Europe/Stockholm'}) as d1 """ Then the result should be, in order: - | d | + | d1 | + | '1984-10-01T00:00+01:00[Europe/Stockholm]' | + | '1984-10-01T00:00+01:00[Europe/Stockholm]' | + | '1984-10-01T00:00+01:00[Europe/Stockholm]' | And no side effects Scenario: Should truncate to week @@ -189,24 +250,34 @@ Feature: TemporalTruncateAcceptance UNWIND [datetime({year:1984, month:10, day:11, hour:12, minute:31, second:14, nanosecond: 645876123, timezone: '+01:00'}), localdatetime({year:1984, month:10, day:11, hour:12, minute:31, second:14, nanosecond: 645876123}), date({year:1984, month:10, day:11})] as d - RETURN datetime.truncate('week', d), datetime.truncate('week', d, {dayOfWeek:2}), - localdatetime.truncate('week', d), localdatetime.truncate('week', d, {dayOfWeek:2}), - date.truncate('week', d), date.truncate('week', d, {dayOfWeek:2}) + RETURN datetime.truncate('week', d) as d1, + datetime.truncate('week', d, {dayOfWeek:2}) as d2, + localdatetime.truncate('week', d) as d3, + localdatetime.truncate('week', d, {dayOfWeek:2}) as d4, + date.truncate('week', d) as d5, + date.truncate('week', d, {dayOfWeek:2}) as d6 """ Then the result should be, in order: - | d | + | d1 | d2 | d3 | d4 | d5 | d6 | + | '1984-10-08T00:00+01:00' | '1984-10-09T00:00+01:00' | '1984-10-08T00:00' | '1984-10-09T00:00' |'1984-10-08' | '1984-10-09' | + | '1984-10-08T00:00Z' | '1984-10-09T00:00Z' | '1984-10-08T00:00' | '1984-10-09T00:00' |'1984-10-08' | '1984-10-09' | + | '1984-10-08T00:00Z' | '1984-10-09T00:00Z' | '1984-10-08T00:00' | '1984-10-09T00:00' |'1984-10-08' | '1984-10-09' | And no side effects Scenario: Should truncate to week with time zone Given an empty graph When executing query: """ - UNWIND [localdatetime({year:1984, month:10, day:11, hour:12, minute:31, second:14, nanosecond: 645876123}), + UNWIND [datetime({year:1984, month:10, day:11, hour:12, minute:31, second:14, nanosecond: 645876123, timezone: '-01:00'}), + localdatetime({year:1984, month:10, day:11, hour:12, minute:31, second:14, nanosecond: 645876123}), date({year:1984, month:10, day:11})] as d - RETURN datetime.truncate('week', d, {timezone:'Europe/Stockholm'}) + RETURN datetime.truncate('week', d, {timezone:'Europe/Stockholm'}) as d1 """ Then the result should be, in order: - | d | + | d1 | + | '1984-10-08T00:00+01:00[Europe/Stockholm]' | + | '1984-10-08T00:00+01:00[Europe/Stockholm]' | + | '1984-10-08T00:00+01:00[Europe/Stockholm]' | And no side effects Scenario: Should truncate to day @@ -216,35 +287,66 @@ Feature: TemporalTruncateAcceptance UNWIND [datetime({year:1984, month:10, day:11, hour:12, minute:31, second:14, nanosecond: 645876123, timezone: '+01:00'}), localdatetime({year:1984, month:10, day:11, hour:12, minute:31, second:14, nanosecond: 645876123}), date({year:1984, month:10, day:11})] as d - RETURN datetime.truncate('day', d), datetime.truncate('day', d, {nanosecond:2}), - localdatetime.truncate('day', d), localdatetime.truncate('day', d, {nanosecond:2}), - date.truncate('day', d) + RETURN datetime.truncate('day', d) as d1, + datetime.truncate('day', d, {nanosecond:2}) as d2, + localdatetime.truncate('day', d) as d3, + localdatetime.truncate('day', d, {nanosecond:2}) as d4, + date.truncate('day', d) as d5 """ Then the result should be, in order: - | d | + | d1 | d2 | d3 | d4 | d5 | + | '1984-10-11T00:00+01:00' | '1984-10-11T00:00:00.000000002+01:00' | '1984-10-11T00:00' | '1984-10-11T00:00:00.000000002' |'1984-10-11' | + | '1984-10-11T00:00Z' | '1984-10-11T00:00:00.000000002Z' | '1984-10-11T00:00' | '1984-10-11T00:00:00.000000002' |'1984-10-11' | + | '1984-10-11T00:00Z' | '1984-10-11T00:00:00.000000002Z' | '1984-10-11T00:00' | '1984-10-11T00:00:00.000000002' |'1984-10-11' | And no side effects + Scenario: Should truncate time to day + Given an empty graph + When executing query: + """ + UNWIND [datetime({year:1984, month:10, day:11, hour:12, minute:31, second:14, nanosecond: 645876123, timezone: '+01:00'}), + localdatetime({year:1984, month:10, day:11, hour:12, minute:31, second:14, nanosecond: 645876123})] as d + RETURN time.truncate('day', d) as d1, + time.truncate('day', d, {nanosecond:2}) as d2, + localtime.truncate('day', d) as d3, + localtime.truncate('day', d, {nanosecond:2}) as d4 + """ + Then the result should be, in order: + | d1 | d2 | d3 | d4 | + | '00:00+01:00' | '00:00:00.000000002+01:00' | '00:00' | '00:00:00.000000002' | + | '00:00Z' | '00:00:00.000000002Z' | '00:00' | '00:00:00.000000002' | + + And no side effects Scenario: Should truncate to day with time zone Given an empty graph When executing query: """ - UNWIND [localdatetime({year:1984, month:10, day:11, hour:12, minute:31, second:14, nanosecond: 645876123}), + UNWIND [datetime({year:1984, month:10, day:11, hour:12, minute:31, second:14, nanosecond: 645876123, timezone: '-01:00'}), + localdatetime({year:1984, month:10, day:11, hour:12, minute:31, second:14, nanosecond: 645876123}), date({year:1984, month:10, day:11})] as d - RETURN datetime.truncate('day', d, {timezone:'Europe/Stockholm'}) + RETURN datetime.truncate('day', d, {timezone:'Europe/Stockholm'}) as d1 """ Then the result should be, in order: - | d | + | d1 | + | '1984-10-11T00:00+01:00[Europe/Stockholm]' | + | '1984-10-11T00:00+01:00[Europe/Stockholm]' | + | '1984-10-11T00:00+01:00[Europe/Stockholm]' | And no side effects Scenario: Should truncate datetime to hour Given an empty graph When executing query: """ - UNWIND [datetime({year:1984, month:10, day:11, hour:12, minute:31, second:14, nanosecond: 645876123, timezone: '+01:00'})] as d - RETURN datetime.truncate('hour', d), datetime.truncate('hour', d, {nanosecond:2}) + UNWIND [datetime({year:1984, month:10, day:11, hour:12, minute:31, second:14, nanosecond: 645876123, timezone: '-01:00'}), + localdatetime({year:1984, month:10, day:11, hour:12, minute:31, second:14, nanosecond: 645876123})] as d + RETURN datetime.truncate('hour', d) as d1, + datetime.truncate('hour', d, {nanosecond:2}) as d2, + datetime.truncate('hour', d, {timezone: 'Europe/Stockholm'}) as d3 """ Then the result should be, in order: - | d | + | d1 | d2 | d3 | + | '1984-10-11T12:00-01:00' | '1984-10-11T12:00:00.000000002-01:00' | '1984-10-11T12:00+01:00[Europe/Stockholm]' | + | '1984-10-11T12:00Z' | '1984-10-11T12:00:00.000000002Z' | '1984-10-11T12:00+01:00[Europe/Stockholm]' | And no side effects Scenario: Should truncate localdatetime to hour @@ -253,24 +355,33 @@ Feature: TemporalTruncateAcceptance """ UNWIND [datetime({year:1984, month:10, day:11, hour:12, minute:31, second:14, nanosecond: 645876123, timezone: '+01:00'}), localdatetime({year:1984, month:10, day:11, hour:12, minute:31, second:14, nanosecond: 645876123})] as d - RETURN localdatetime.truncate('hour', d), localdatetime.truncate('hour', d, {nanosecond:2}) + RETURN localdatetime.truncate('hour', d) as d1, + localdatetime.truncate('hour', d, {nanosecond:2}) as d2 """ Then the result should be, in order: - | d | + | d1 | d2 | + | '1984-10-11T12:00' | '1984-10-11T12:00:00.000000002' | + | '1984-10-11T12:00' | '1984-10-11T12:00:00.000000002' | And no side effects Scenario: Should truncate time to hour Given an empty graph When executing query: """ - UNWIND [datetime({year:1984, month:10, day:11, hour:12, minute:31, second:14, nanosecond: 645876123, timezone: '+01:00'}), + UNWIND [datetime({year:1984, month:10, day:11, hour:12, minute:31, second:14, nanosecond: 645876123, timezone: '-01:00'}), localdatetime({year:1984, month:10, day:11, hour:12, minute:31, second:14, nanosecond: 645876123}), - time({hour:12, minute:31, second:14, nanosecond: 645876123, timezone: '+01:00'}), + time({hour:12, minute:31, second:14, nanosecond: 645876123, timezone: '-01:00'}), localtime({hour:12, minute:31, second:14, nanosecond: 645876123})] as d - RETURN time.truncate('hour', d), time.truncate('hour', d, {nanosecond:2}) + RETURN time.truncate('hour', d) as d1, + time.truncate('hour', d, {nanosecond:2}) as d2, + time.truncate('hour', d, {timezone: 'Europe/Stockholm'}) as d3 """ Then the result should be, in order: - | d | + | d1 | d2 | d3 | + | '12:00-01:00' | '12:00:00.000000002-01:00' | '12:00+01:00' | + | '12:00Z' | '12:00:00.000000002Z' | '12:00+01:00' | + | '12:00-01:00' | '12:00:00.000000002-01:00' | '12:00+01:00' | + | '12:00Z' | '12:00:00.000000002Z' | '12:00+01:00' | And no side effects Scenario: Should truncate localtime to hour @@ -281,21 +392,31 @@ Feature: TemporalTruncateAcceptance localdatetime({year:1984, month:10, day:11, hour:12, minute:31, second:14, nanosecond: 645876123}), time({hour:12, minute:31, second:14, nanosecond: 645876123, timezone: '+01:00'}), localtime({hour:12, minute:31, second:14, nanosecond: 645876123})] as d - RETURN localtime.truncate('hour', d), localtime.truncate('hour', d, , {nanosecond:2}) + RETURN localtime.truncate('hour', d) as d1, + localtime.truncate('hour', d, {nanosecond:2}) as d2 """ Then the result should be, in order: - | d | + | d1 | d2 | + | '12:00' | '12:00:00.000000002' | + | '12:00' | '12:00:00.000000002' | + | '12:00' | '12:00:00.000000002' | + | '12:00' | '12:00:00.000000002' | And no side effects Scenario: Should truncate datetime to minute Given an empty graph When executing query: """ - UNWIND [datetime({year:1984, month:10, day:11, hour:12, minute:31, second:14, nanosecond: 645876123, timezone: '+01:00'})] as d - RETURN datetime.truncate('minute', d), datetime.truncate('minute', d, {nanosecond:2}) + UNWIND [datetime({year:1984, month:10, day:11, hour:12, minute:31, second:14, nanosecond: 645876123, timezone: '-01:00'}), + localdatetime({year:1984, month:10, day:11, hour:12, minute:31, second:14, nanosecond: 645876123})] as d + RETURN datetime.truncate('minute', d) as d1, + datetime.truncate('minute', d, {nanosecond:2}) as d2, + datetime.truncate('minute', d, {timezone: 'Europe/Stockholm'}) as d3 """ Then the result should be, in order: - | d | + | d1 | d2 | d3 | + | '1984-10-11T12:31-01:00' | '1984-10-11T12:31:00.000000002-01:00' | '1984-10-11T12:31+01:00[Europe/Stockholm]' | + | '1984-10-11T12:31Z' | '1984-10-11T12:31:00.000000002Z' | '1984-10-11T12:31+01:00[Europe/Stockholm]' | And no side effects Scenario: Should truncate localdatetime to minute @@ -304,10 +425,13 @@ Feature: TemporalTruncateAcceptance """ UNWIND [datetime({year:1984, month:10, day:11, hour:12, minute:31, second:14, nanosecond: 645876123, timezone: '+01:00'}), localdatetime({year:1984, month:10, day:11, hour:12, minute:31, second:14, nanosecond: 645876123})] as d - RETURN localdatetime.truncate('minute', d), localdatetime.truncate('minute', d, {nanosecond:2}) + RETURN localdatetime.truncate('minute', d) as d1, + localdatetime.truncate('minute', d, {nanosecond:2}) as d2 """ Then the result should be, in order: - | d | + | d1 | d2 | + | '1984-10-11T12:31' | '1984-10-11T12:31:00.000000002' | + | '1984-10-11T12:31' | '1984-10-11T12:31:00.000000002' | And no side effects Scenario: Should truncate time to minute @@ -318,10 +442,15 @@ Feature: TemporalTruncateAcceptance localdatetime({year:1984, month:10, day:11, hour:12, minute:31, second:14, nanosecond: 645876123}), time({hour:12, minute:31, second:14, nanosecond: 645876123, timezone: '+01:00'}), localtime({hour:12, minute:31, second:14, nanosecond: 645876123})] as d - RETURN time.truncate('minute', d), time.truncate('minute', d, {nanosecond:2}) + RETURN time.truncate('minute', d) as d1, + time.truncate('minute', d, {nanosecond:2}) as d2 """ Then the result should be, in order: - | d | + | d1 | d2 | + | '12:31+01:00' | '12:31:00.000000002+01:00' | + | '12:31Z' | '12:31:00.000000002Z' | + | '12:31+01:00' | '12:31:00.000000002+01:00' | + | '12:31Z' | '12:31:00.000000002Z' | And no side effects Scenario: Should truncate localtime to minute @@ -332,21 +461,30 @@ Feature: TemporalTruncateAcceptance localdatetime({year:1984, month:10, day:11, hour:12, minute:31, second:14, nanosecond: 645876123}), time({hour:12, minute:31, second:14, nanosecond: 645876123, timezone: '+01:00'}), localtime({hour:12, minute:31, second:14, nanosecond: 645876123})] as d - RETURN localtime.truncate('minute', d), localtime.truncate('minute', d, {nanosecond:2}) + RETURN localtime.truncate('minute', d) as d1, + localtime.truncate('minute', d, {nanosecond:2}) as d2 """ Then the result should be, in order: - | d | - And no side effects + | d1 | d2 | + | '12:31' | '12:31:00.000000002' | + | '12:31' | '12:31:00.000000002' | + | '12:31' | '12:31:00.000000002' | + | '12:31' | '12:31:00.000000002' | + And no side effects Scenario: Should truncate datetime to second Given an empty graph When executing query: """ - UNWIND [datetime({year:1984, month:10, day:11, hour:12, minute:31, second:14, nanosecond: 645876123, timezone: '+01:00'})] as d - RETURN datetime.truncate('second', d), datetime.truncate('second', d, {nanosecond:2}) + UNWIND [datetime({year:1984, month:10, day:11, hour:12, minute:31, second:14, nanosecond: 645876123, timezone: '+01:00'}), + localdatetime({year:1984, month:10, day:11, hour:12, minute:31, second:14, nanosecond: 645876123})] as d + RETURN datetime.truncate('second', d) as d1, + datetime.truncate('second', d, {nanosecond:2}) as d2 """ Then the result should be, in order: - | d | + | d1 | d2 | + | '1984-10-11T12:31:14+01:00' | '1984-10-11T12:31:14.000000002+01:00' | + | '1984-10-11T12:31:14Z' | '1984-10-11T12:31:14.000000002Z' | And no side effects Scenario: Should truncate localdatetime to second @@ -355,10 +493,13 @@ Feature: TemporalTruncateAcceptance """ UNWIND [datetime({year:1984, month:10, day:11, hour:12, minute:31, second:14, nanosecond: 645876123, timezone: '+01:00'}), localdatetime({year:1984, month:10, day:11, hour:12, minute:31, second:14, nanosecond: 645876123})] as d - RETURN localdatetime.truncate('second', d), localdatetime.truncate('second', d, {nanosecond:2}) + RETURN localdatetime.truncate('second', d) as d1, + localdatetime.truncate('second', d, {nanosecond:2}) as d2 """ Then the result should be, in order: - | d | + | d1 | d2 | + | '1984-10-11T12:31:14' | '1984-10-11T12:31:14.000000002' | + | '1984-10-11T12:31:14' | '1984-10-11T12:31:14.000000002' | And no side effects Scenario: Should truncate time to second @@ -369,10 +510,15 @@ Feature: TemporalTruncateAcceptance localdatetime({year:1984, month:10, day:11, hour:12, minute:31, second:14, nanosecond: 645876123}), time({hour:12, minute:31, second:14, nanosecond: 645876123, timezone: '+01:00'}), localtime({hour:12, minute:31, second:14, nanosecond: 645876123})] as d - RETURN time.truncate('second', d), time.truncate('second', d, {nanosecond:2}) + RETURN time.truncate('second', d) as d1, + time.truncate('second', d, {nanosecond:2}) as d2 """ Then the result should be, in order: - | d | + | d1 | d2 | + | '12:31:14+01:00' | '12:31:14.000000002+01:00' | + | '12:31:14Z' | '12:31:14.000000002Z' | + | '12:31:14+01:00' | '12:31:14.000000002+01:00' | + | '12:31:14Z' | '12:31:14.000000002Z' | And no side effects Scenario: Should truncate localtime to second @@ -383,21 +529,30 @@ Feature: TemporalTruncateAcceptance localdatetime({year:1984, month:10, day:11, hour:12, minute:31, second:14, nanosecond: 645876123}), time({hour:12, minute:31, second:14, nanosecond: 645876123, timezone: '+01:00'}), localtime({hour:12, minute:31, second:14, nanosecond: 645876123})] as d - RETURN localtime.truncate('second', d), localtime.truncate('second', d, {nanosecond:2}) + RETURN localtime.truncate('second', d) as d1, + localtime.truncate('second', d, {nanosecond:2}) as d2 """ Then the result should be, in order: - | d | + | d1 | d2 | + | '12:31:14' | '12:31:14.000000002' | + | '12:31:14' | '12:31:14.000000002' | + | '12:31:14' | '12:31:14.000000002' | + | '12:31:14' | '12:31:14.000000002' | And no side effects Scenario: Should truncate datetime to millisecond Given an empty graph When executing query: """ - UNWIND [datetime({year:1984, month:10, day:11, hour:12, minute:31, second:14, nanosecond: 645876123, timezone: '+01:00'})] as d - RETURN datetime.truncate('millisecond', d), datetime.truncate('millisecond', d, {nanosecond:2}) + UNWIND [datetime({year:1984, month:10, day:11, hour:12, minute:31, second:14, nanosecond: 645876123, timezone: '+01:00'}), + localdatetime({year:1984, month:10, day:11, hour:12, minute:31, second:14, nanosecond: 645876123})] as d + RETURN datetime.truncate('millisecond', d) as d1, + datetime.truncate('millisecond', d, {nanosecond:2}) as d2 """ Then the result should be, in order: - | d | + | d1 | d2 | + | '1984-10-11T12:31:14.645+01:00' | '1984-10-11T12:31:14.645000002+01:00' | + | '1984-10-11T12:31:14.645Z' | '1984-10-11T12:31:14.645000002Z' | And no side effects Scenario: Should truncate localdatetime to millisecond @@ -406,10 +561,13 @@ Feature: TemporalTruncateAcceptance """ UNWIND [datetime({year:1984, month:10, day:11, hour:12, minute:31, second:14, nanosecond: 645876123, timezone: '+01:00'}), localdatetime({year:1984, month:10, day:11, hour:12, minute:31, second:14, nanosecond: 645876123})] as d - RETURN localdatetime.truncate('millisecond', d), localdatetime.truncate('millisecond', d, {nanosecond:2}) + RETURN localdatetime.truncate('millisecond', d) as d1, + localdatetime.truncate('millisecond', d, {nanosecond:2}) as d2 """ Then the result should be, in order: - | d | + | d1 | d2 | + | '1984-10-11T12:31:14.645' | '1984-10-11T12:31:14.645000002' | + | '1984-10-11T12:31:14.645' | '1984-10-11T12:31:14.645000002' | And no side effects Scenario: Should truncate time to millisecond @@ -420,10 +578,15 @@ Feature: TemporalTruncateAcceptance localdatetime({year:1984, month:10, day:11, hour:12, minute:31, second:14, nanosecond: 645876123}), time({hour:12, minute:31, second:14, nanosecond: 645876123, timezone: '+01:00'}), localtime({hour:12, minute:31, second:14, nanosecond: 645876123})] as d - RETURN time.truncate('millisecond', d), time.truncate('millisecond', d, {nanosecond:2}) + RETURN time.truncate('millisecond', d) as d1, + time.truncate('millisecond', d, {nanosecond:2}) as d2 """ Then the result should be, in order: - | d | + | d1 | d2 | + | '12:31:14.645+01:00' | '12:31:14.645000002+01:00' | + | '12:31:14.645Z' | '12:31:14.645000002Z' | + | '12:31:14.645+01:00' | '12:31:14.645000002+01:00' | + | '12:31:14.645Z' | '12:31:14.645000002Z' | And no side effects Scenario: Should truncate localtime to millisecond @@ -434,21 +597,30 @@ Feature: TemporalTruncateAcceptance localdatetime({year:1984, month:10, day:11, hour:12, minute:31, second:14, nanosecond: 645876123}), time({hour:12, minute:31, second:14, nanosecond: 645876123, timezone: '+01:00'}), localtime({hour:12, minute:31, second:14, nanosecond: 645876123})] as d - RETURN localtime.truncate('millisecond', d), localtime.truncate('millisecond', d, {nanosecond:2}) + RETURN localtime.truncate('millisecond', d) as d1, + localtime.truncate('millisecond', d, {nanosecond:2}) as d2 """ Then the result should be, in order: - | d | + | d1 | d2 | + | '12:31:14.645' | '12:31:14.645000002' | + | '12:31:14.645' | '12:31:14.645000002' | + | '12:31:14.645' | '12:31:14.645000002' | + | '12:31:14.645' | '12:31:14.645000002' | And no side effects Scenario: Should truncate datetime to microsecond Given an empty graph When executing query: """ - UNWIND [datetime({year:1984, month:10, day:11, hour:12, minute:31, second:14, nanosecond: 645876123, timezone: '+01:00'})] as d - RETURN datetime.truncate('microsecond', d), datetime.truncate('microsecond', d, {nanosecond:2}) + UNWIND [datetime({year:1984, month:10, day:11, hour:12, minute:31, second:14, nanosecond: 645876123, timezone: '+01:00'}), + localdatetime({year:1984, month:10, day:11, hour:12, minute:31, second:14, nanosecond: 645876123})] as d + RETURN datetime.truncate('microsecond', d) as d1, + datetime.truncate('microsecond', d, {nanosecond:2}) as d2 """ Then the result should be, in order: - | d | + | d1 | d2 | + | '1984-10-11T12:31:14.645876+01:00' | '1984-10-11T12:31:14.645876002+01:00' | + | '1984-10-11T12:31:14.645876Z' | '1984-10-11T12:31:14.645876002Z' | And no side effects Scenario: Should truncate localdatetime to microsecond @@ -457,10 +629,13 @@ Feature: TemporalTruncateAcceptance """ UNWIND [datetime({year:1984, month:10, day:11, hour:12, minute:31, second:14, nanosecond: 645876123, timezone: '+01:00'}), localdatetime({year:1984, month:10, day:11, hour:12, minute:31, second:14, nanosecond: 645876123})] as d - RETURN localdatetime.truncate('microsecond', d), localdatetime.truncate('microsecond', d, {nanosecond:2}) + RETURN localdatetime.truncate('microsecond', d) as d1, + localdatetime.truncate('microsecond', d, {nanosecond:2}) as d2 """ Then the result should be, in order: - | d | + | d1 | d2 | + | '1984-10-11T12:31:14.645876' | '1984-10-11T12:31:14.645876002' | + | '1984-10-11T12:31:14.645876' | '1984-10-11T12:31:14.645876002' | And no side effects Scenario: Should truncate time to microsecond @@ -471,10 +646,15 @@ Feature: TemporalTruncateAcceptance localdatetime({year:1984, month:10, day:11, hour:12, minute:31, second:14, nanosecond: 645876123}), time({hour:12, minute:31, second:14, nanosecond: 645876123, timezone: '+01:00'}), localtime({hour:12, minute:31, second:14, nanosecond: 645876123})] as d - RETURN time.truncate('microsecond', d), time.truncate('microsecond', d, {nanosecond:2}) + RETURN time.truncate('microsecond', d) as d1, + time.truncate('microsecond', d, {nanosecond:2}) as d2 """ Then the result should be, in order: - | d | + | d1 | d2 | + | '12:31:14.645876+01:00' | '12:31:14.645876002+01:00' | + | '12:31:14.645876Z' | '12:31:14.645876002Z' | + | '12:31:14.645876+01:00' | '12:31:14.645876002+01:00' | + | '12:31:14.645876Z' | '12:31:14.645876002Z' | And no side effects Scenario: Should truncate localtime to microsecond @@ -485,8 +665,13 @@ Feature: TemporalTruncateAcceptance localdatetime({year:1984, month:10, day:11, hour:12, minute:31, second:14, nanosecond: 645876123}), time({hour:12, minute:31, second:14, nanosecond: 645876123, timezone: '+01:00'}), localtime({hour:12, minute:31, second:14, nanosecond: 645876123})] as d - RETURN localtime.truncate('microsecond', d), localtime.truncate('microsecond', d, {nanosecond:2}) + RETURN localtime.truncate('microsecond', d) as d1, + localtime.truncate('microsecond', d, {nanosecond:2}) as d2 """ Then the result should be, in order: - | d | + | d1 | d2 | + | '12:31:14.645876' | '12:31:14.645876002' | + | '12:31:14.645876' | '12:31:14.645876002' | + | '12:31:14.645876' | '12:31:14.645876002' | + | '12:31:14.645876' | '12:31:14.645876002' | And no side effects diff --git a/enterprise/cypher/acceptance-spec-suite/src/test/scala/org/neo4j/internal/cypher/acceptance/TemporalAcceptanceTest.scala b/enterprise/cypher/acceptance-spec-suite/src/test/scala/org/neo4j/internal/cypher/acceptance/TemporalAcceptanceTest.scala index b4f2137b4ac06..84c8f75ccc51b 100644 --- a/enterprise/cypher/acceptance-spec-suite/src/test/scala/org/neo4j/internal/cypher/acceptance/TemporalAcceptanceTest.scala +++ b/enterprise/cypher/acceptance-spec-suite/src/test/scala/org/neo4j/internal/cypher/acceptance/TemporalAcceptanceTest.scala @@ -19,6 +19,7 @@ */ package org.neo4j.internal.cypher.acceptance +import java.time.temporal.UnsupportedTemporalTypeException import java.time.format.DateTimeParseException import org.neo4j.cypher._ @@ -182,233 +183,223 @@ class TemporalAcceptanceTest extends ExecutionEngineFunSuite with QueryStatistic // Truncating with wrong receiver or argument - ignore("should not truncate to millennium with wrong receiver") { - shouldNotTruncate(Seq("time", "localtime"), "millennium", + test("should not truncate to millennium with wrong receiver") { + shouldNotTruncate[UnsupportedTemporalTypeException](Seq("time", "localtime"), "millennium", Seq("datetime({year:1984, month: 2, day:11, hour: 12, minute: 30, second: 40, timezone:'+01:00'})")) } - ignore("should not truncate to millennium with wrong argument") { - shouldNotTruncate(Seq("datetime", "localdatetime", "date"), "millennium", + test("should not truncate to millennium with wrong argument") { + shouldNotTruncate[IllegalArgumentException](Seq("datetime", "localdatetime", "date"), "millennium", Seq("time({hour: 12, minute: 30, second: 40, timezone:'+01:00'})", "localtime({hour: 12, minute: 30, second: 40})")) } - ignore("should not truncate to century with wrong receiver") { - shouldNotTruncate(Seq("time", "localtime"), "century", + test("should not truncate to century with wrong receiver") { + shouldNotTruncate[UnsupportedTemporalTypeException](Seq("time", "localtime"), "century", Seq("datetime({year:1984, month: 2, day:11, hour: 12, minute: 30, second: 40, timezone:'+01:00'})")) } - ignore("should not truncate to century with wrong argument") { - shouldNotTruncate(Seq("datetime", "localdatetime", "date"), "century", + test("should not truncate to century with wrong argument") { + shouldNotTruncate[IllegalArgumentException](Seq("datetime", "localdatetime", "date"), "century", Seq("time({hour: 12, minute: 30, second: 40, timezone:'+01:00'})", "localtime({hour: 12, minute: 30, second: 40})")) } - ignore("should not truncate to decade with wrong receiver") { - shouldNotTruncate(Seq("time", "localtime"), "decade", + test("should not truncate to decade with wrong receiver") { + shouldNotTruncate[UnsupportedTemporalTypeException](Seq("time", "localtime"), "decade", Seq("datetime({year:1984, month: 2, day:11, hour: 12, minute: 30, second: 40, timezone:'+01:00'})")) } - ignore("should not truncate to decade with wrong argument") { - shouldNotTruncate(Seq("datetime", "localdatetime", "date"), "decade", + test("should not truncate to decade with wrong argument") { + shouldNotTruncate[IllegalArgumentException](Seq("datetime", "localdatetime", "date"), "decade", Seq("time({hour: 12, minute: 30, second: 40, timezone:'+01:00'})", "localtime({hour: 12, minute: 30, second: 40})")) } - ignore("should not truncate to year with wrong receiver") { - shouldNotTruncate(Seq("time", "localtime"), "year", + test("should not truncate to year with wrong receiver") { + shouldNotTruncate[UnsupportedTemporalTypeException](Seq("time", "localtime"), "year", Seq("datetime({year:1984, month: 2, day:11, hour: 12, minute: 30, second: 40, timezone:'+01:00'})")) } - ignore("should not truncate to year with wrong argument") { - shouldNotTruncate(Seq("datetime", "localdatetime", "date"), "year", + test("should not truncate to year with wrong argument") { + shouldNotTruncate[IllegalArgumentException](Seq("datetime", "localdatetime", "date"), "year", Seq("time({hour: 12, minute: 30, second: 40, timezone:'+01:00'})", "localtime({hour: 12, minute: 30, second: 40})")) } - ignore("should not truncate to quarter with wrong receiver") { - shouldNotTruncate(Seq("time", "localtime"), "quarter", + test("should not truncate to quarter with wrong receiver") { + shouldNotTruncate[UnsupportedTemporalTypeException](Seq("time", "localtime"), "quarter", Seq("datetime({year:1984, month: 2, day:11, hour: 12, minute: 30, second: 40, timezone:'+01:00'})")) } - ignore("should not truncate to quarter with wrong argument") { - shouldNotTruncate(Seq("datetime", "localdatetime", "date"), "quarter", + test("should not truncate to quarter with wrong argument") { + shouldNotTruncate[IllegalArgumentException](Seq("datetime", "localdatetime", "date"), "quarter", Seq("time({hour: 12, minute: 30, second: 40, timezone:'+01:00'})", "localtime({hour: 12, minute: 30, second: 40})")) } - ignore("should not truncate to month with wrong receiver") { - shouldNotTruncate(Seq("time", "localtime"), "month", + test("should not truncate to month with wrong receiver") { + shouldNotTruncate[UnsupportedTemporalTypeException](Seq("time", "localtime"), "month", Seq("datetime({year:1984, month: 2, day:11, hour: 12, minute: 30, second: 40, timezone:'+01:00'})")) } - ignore("should not truncate to month with wrong argument") { - shouldNotTruncate(Seq("datetime", "localdatetime", "date"), "month", + test("should not truncate to month with wrong argument") { + shouldNotTruncate[IllegalArgumentException](Seq("datetime", "localdatetime", "date"), "month", Seq("time({hour: 12, minute: 30, second: 40, timezone:'+01:00'})", "localtime({hour: 12, minute: 30, second: 40})")) } - ignore("should not truncate to week with wrong receiver") { - shouldNotTruncate(Seq("time", "localtime"), "week", + test("should not truncate to week with wrong receiver") { + shouldNotTruncate[UnsupportedTemporalTypeException](Seq("time", "localtime"), "week", Seq("datetime({year:1984, month: 2, day:11, hour: 12, minute: 30, second: 40, timezone:'+01:00'})")) } - ignore("should not truncate to week with wrong argument") { - shouldNotTruncate(Seq("datetime", "localdatetime", "date"), "week", + test("should not truncate to week with wrong argument") { + shouldNotTruncate[IllegalArgumentException](Seq("datetime", "localdatetime", "date"), "week", Seq("time({hour: 12, minute: 30, second: 40, timezone:'+01:00'})", "localtime({hour: 12, minute: 30, second: 40})")) } - ignore("should not truncate to day with wrong receiver") { - shouldNotTruncate(Seq("time", "localtime"), "day", - Seq("datetime({year:1984, month: 2, day:11, hour: 12, minute: 30, second: 40, timezone:'+01:00'})")) - } - - ignore("should not truncate to day with wrong argument") { - shouldNotTruncate(Seq("datetime", "localdatetime", "date"), "day", + test("should not truncate to day with wrong argument") { + shouldNotTruncate[IllegalArgumentException](Seq("datetime", "localdatetime", "date"), "day", Seq("time({hour: 12, minute: 30, second: 40, timezone:'+01:00'})", "localtime({hour: 12, minute: 30, second: 40})")) } - ignore("should not truncate to hour with wrong receiver") { - shouldNotTruncate(Seq("date"), "hour", + test("should not truncate to hour with wrong receiver") { + shouldNotTruncate[UnsupportedTemporalTypeException](Seq("date"), "hour", Seq("datetime({year:1984, month: 2, day:11, hour: 12, minute: 30, second: 40, timezone:'+01:00'})")) } - ignore("should not truncate datetime to hour with wrong argument") { - shouldNotTruncate(Seq("datetime"), "hour", + test("should not truncate datetime to hour with wrong argument") { + shouldNotTruncate[IllegalArgumentException](Seq("datetime"), "hour", Seq("date({year:1984, month: 2, day:11})", "time({hour: 12, minute: 30, second: 40, timezone:'+01:00'})", - "localtime({hour: 12, minute: 30, second: 40})", - "localdatetime({year:1984, month:10, day:11, hour:12, minute:31, second:14, nanosecond: 645876123})")) + "localtime({hour: 12, minute: 30, second: 40})")) } - ignore("should not truncate localdatetime to hour with wrong argument") { - shouldNotTruncate(Seq("localdatetime"), "hour", + test("should not truncate localdatetime to hour with wrong argument") { + shouldNotTruncate[IllegalArgumentException](Seq("localdatetime"), "hour", Seq("date({year:1984, month: 2, day:11})", "time({hour: 12, minute: 30, second: 40, timezone:'+01:00'})", "localtime({hour: 12, minute: 30, second: 40})")) } - ignore("should not truncate time to hour with wrong argument") { - shouldNotTruncate(Seq("time"), "hour", + test("should not truncate time to hour with wrong argument") { + shouldNotTruncate[IllegalArgumentException](Seq("time"), "hour", Seq("date({year:1984, month: 2, day:11})")) } - ignore("should not truncate localtime to hour with wrong argument") { - shouldNotTruncate(Seq("localtime"), "hour", + test("should not truncate localtime to hour with wrong argument") { + shouldNotTruncate[IllegalArgumentException](Seq("localtime"), "hour", Seq("date({year:1984, month: 2, day:11})")) } - ignore("should not truncate to minute with wrong receiver") { - shouldNotTruncate(Seq("date"), "minute", + test("should not truncate to minute with wrong receiver") { + shouldNotTruncate[UnsupportedTemporalTypeException](Seq("date"), "minute", Seq("datetime({year:1984, month: 2, day:11, hour: 12, minute: 30, second: 40, timezone:'+01:00'})")) } - ignore("should not truncate datetime to minute with wrong argument") { - shouldNotTruncate(Seq("datetime"), "minute", + test("should not truncate datetime to minute with wrong argument") { + shouldNotTruncate[IllegalArgumentException](Seq("datetime"), "minute", Seq("date({year:1984, month: 2, day:11})", "time({hour: 12, minute: 30, second: 40, timezone:'+01:00'})", - "localtime({hour: 12, minute: 30, second: 40})", - "localdatetime({year:1984, month:10, day:11, hour:12, minute:31, second:14, nanosecond: 645876123})")) + "localtime({hour: 12, minute: 30, second: 40})")) } - ignore("should not truncate localdatetime to minute with wrong argument") { - shouldNotTruncate(Seq("localdatetime"), "minute", + test("should not truncate localdatetime to minute with wrong argument") { + shouldNotTruncate[IllegalArgumentException](Seq("localdatetime"), "minute", Seq("date({year:1984, month: 2, day:11})", "time({hour: 12, minute: 30, second: 40, timezone:'+01:00'})", "localtime({hour: 12, minute: 30, second: 40})")) } - ignore("should not truncate time to minute with wrong argument") { - shouldNotTruncate(Seq("time"), "minute", + test("should not truncate time to minute with wrong argument") { + shouldNotTruncate[IllegalArgumentException](Seq("time"), "minute", Seq("date({year:1984, month: 2, day:11})")) } - ignore("should not truncate localtime to minute with wrong argument") { - shouldNotTruncate(Seq("localtime"), "minute", + test("should not truncate localtime to minute with wrong argument") { + shouldNotTruncate[IllegalArgumentException](Seq("localtime"), "minute", Seq("date({year:1984, month: 2, day:11})")) } - ignore("should not truncate to second with wrong receiver") { - shouldNotTruncate(Seq("date"), "second", + test("should not truncate to second with wrong receiver") { + shouldNotTruncate[UnsupportedTemporalTypeException](Seq("date"), "second", Seq("datetime({year:1984, month: 2, day:11, hour: 12, minute: 30, second: 40, timezone:'+01:00'})")) } - ignore("should not truncate datetime to second with wrong argument") { - shouldNotTruncate(Seq("datetime"), "second", + test("should not truncate datetime to second with wrong argument") { + shouldNotTruncate[IllegalArgumentException](Seq("datetime"), "second", Seq("date({year:1984, month: 2, day:11})", "time({hour: 12, minute: 30, second: 40, timezone:'+01:00'})", - "localtime({hour: 12, minute: 30, second: 40})", - "localdatetime({year:1984, month:10, day:11, hour:12, minute:31, second:14, nanosecond: 645876123})")) + "localtime({hour: 12, minute: 30, second: 40})")) } - ignore("should not truncate localdatetime to second with wrong argument") { - shouldNotTruncate(Seq("localdatetime"), "second", + test("should not truncate localdatetime to second with wrong argument") { + shouldNotTruncate[IllegalArgumentException](Seq("localdatetime"), "second", Seq("date({year:1984, month: 2, day:11})", "time({hour: 12, minute: 30, second: 40, timezone:'+01:00'})", "localtime({hour: 12, minute: 30, second: 40})")) } - ignore("should not truncate time to second with wrong argument") { - shouldNotTruncate(Seq("time"), "second", + test("should not truncate time to second with wrong argument") { + shouldNotTruncate[IllegalArgumentException](Seq("time"), "second", Seq("date({year:1984, month: 2, day:11})")) } - ignore("should not truncate localtime to second with wrong argument") { - shouldNotTruncate(Seq("localtime"), "second", + test("should not truncate localtime to second with wrong argument") { + shouldNotTruncate[IllegalArgumentException](Seq("localtime"), "second", Seq("date({year:1984, month: 2, day:11})")) } - ignore("should not truncate to millisecond with wrong receiver") { - shouldNotTruncate(Seq("date"), "millisecond", + test("should not truncate to millisecond with wrong receiver") { + shouldNotTruncate[UnsupportedTemporalTypeException](Seq("date"), "millisecond", Seq("datetime({year:1984, month: 2, day:11, hour: 12, minute: 30, second: 40, timezone:'+01:00'})")) } - ignore("should not truncate datetime to millisecond with wrong argument") { - shouldNotTruncate(Seq("datetime"), "millisecond", + test("should not truncate datetime to millisecond with wrong argument") { + shouldNotTruncate[IllegalArgumentException](Seq("datetime"), "millisecond", Seq("date({year:1984, month: 2, day:11})", "time({hour: 12, minute: 30, second: 40, timezone:'+01:00'})", - "localtime({hour: 12, minute: 30, second: 40})", - "localdatetime({year:1984, month:10, day:11, hour:12, minute:31, second:14, nanosecond: 645876123})")) + "localtime({hour: 12, minute: 30, second: 40})")) } - ignore("should not truncate localdatetime to millisecond with wrong argument") { - shouldNotTruncate(Seq("localdatetime"), "millisecond", + test("should not truncate localdatetime to millisecond with wrong argument") { + shouldNotTruncate[IllegalArgumentException](Seq("localdatetime"), "millisecond", Seq("date({year:1984, month: 2, day:11})", "time({hour: 12, minute: 30, second: 40, timezone:'+01:00'})", "localtime({hour: 12, minute: 30, second: 40})")) } - ignore("should not truncate time to millisecond with wrong argument") { - shouldNotTruncate(Seq("time"), "millisecond", + test("should not truncate time to millisecond with wrong argument") { + shouldNotTruncate[IllegalArgumentException](Seq("time"), "millisecond", Seq("date({year:1984, month: 2, day:11})")) } - ignore("should not truncate localtime to millisecond with wrong argument") { - shouldNotTruncate(Seq("localtime"), "millisecond", + test("should not truncate localtime to millisecond with wrong argument") { + shouldNotTruncate[IllegalArgumentException](Seq("localtime"), "millisecond", Seq("date({year:1984, month: 2, day:11})")) } - ignore("should not truncate to microsecond with wrong receiver") { - shouldNotTruncate(Seq("date"), "microsecond", + test("should not truncate to microsecond with wrong receiver") { + shouldNotTruncate[UnsupportedTemporalTypeException](Seq("date"), "microsecond", Seq("datetime({year:1984, month: 2, day:11, hour: 12, minute: 30, second: 40, timezone:'+01:00'})")) } - ignore("should not truncate datetime to microsecond with wrong argument") { - shouldNotTruncate(Seq("datetime"), "microsecond", + test("should not truncate datetime to microsecond with wrong argument") { + shouldNotTruncate[IllegalArgumentException](Seq("datetime"), "microsecond", Seq("date({year:1984, month: 2, day:11})", "time({hour: 12, minute: 30, second: 40, timezone:'+01:00'})", - "localtime({hour: 12, minute: 30, second: 40})", - "localdatetime({year:1984, month:10, day:11, hour:12, minute:31, second:14, nanosecond: 645876123})")) + "localtime({hour: 12, minute: 30, second: 40})")) } - ignore("should not truncate localdatetime to microsecond with wrong argument") { - shouldNotTruncate(Seq("localdatetime"), "microsecond", + test("should not truncate localdatetime to microsecond with wrong argument") { + shouldNotTruncate[IllegalArgumentException](Seq("localdatetime"), "microsecond", Seq("date({year:1984, month: 2, day:11})", "time({hour: 12, minute: 30, second: 40, timezone:'+01:00'})", "localtime({hour: 12, minute: 30, second: 40})")) } - ignore("should not truncate time to microsecond with wrong argument") { - shouldNotTruncate(Seq("time"), "microsecond", + test("should not truncate time to microsecond with wrong argument") { + shouldNotTruncate[IllegalArgumentException](Seq("time"), "microsecond", Seq("date({year:1984, month: 2, day:11})")) } - ignore("should not truncate localtime to microsecond with wrong argument") { - shouldNotTruncate(Seq("localtime"), "microsecond", + test("should not truncate localtime to microsecond with wrong argument") { + shouldNotTruncate[IllegalArgumentException](Seq("localtime"), "microsecond", Seq("date({year:1984, month: 2, day:11})")) } @@ -437,11 +428,11 @@ class TemporalAcceptanceTest extends ExecutionEngineFunSuite with QueryStatistic } } - private def shouldNotTruncate(receivers: Seq[String], truncationUnit: String, args: Seq[String]): Unit = { + private def shouldNotTruncate[E : Manifest](receivers: Seq[String], truncationUnit: String, args: Seq[String]): Unit = { for (receiver <- receivers; arg <- args) { val query = s"RETURN $receiver.truncate('$truncationUnit', $arg)" withClue(s"Executing $query") { - an[IllegalArgumentException] shouldBe thrownBy { + an[E] shouldBe thrownBy { println(graph.execute(query).next()) } }