Skip to content

Commit 9829c01

Browse files
committed
Merge branch '3.8-dev'
2 parents 49cad09 + a0c5851 commit 9829c01

47 files changed

Lines changed: 807 additions & 138 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

CHANGELOG.asciidoc

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -65,8 +65,7 @@ image::https://raw.githubusercontent.com/apache/tinkerpop/master/docs/static/ima
6565
* Added `auth` module in `gremlin-python` for pluggable authentication.
6666
* Fixed `GremlinLangScriptEngine` handling for some strategies.
6767
* Updated Docker test suite set-up in `gremlin-python` to work with HTTP driver/server.
68-
* Added `DateTime` serializer for Java and Python according for GraphBinaryV4.
69-
* Replaced `Date` with `OffsetDateTime` in Java core.
68+
* Updated `DateTime` serializers for Java and Python according to GraphBinaryV4.
7069
* Defined GraphBinaryV4 specification.
7170
* Defined GraphSONV4 specification.
7271
* Update serializers for `label` of an `Element` as a singleton list of string for GraphBinaryV4.
@@ -119,6 +118,8 @@ This release also includes changes from <<release-3-7-XXX, 3.7.XXX>>.
119118
* Fixed bug in `group()` value traversal of the second `by()` where a `CollectingBarrierStep` could produce an unexpected filtering effect when `ReducingBarrierStep` or `SupplyingBarrierStep` instances were not taken into account.
120119
* Changed `DetachedFactory` to special case the handling of `ComputerAdjacentVertex` which doesn't carry properties but still needs to be detachable for OLAP cases.
121120
* Deprecated `ProfilingAware.prepareForProfiling` method preferring to simply `resetBarrierFromValueTraversal` from the `Grouping` interface after strategy application.
121+
* Deprecated `Date` in favor of `OffsetDateTime` as the default date type in core, `Date` is still supported as input to date steps for compatibility.
122+
* Added and made `OffsetDateTime` serializers the default for existing date types in Python, Go, JavaScript, and .NET. `Date` is only used to deserialize from server.
122123
* Added missing strategies in `gremlin-go`, updated certain strategies to take varargs and updated `GoTranslatorVisitor` for corresponding translations.
123124
* Fixed `BigInt` and `BigDecimal` parsing in `gremlin-go` cucumber test suite, fixed `UnscaledValue` type in `BigDecimal` struct and added `ParseBigDecimal` method.
124125
* Added validation to `groupCount()` to prevent an invalid usage of multiple `by()` modulators.

docs/src/reference/the-traversal.asciidoc

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -816,7 +816,7 @@ The `asDate()`-step (*map*) converts string or numeric input to Date.
816816
For string input only ISO-8601 format is supported. For numbers, the value is considered as the number of the
817817
milliseconds since "the epoch" (January 1, 1970, 00:00:00 GMT). Date input is passed without changes.
818818
819-
If the incoming traverser is not a string, number or Date then an `IllegalArgumentException` will be thrown.
819+
If the incoming traverser is not a string, number, Date or OffsetDateTime then an `IllegalArgumentException` will be thrown.
820820
821821
[gremlin-groovy,modern]
822822
----
@@ -1358,7 +1358,7 @@ link:++https://tinkerpop.apache.org/javadocs/x.y.z/core/org/apache/tinkerpop/gre
13581358
=== DateAdd Step
13591359
13601360
The `dateAdd()`-step (*map*) returns the value with the addition of the value number of units as specified by the DateToken.
1361-
If the incoming traverser is not a Date, then an `IllegalArgumentException` will be thrown.
1361+
If the incoming traverser is not a Date or OffsetDateTime, then an `IllegalArgumentException` will be thrown.
13621362
13631363
[gremlin-groovy,modern]
13641364
----
@@ -1377,7 +1377,7 @@ link:++https://tinkerpop.apache.org/javadocs/x.y.z/core/org/apache/tinkerpop/gre
13771377
=== DateDiff Step
13781378
13791379
The `dateDiff()`-step (*map*) returns the difference between two Dates in epoch time.
1380-
If the incoming traverser is not a Date, then an `IllegalArgumentException` will be thrown.
1380+
If the incoming traverser is not a Date or OffsetDateTime, then an `IllegalArgumentException` will be thrown.
13811381
13821382
[gremlin-groovy,modern]
13831383
----
@@ -1389,6 +1389,7 @@ g.inject("2023-08-02T00:00:00Z").asDate().dateDiff(constant("2023-08-03T00:00:00
13891389
*Additional References*
13901390
13911391
link:++https://tinkerpop.apache.org/javadocs/x.y.z/core/org/apache/tinkerpop/gremlin/process/traversal/dsl/graph/GraphTraversal.html#dateDiff(java.util.Date)++[`dateDiff(Date)`],
1392+
link:++https://tinkerpop.apache.org/javadocs/x.y.z/core/org/apache/tinkerpop/gremlin/process/traversal/dsl/graph/GraphTraversal.html#dateDiff(java.util.Date)++[`dateDiff(OffsetDateTime)`],
13921393
link:++https://tinkerpop.apache.org/javadocs/x.y.z/core/org/apache/tinkerpop/gremlin/process/traversal/dsl/graph/GraphTraversal.html#dateDiff(org.apache.tinkerpop.gremlin.process.traversal.Traversal)++[`dateDiff(Traversal)`]
13931394
13941395
[[dedup-step]]

docs/src/upgrade/release-3.8.x.asciidoc

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,17 @@ complete list of all the modifications that are part of this release.
3030
3131
=== Upgrading for Users
3232
33+
==== The Switch from Date to OffsetDateTime
34+
The default implementation for date type in Gremlin is now changed from the `java.util.Date` to the more encompassing `java.time.OffsetDateTime`. This means the reference implementation for all date manipulation steps, `asDate()`, `dateAdd()`, and `dateDiff()`, as well as helper methods `datetime()`, will return `OffsetDateTime`, whose string representation will be in ISO 8601 format.
35+
36+
`Date` is still supported as incoming traverser results for these steps, as well as input into `dateDiff()` for compatibility purposes. All dates are assumed to be in `UTC` (given epoch time).
37+
38+
If one is using a persisted TinkerGraph that stored `Date` objects inside properties, one may notice `OffsetDateTime` being returned after traversal manipulation. The recommended solution is to update all existing `Date` objects into `OffsetDateTime`. This can be done by querying for the properties and transforming them using `asDate()`. Do note that all dates are assumed to be in `UTC` (given epoch time).
39+
40+
For Python, Go, JavaScript, and .NET GLVs, the existing date types are retained. The change is at the serialization level, where the exiting date type will be serialized as `OffsetDateTime` to the server, and both `Date` and `OffsetDateTime` from the server will be deserialized into the existing date types in the host language. As such, users of these GLVs should not notice impact to the application code. The caution remains in cases when client is accessing a database with `Date` object stored, the `Date` to `OffsetDateTime` transformations on the server assumes `UTC` timezone.
41+
42+
For Java GLV, this change would impact users who are expecting the old `Date` object from a traversal in their application, in this case the recommendation is to update code to expect `OffsetDateTime` as part of the version upgrade.
43+
3344
==== Simplification to g creation
3445
The creation of "g" is the start point to writing Gremlin. There are a number of ways to create it, but TinkerPop has
3546
long recommended the use of the anonymous `traversal()` function for this creation.
@@ -284,4 +295,16 @@ See: link:https://issues.apache.org/jira/browse/TINKERPOP-3121[TINKERPOP-3121]
284295
285296
==== Graph System Providers
286297
287-
==== Graph Driver Providers
298+
==== The Switch from Date to OffsetDateTime
299+
The default implementation for date type in Gremlin is now changed from the deprecated `java.util.Date` to the more encompassing `java.time.OffsetDateTime`. This means the reference implementation for all date manipulation steps, `asDate()`, `dateAdd()`, and `dateDiff()`, as well as helper methods `datetime()`, will return `OffsetDateTime`, whose string representation will be in ISO 8601 format.
300+
301+
`Date` is still supported as incoming traverser results for these steps, as well as input into `dateDiff()` for compatibility purposes. All dates are assumed to be in `UTC` (given epoch time).
302+
303+
This may impact providers who use TinkerGraph or whose implementation store dates as `java.util.Date`. While steps will support `Date`, all date manipulations will output `OffsetDateTime`. If a user had persisted `Date` objects in the database, upgrading to 3.8 may lead to the database having both types stored. It is recommended for users to perform transformation of `Date` to `OffsetDateTime` to retain consistency.
304+
305+
==== Graph Driver Providers
306+
307+
==== The Switch from Date to OffsetDateTime
308+
The default implementation for date type in Gremlin is now changed from the deprecated `java.util.Date` to the more encompassing `java.time.OffsetDateTime`. This means the reference implementation for all date manipulation steps, `asDate()`, `dateAdd()`, and `dateDiff()`, as well as helper methods `datetime()`, will return `OffsetDateTime`, whose string representation will be in ISO 8601 format.
309+
310+
This means that drivers should use the extended `OffsetDateTime` type in the IO specs to serialize and deserialize native date objects.

gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/jsr223/CoreImports.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -323,6 +323,7 @@ public final class CoreImports {
323323
CLASS_IMPORTS.add(TimeUtil.class);
324324
CLASS_IMPORTS.add(Lambda.class);
325325
CLASS_IMPORTS.add(java.util.Date.class);
326+
CLASS_IMPORTS.add(java.time.OffsetDateTime.class);
326327
CLASS_IMPORTS.add(java.sql.Timestamp.class);
327328
CLASS_IMPORTS.add(java.util.UUID.class);
328329
CLASS_IMPORTS.add(GremlinTranslator.class);

gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/grammar/ArgumentVisitor.java

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,8 @@
2424
import org.apache.tinkerpop.gremlin.util.iterator.IteratorUtils;
2525

2626
import java.lang.reflect.Array;
27-
import java.util.Date;
27+
import java.time.OffsetDateTime;
28+
import java.util.Comparator;
2829
import java.util.Map;
2930
import java.util.Objects;
3031

@@ -70,8 +71,8 @@ public String parseString(final GremlinParser.StringArgumentContext ctx) {
7071
/**
7172
* Wrapper to visit function for Date type.
7273
*/
73-
public Date parseDate(final GremlinParser.DateArgumentContext ctx) {
74-
return (Date) visitDateArgument(ctx);
74+
public OffsetDateTime parseDate(final GremlinParser.DateArgumentContext ctx) {
75+
return (OffsetDateTime) visitDateArgument(ctx);
7576
}
7677

7778
/**

gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/translator/AnonymizedTranslatorVisitor.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323

2424
import java.math.BigDecimal;
2525
import java.math.BigInteger;
26-
import java.util.Date;
26+
import java.time.OffsetDateTime;
2727
import java.util.HashMap;
2828
import java.util.List;
2929
import java.util.Map;
@@ -167,7 +167,7 @@ public Void visitBooleanLiteral(final GremlinParser.BooleanLiteralContext ctx) {
167167

168168
@Override
169169
public Void visitDateLiteral(final GremlinParser.DateLiteralContext ctx) {
170-
return anonymize(ctx, Date.class);
170+
return anonymize(ctx, OffsetDateTime.class);
171171
}
172172

173173
@Override

gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/translator/DotNetTranslateVisitor.java

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -159,10 +159,9 @@ public Void visitDateLiteral(final GremlinParser.DateLiteralContext ctx) {
159159
// child at 2 is the date argument to datetime() and comes enclosed in quotes
160160
final String dtString = ctx.getChild(2).getText();
161161
final OffsetDateTime dt = DatetimeHelper.parse(removeFirstAndLastCharacters(dtString));
162-
// todo: update when dotnet datetime serializer is implemented
163-
sb.append("DateTimeOffset.FromUnixTimeMilliseconds(");
164-
sb.append(dt.toInstant().toEpochMilli());
165-
sb.append(")");
162+
sb.append("DateTimeOffset.Parse(\"");
163+
sb.append(dt);
164+
sb.append("\")");
166165
return null;
167166
}
168167

gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/translator/GoTranslateVisitor.java

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,6 @@
3030
import java.time.OffsetDateTime;
3131
import java.util.Arrays;
3232
import java.util.Collections;
33-
import java.util.Date;
3433
import java.util.HashMap;
3534
import java.util.List;
3635
import java.util.Map;
@@ -59,8 +58,16 @@ public Void visitDateLiteral(final GremlinParser.DateLiteralContext ctx) {
5958
// child at 2 is the date argument to datetime() and comes enclosed in quotes
6059
final String dtString = ctx.getChild(2).getText();
6160
final OffsetDateTime dt = DatetimeHelper.parse(removeFirstAndLastCharacters(dtString));
62-
// todo: update when go datetime serializer is implemented
63-
sb.append("time.UnixMilli(" + dt.toInstant().toEpochMilli() + ")");
61+
final String zoneInfo = dt.getOffset().getId().equals("Z") ? "UTC+00:00" : "UTC" + dt.getOffset().getId();
62+
sb.append("time.Date(").append(dt.getYear()).
63+
append(", ").append(dt.getMonthValue()).
64+
append(", ").append(dt.getDayOfMonth()).
65+
append(", ").append(dt.getHour()).
66+
append(", ").append(dt.getMinute()).
67+
append(", ").append(dt.getSecond()).
68+
append(", ").append(dt.getNano()).
69+
append(", time.FixedZone(\"").append(zoneInfo).append("\", ").append(dt.getOffset().getTotalSeconds()).append(")").
70+
append(")");
6471
return null;
6572
}
6673

gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/translator/JavaTranslateVisitor.java

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,6 @@
2626
import org.apache.tinkerpop.gremlin.util.DatetimeHelper;
2727

2828
import java.time.OffsetDateTime;
29-
import java.util.Date;
3029
import java.util.List;
3130
import java.util.stream.Collectors;
3231

gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/translator/JavascriptTranslateVisitor.java

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -134,11 +134,11 @@ public Void visitMapKey(final GremlinParser.MapKeyContext ctx) {
134134
public Void visitDateLiteral(final GremlinParser.DateLiteralContext ctx) {
135135
// child at 2 is the date argument to datetime() and comes enclosed in quotes
136136
final String dtString = ctx.getChild(2).getText();
137+
// for consistency, use the way OffsetDateTime formats the date strings
137138
final OffsetDateTime dt = DatetimeHelper.parse(removeFirstAndLastCharacters(dtString));
138-
// todo: update when javascript datetime serializer is implemented
139-
sb.append("new Date(");
140-
sb.append(dt.toInstant().toEpochMilli());
141-
sb.append(")");
139+
sb.append("new Date('");
140+
sb.append(dt);
141+
sb.append("')");
142142
return null;
143143
}
144144

0 commit comments

Comments
 (0)