This is an automated email from the ASF dual-hosted git repository.

xiazcy pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/tinkerpop.git


The following commit(s) were added to refs/heads/master by this push:
     new 3cf2f94446 [TINKERPOP-2979] added datetime() (#2289)
3cf2f94446 is described below

commit 3cf2f9444632f73c130a72b60441f4142f68223e
Author: Valentyn Kahamlyk <vkagam...@users.noreply.github.com>
AuthorDate: Wed Oct 18 16:25:53 2023 -0700

    [TINKERPOP-2979] added datetime() (#2289)
    
    * implementation and tests
    
    * update doc
    
    ---------
    
    Co-authored-by: Valentyn Kahamlyk <valentyn.kaham...@improving.com>
---
 CHANGELOG.asciidoc                                 |  1 +
 docs/src/upgrade/release-3.7.x.asciidoc            | 47 +++++++++++++---------
 .../tinkerpop/gremlin/jsr223/CoreImports.java      |  1 +
 .../language/grammar/GenericLiteralVisitor.java    |  2 +
 .../tinkerpop/gremlin/util/DatetimeHelper.java     |  7 ++++
 .../grammar/GeneralLiteralVisitorTest.java         | 12 ++++++
 .../Gremlin.Net.IntegrationTest/Gherkin/Gremlin.cs | 17 ++++----
 gremlin-go/driver/cucumber/gremlin.go              | 17 ++++----
 .../gremlin-javascript/test/cucumber/gremlin.js    | 17 ++++----
 gremlin-language/src/main/antlr4/Gremlin.g4        |  1 +
 gremlin-python/src/main/python/radish/gremlin.py   | 17 ++++----
 .../gremlin/test/features/map/DateDiff.feature     | 10 +++++
 12 files changed, 98 insertions(+), 51 deletions(-)

diff --git a/CHANGELOG.asciidoc b/CHANGELOG.asciidoc
index ea3240b8ea..f6ee569f88 100644
--- a/CHANGELOG.asciidoc
+++ b/CHANGELOG.asciidoc
@@ -33,6 +33,7 @@ This release also includes changes from <<release-3-6-5, 
3.6.6>> and <<release-3
 * Added date manipulation steps `asDate`, `dateAdd` and `dateDiff`.
 * Added new data type `DT` to represent periods of time.
 * Added Gherkin support for Date.
+* Extended `datetime()` function for current server date.
 * Added list filtering functions `all` and `any`.
 * Added getter for `isStart` on `UnionStep`.
 * Added `agent` parameter to `DriverRemoteConnection` options to allow a 
user-provided `http.Agent` implementation.
diff --git a/docs/src/upgrade/release-3.7.x.asciidoc 
b/docs/src/upgrade/release-3.7.x.asciidoc
index 40ee470eaa..5b50aa07c8 100644
--- a/docs/src/upgrade/release-3.7.x.asciidoc
+++ b/docs/src/upgrade/release-3.7.x.asciidoc
@@ -141,25 +141,6 @@ See: 
link:https://tinkerpop.apache.org/docs/x.y.z/reference/#rTrim-step[rTrim()-
 See: 
link:https://tinkerpop.apache.org/docs/x.y.z/reference/#reverse-step[reverse()-step]
 See: link:https://issues.apache.org/jira/browse/TINKERPOP-2672[TINKERPOP-2672]
 
-==== Date manipulation functions
-
-Date manipulations in Gremlin queries were only possible using closures, which 
may or may not be supported by
-different providers. In 3.7.1, we introduce the `asDate()`, `dateAdd` and 
`dateDiff` steps aimed to replace the usage of closure.
-
-The following example demonstrates usage of newly introduced steps:
-
-[source,text]
-----
-gremlin> g.inject("2023-08-02T00:00:00Z").asDate().dateAdd(DT.day, 
7).dateDiff(datetime("2023-08-02T00:00:00Z"))
-==>604800
-----
-
-See: 
link:https://tinkerpop.apache.org/docs/x.y.z/reference/#asDate-step[asDate()-step]
-See: 
link:https://tinkerpop.apache.org/docs/x.y.z/reference/#dateAdd-step[dateAdd()-step]
-See: 
link:https://tinkerpop.apache.org/docs/x.y.z/reference/#dateDiff-step[dateDiff()-step]
-See: link:https://issues.apache.org/jira/browse/TINKERPOP-2979[TINKERPOP-2979]
-
-
 ===== String Steps replace(), split(), substring()
 
 The following example demonstrates the use of a closure to perform `replace()` 
and `split()` functions:
@@ -250,6 +231,34 @@ See: 
link:https://issues.apache.org/jira/browse/TINKERPOP-2978[TINKERPOP-2978],
 link:https://tinkerpop.apache.org/docs/x.y.z/reference/#all-step[all()-step],
 link:https://tinkerpop.apache.org/docs/x.y.z/reference/#any-step[any()-step]
 
+==== Date manipulation functions
+
+Date manipulations in Gremlin queries were only possible using closures, which 
may or may not be supported by
+different providers. In 3.7.1, we introduce the `asDate()`, `dateAdd` and 
`dateDiff` steps aimed to replace the usage of closure.
+
+The following example demonstrates usage of newly introduced steps:
+
+[source,text]
+----
+gremlin> g.inject("2023-08-02T00:00:00Z").asDate().dateAdd(DT.day, 
7).dateDiff(datetime("2023-08-02T00:00:00Z"))
+==>604800
+----
+
+See: 
link:https://tinkerpop.apache.org/docs/x.y.z/reference/#asDate-step[asDate()-step]
+See: 
link:https://tinkerpop.apache.org/docs/x.y.z/reference/#dateAdd-step[dateAdd()-step]
+See: 
link:https://tinkerpop.apache.org/docs/x.y.z/reference/#dateDiff-step[dateDiff()-step]
+See: link:https://issues.apache.org/jira/browse/TINKERPOP-2979[TINKERPOP-2979]
+
+===== `datetime()` for current server time
+
+Function `datetime()` extended to return current server time when used without 
argument.
+
+[source,text]
+----
+gremlin> datetime().toGMTString()
+==>13 Oct 2023 20:44:20 GMT
+----
+
 === Upgrading for Providers
 
 ==== Graph System Providers
diff --git 
a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/jsr223/CoreImports.java
 
b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/jsr223/CoreImports.java
index 13868cee47..96f55920d1 100644
--- 
a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/jsr223/CoreImports.java
+++ 
b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/jsr223/CoreImports.java
@@ -337,6 +337,7 @@ public final class CoreImports {
         uniqueMethods(Lambda.class).forEach(METHOD_IMPORTS::add);
         try {
             METHOD_IMPORTS.add(DatetimeHelper.class.getMethod("datetime", 
String.class));
+            METHOD_IMPORTS.add(DatetimeHelper.class.getMethod("datetime"));
         } catch (Exception ex) {
             throw new IllegalStateException("Could not load datetime() 
function to imports");
         }
diff --git 
a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/grammar/GenericLiteralVisitor.java
 
b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/grammar/GenericLiteralVisitor.java
index 85de69a84f..7b841de87c 100644
--- 
a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/grammar/GenericLiteralVisitor.java
+++ 
b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/language/grammar/GenericLiteralVisitor.java
@@ -478,6 +478,8 @@ public class GenericLiteralVisitor extends 
DefaultGremlinBaseVisitor<Object> {
      */
     @Override
     public Object visitDateLiteral(final GremlinParser.DateLiteralContext ctx) 
{
+        if (ctx.stringArgument() == null)
+            return DatetimeHelper.datetime();
         return DatetimeHelper.parse((String) 
antlr.argumentVisitor.visitStringArgument(ctx.stringArgument()));
     }
 
diff --git 
a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/util/DatetimeHelper.java
 
b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/util/DatetimeHelper.java
index 741bd18fc7..31334117b0 100644
--- 
a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/util/DatetimeHelper.java
+++ 
b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/util/DatetimeHelper.java
@@ -127,4 +127,11 @@ public final class DatetimeHelper {
     public static Date datetime(final String d) {
         return parse(d);
     }
+
+    /**
+     * A proxy allows for syntax similar to Gremlin grammar of {@code 
datetime()}.
+     */
+    public static Date datetime() {
+        return new Date();
+    }
 }
diff --git 
a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/language/grammar/GeneralLiteralVisitorTest.java
 
b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/language/grammar/GeneralLiteralVisitorTest.java
index 7b84f7ea5b..96d0ede1c7 100644
--- 
a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/language/grammar/GeneralLiteralVisitorTest.java
+++ 
b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/language/grammar/GeneralLiteralVisitorTest.java
@@ -481,6 +481,18 @@ public class GeneralLiteralVisitorTest {
         }
     }
 
+    public static class ValidCurrentDateLiteralTest {
+        @Test
+        public void shouldParseCurrentDate() {
+            final GremlinLexer lexer = new 
GremlinLexer(CharStreams.fromString("datetime()"));
+            final GremlinParser parser = new GremlinParser(new 
CommonTokenStream(lexer));
+            final GremlinParser.DateLiteralContext ctx = parser.dateLiteral();
+
+            final Date dt = (Date) new GenericLiteralVisitor(new 
GremlinAntlrToJava()).visitDateLiteral(ctx);
+            assertTrue(new Date().getTime() - dt.getTime() < 1000);
+        }
+    }
+
     @RunWith(Parameterized.class)
     public static class ValidBooleanLiteralTest {
         @Parameterized.Parameter(value = 0)
diff --git a/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/Gremlin.cs 
b/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/Gremlin.cs
index 718d60d0f9..bf1f83db0a 100644
--- a/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/Gremlin.cs
+++ b/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/Gremlin.cs
@@ -604,6 +604,7 @@ namespace Gremlin.Net.IntegrationTest.Gherkin
                {"g_injectXdatetimeXstrXX_dateAddXminute_10X", new 
List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> 
{(g,p) 
=>g.Inject(DateTimeOffset.FromUnixTimeMilliseconds(1690934400000)).DateAdd(DT.Minute,10)}},
 
                {"g_injectXdatetimeXstrXX_dateAddXsecond_20X", new 
List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> 
{(g,p) 
=>g.Inject(DateTimeOffset.FromUnixTimeMilliseconds(1690934400000)).DateAdd(DT.Second,20)}},
 
                {"g_injectXdatetimeXstrXX_dateAddXday_11X", new 
List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> 
{(g,p) 
=>g.Inject(DateTimeOffset.FromUnixTimeMilliseconds(1693958400000)).DateAdd(DT.Day,11)}},
 
+               {"g_injectXdatetimeXXX_dateDiffXdatetimeXstrXX", new 
List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> 
{(g,p) 
=>g.Inject(DateTimeOffset.FromUnixTimeMilliseconds(1697150417516)).DateDiff(DateTimeOffset.FromUnixTimeMilliseconds(1673481600000)).Is(P.Gt(0))}},
 
                {"g_injectXdatetimeXstr1XX_dateDiffXdatetimeXstr2XX", new 
List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> 
{(g,p) 
=>g.Inject(DateTimeOffset.FromUnixTimeMilliseconds(1690934400000)).DateDiff(DateTimeOffset.FromUnixTimeMilliseconds(1691539200000))}},
 
                {"g_injectXdatetimeXstr1XX_dateDiffXinjectXdatetimeXstr2XXX", 
new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> 
{(g,p) 
=>g.Inject(DateTimeOffset.FromUnixTimeMilliseconds(1691452800000)).DateDiff(__.Inject(DateTimeOffset.FromUnixTimeMilliseconds(1690848000000)))}},
 
                {"g_V_EX11X", new List<Func<GraphTraversalSource, 
IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().E(p["eid11"])}}, 
@@ -638,10 +639,6 @@ namespace Gremlin.Net.IntegrationTest.Gherkin
                
{"g_V_hasLabelXsoftwareX_name_fold_orderXlocalX_index_unfold_order_byXtailXlocal_1XX",
 new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> 
{(g,p) 
=>g.V().HasLabel("software").Values<object>("name").Fold().Order(Scope.Local).Index<object>().Unfold<object>().Order().By(__.Tail<object>(Scope.Local,1))}},
 
                {"g_V_hasLabelXpersonX_name_fold_orderXlocalX_index_withXmapX", 
new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> 
{(g,p) 
=>g.V().HasLabel("person").Values<object>("name").Fold().Order(Scope.Local).Index<object>().With("~tinkerpop.index.indexer",1)}},
 
                {"g_VX1X_valuesXageX_index_unfold_unfold", new 
List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> 
{(g,p) 
=>g.V(p["vid1"]).Values<object>("age").Index<object>().Unfold<object>().Unfold<object>()}},
 
-               {"g_injectX__feature___test__nullX_lTrim", new 
List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> 
{(g,p) =>g.Inject<object>("  feature"," one test",null,""," ").LTrim()}}, 
-               {"g_injectX__feature__X_lTrim", new 
List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> 
{(g,p) =>g.Inject("  feature  ").LTrim()}}, 
-               {"g_injectXListXa_bXX_lTrim", new 
List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> 
{(g,p) =>g.Inject(p["xx1"]).LTrim()}}, 
-               {"g_V_valuesXnameX_lTrim", new List<Func<GraphTraversalSource, 
IDictionary<string, object>, ITraversal>> {(g,p) 
=>g.AddV("person").Property("name"," marko 
").Property("age",29).As("marko").AddV("person").Property("name","  vadas  
").Property("age",27).As("vadas").AddV("software").Property("name","  
lop").Property("lang","java").As("lop").AddV("person").Property("name","josh  
").Property("age",32).As("josh").AddV("software").Property("name","   ripple   
").Property("lang"," [...]
                {"g_injectXfeature_test_nullX_length", new 
List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> 
{(g,p) =>g.Inject<object>("feature","test",null).Length()}}, 
                {"g_injectXListXa_bXX_length", new 
List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> 
{(g,p) =>g.Inject(p["xx1"]).Length()}}, 
                {"g_V_valuesXnameX_length", new List<Func<GraphTraversalSource, 
IDictionary<string, object>, ITraversal>> {(g,p) 
=>g.V().Values<object>("name").Length()}}, 
@@ -649,6 +646,10 @@ namespace Gremlin.Net.IntegrationTest.Gherkin
                
{"g_VX1X_repeatXboth_simplePathX_untilXhasXname_peterX_or_loops_isX2XX_hasXname_peterX_path_byXnameX",
 new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> 
{(g,p) 
=>g.V(p["vid1"]).Repeat(__.Both().SimplePath()).Until(__.Has("name","peter").Or().Loops().Is(2)).Has("name","peter").Path().By("name")}},
 
                
{"g_VX1X_repeatXboth_simplePathX_untilXhasXname_peterX_and_loops_isX3XX_hasXname_peterX_path_byXnameX",
 new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> 
{(g,p) 
=>g.V(p["vid1"]).Repeat(__.Both().SimplePath()).Until(__.Has("name","peter").And().Loops().Is(3)).Has("name","peter").Path().By("name")}},
 
                
{"g_V_emitXhasXname_markoX_or_loops_isX2XX_repeatXoutX_valuesXnameX", new 
List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> 
{(g,p) 
=>g.V().Emit(__.Has("name","marko").Or().Loops().Is(2)).Repeat(__.Out()).Values<object>("name")}},
 
+               {"g_injectX__feature___test__nullX_lTrim", new 
List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> 
{(g,p) =>g.Inject<object>("  feature"," one test",null,""," ").LTrim()}}, 
+               {"g_injectX__feature__X_lTrim", new 
List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> 
{(g,p) =>g.Inject("  feature  ").LTrim()}}, 
+               {"g_injectXListXa_bXX_lTrim", new 
List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> 
{(g,p) =>g.Inject(p["xx1"]).LTrim()}}, 
+               {"g_V_valuesXnameX_lTrim", new List<Func<GraphTraversalSource, 
IDictionary<string, object>, ITraversal>> {(g,p) 
=>g.AddV("person").Property("name"," marko 
").Property("age",29).As("marko").AddV("person").Property("name","  vadas  
").Property("age",27).As("vadas").AddV("software").Property("name","  
lop").Property("lang","java").As("lop").AddV("person").Property("name","josh  
").Property("age",32).As("josh").AddV("software").Property("name","   ripple   
").Property("lang"," [...]
                {"g_VX1X_mapXnameX", new List<Func<GraphTraversalSource, 
IDictionary<string, object>, ITraversal>> {(g,p) 
=>g.V(p["vid1"]).Map<object>((IFunction) p["l1"])}}, 
                {"g_VX1X_outE_label_mapXlengthX", new 
List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> 
{(g,p) =>g.V(p["vid1"]).OutE().Label().Map<object>((IFunction) p["l1"])}}, 
                {"g_VX1X_out_mapXnameX_mapXlengthX", new 
List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> 
{(g,p) =>g.V(p["vid1"]).Out().Map<object>((IFunction) 
p["l1"]).Map<object>((IFunction) p["l2"])}}, 
@@ -911,10 +912,6 @@ namespace Gremlin.Net.IntegrationTest.Gherkin
                {"g_V_hasXageX_propertiesXage_nameX_value", new 
List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> 
{(g,p) =>g.V().Has("age").Properties<object>("age","name").Value<object>()}}, 
                {"g_V_propertiesXname_age_nullX_value", new 
List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> 
{(g,p) =>g.V().Properties<object>("name","age",null).Value<object>()}}, 
                {"g_V_valuesXname_age_nullX", new 
List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> 
{(g,p) =>g.V().Values<object>("name","age",null)}}, 
-               {"g_injectX__feature___test__nullX_rTrim", new 
List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> 
{(g,p) =>g.Inject<object>("feature  ","one test ",null,""," ").RTrim()}}, 
-               {"g_injectX__feature__X_rTrim", new 
List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> 
{(g,p) =>g.Inject("  feature  ").RTrim()}}, 
-               {"g_injectXListXa_bXX_rTrim", new 
List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> 
{(g,p) =>g.Inject(p["xx1"]).RTrim()}}, 
-               {"g_V_valuesXnameX_rTrim", new List<Func<GraphTraversalSource, 
IDictionary<string, object>, ITraversal>> {(g,p) 
=>g.AddV("person").Property("name"," marko 
").Property("age",29).As("marko").AddV("person").Property("name","  vadas  
").Property("age",27).As("vadas").AddV("software").Property("name","  
lop").Property("lang","java").As("lop").AddV("person").Property("name","josh  
").Property("age",32).As("josh").AddV("software").Property("name","   ripple   
").Property("lang"," [...]
                {"g_injectXthat_this_testX_replaceXh_jX", new 
List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> 
{(g,p) =>g.Inject<object>("that","this","test",null).Replace("h","j")}}, 
                {"g_injectXListXa_bXcX_replaceXa_bX", new 
List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> 
{(g,p) =>g.Inject(p["xx1"]).Replace("a","b")}}, 
                {"g_V_hasLabelXsoftwareX_valueXnameX_replaceXnull_iX", new 
List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> 
{(g,p) =>g.V().HasLabel("software").Values<object>("name").Replace(null,"g")}}, 
@@ -922,6 +919,10 @@ namespace Gremlin.Net.IntegrationTest.Gherkin
                {"g_injectXfeature_test_nullX_reverse", new 
List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> 
{(g,p) =>g.Inject<object>("feature","test one",null).Reverse()}}, 
                {"g_injectXListXa_bXX_reverse", new 
List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> 
{(g,p) =>g.Inject(p["xx1"]).Reverse()}}, 
                {"g_V_valuesXnameX_reverse", new 
List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> 
{(g,p) =>g.V().Values<object>("name").Reverse()}}, 
+               {"g_injectX__feature___test__nullX_rTrim", new 
List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> 
{(g,p) =>g.Inject<object>("feature  ","one test ",null,""," ").RTrim()}}, 
+               {"g_injectX__feature__X_rTrim", new 
List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> 
{(g,p) =>g.Inject("  feature  ").RTrim()}}, 
+               {"g_injectXListXa_bXX_rTrim", new 
List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> 
{(g,p) =>g.Inject(p["xx1"]).RTrim()}}, 
+               {"g_V_valuesXnameX_rTrim", new List<Func<GraphTraversalSource, 
IDictionary<string, object>, ITraversal>> {(g,p) 
=>g.AddV("person").Property("name"," marko 
").Property("age",29).As("marko").AddV("person").Property("name","  vadas  
").Property("age",27).As("vadas").AddV("software").Property("name","  
lop").Property("lang","java").As("lop").AddV("person").Property("name","josh  
").Property("age",32).As("josh").AddV("software").Property("name","   ripple   
").Property("lang"," [...]
                {"g_VX1X_asXaX_outXknowsX_asXbX_selectXa_bX", new 
List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> 
{(g,p) =>g.V(p["vid1"]).As("a").Out("knows").As("b").Select<object>("a","b")}}, 
                {"g_VX1X_asXaX_outXknowsX_asXbX_selectXa_bX_byXnameX", new 
List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> 
{(g,p) 
=>g.V(p["vid1"]).As("a").Out("knows").As("b").Select<object>("a","b").By("name")}},
 
                {"g_VX1X_asXaX_outXknowsX_asXbX_selectXaX", new 
List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> 
{(g,p) =>g.V(p["vid1"]).As("a").Out("knows").As("b").Select<object>("a")}}, 
diff --git a/gremlin-go/driver/cucumber/gremlin.go 
b/gremlin-go/driver/cucumber/gremlin.go
index b78f9629c0..a1b837ada1 100644
--- a/gremlin-go/driver/cucumber/gremlin.go
+++ b/gremlin-go/driver/cucumber/gremlin.go
@@ -575,6 +575,7 @@ var translationMap = map[string][]func(g 
*gremlingo.GraphTraversalSource, p map[
     "g_injectXdatetimeXstrXX_dateAddXminute_10X": {func(g 
*gremlingo.GraphTraversalSource, p map[string]interface{}) 
*gremlingo.GraphTraversal {return 
g.Inject(time.UnixMilli(1690934400000)).DateAdd(gremlingo.DT.Minute, 10)}}, 
     "g_injectXdatetimeXstrXX_dateAddXsecond_20X": {func(g 
*gremlingo.GraphTraversalSource, p map[string]interface{}) 
*gremlingo.GraphTraversal {return 
g.Inject(time.UnixMilli(1690934400000)).DateAdd(gremlingo.DT.Second, 20)}}, 
     "g_injectXdatetimeXstrXX_dateAddXday_11X": {func(g 
*gremlingo.GraphTraversalSource, p map[string]interface{}) 
*gremlingo.GraphTraversal {return 
g.Inject(time.UnixMilli(1693958400000)).DateAdd(gremlingo.DT.Day, 11)}}, 
+    "g_injectXdatetimeXXX_dateDiffXdatetimeXstrXX": {func(g 
*gremlingo.GraphTraversalSource, p map[string]interface{}) 
*gremlingo.GraphTraversal {return 
g.Inject(time.UnixMilli(1697150105085)).DateDiff(time.UnixMilli(1673481600000)).Is(gremlingo.P.Gt(0))}},
 
     "g_injectXdatetimeXstr1XX_dateDiffXdatetimeXstr2XX": {func(g 
*gremlingo.GraphTraversalSource, p map[string]interface{}) 
*gremlingo.GraphTraversal {return 
g.Inject(time.UnixMilli(1690934400000)).DateDiff(time.UnixMilli(1691539200000))}},
 
     "g_injectXdatetimeXstr1XX_dateDiffXinjectXdatetimeXstr2XXX": {func(g 
*gremlingo.GraphTraversalSource, p map[string]interface{}) 
*gremlingo.GraphTraversal {return 
g.Inject(time.UnixMilli(1691452800000)).DateDiff(gremlingo.T__.Inject(time.UnixMilli(1690848000000)))}},
 
     "g_V_EX11X": {func(g *gremlingo.GraphTraversalSource, p 
map[string]interface{}) *gremlingo.GraphTraversal {return 
g.V().E(p["eid11"])}}, 
@@ -609,10 +610,6 @@ var translationMap = map[string][]func(g 
*gremlingo.GraphTraversalSource, p map[
     
"g_V_hasLabelXsoftwareX_name_fold_orderXlocalX_index_unfold_order_byXtailXlocal_1XX":
 {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) 
*gremlingo.GraphTraversal {return 
g.V().HasLabel("software").Values("name").Fold().Order(gremlingo.Scope.Local).Index().Unfold().Order().By(gremlingo.T__.Tail(gremlingo.Scope.Local,
 1))}}, 
     "g_V_hasLabelXpersonX_name_fold_orderXlocalX_index_withXmapX": {func(g 
*gremlingo.GraphTraversalSource, p map[string]interface{}) 
*gremlingo.GraphTraversal {return 
g.V().HasLabel("person").Values("name").Fold().Order(gremlingo.Scope.Local).Index().With("~tinkerpop.index.indexer",
 1)}}, 
     "g_VX1X_valuesXageX_index_unfold_unfold": {func(g 
*gremlingo.GraphTraversalSource, p map[string]interface{}) 
*gremlingo.GraphTraversal {return 
g.V(p["vid1"]).Values("age").Index().Unfold().Unfold()}}, 
-    "g_injectX__feature___test__nullX_lTrim": {func(g 
*gremlingo.GraphTraversalSource, p map[string]interface{}) 
*gremlingo.GraphTraversal {return g.Inject("  feature", " one test", nil, "", " 
").LTrim()}}, 
-    "g_injectX__feature__X_lTrim": {func(g *gremlingo.GraphTraversalSource, p 
map[string]interface{}) *gremlingo.GraphTraversal {return g.Inject("  feature  
").LTrim()}}, 
-    "g_injectXListXa_bXX_lTrim": {func(g *gremlingo.GraphTraversalSource, p 
map[string]interface{}) *gremlingo.GraphTraversal {return 
g.Inject(p["xx1"]).LTrim()}}, 
-    "g_V_valuesXnameX_lTrim": {func(g *gremlingo.GraphTraversalSource, p 
map[string]interface{}) *gremlingo.GraphTraversal {return 
g.AddV("person").Property("name", " marko ").Property("age", 
29).As("marko").AddV("person").Property("name", "  vadas  ").Property("age", 
27).As("vadas").AddV("software").Property("name", "  lop").Property("lang", 
"java").As("lop").AddV("person").Property("name", "josh  ").Property("age", 
32).As("josh").AddV("software").Property("name", "   ripple   ").Proper [...]
     "g_injectXfeature_test_nullX_length": {func(g 
*gremlingo.GraphTraversalSource, p map[string]interface{}) 
*gremlingo.GraphTraversal {return g.Inject("feature", "test", nil).Length()}}, 
     "g_injectXListXa_bXX_length": {func(g *gremlingo.GraphTraversalSource, p 
map[string]interface{}) *gremlingo.GraphTraversal {return 
g.Inject(p["xx1"]).Length()}}, 
     "g_V_valuesXnameX_length": {func(g *gremlingo.GraphTraversalSource, p 
map[string]interface{}) *gremlingo.GraphTraversal {return 
g.V().Values("name").Length()}}, 
@@ -620,6 +617,10 @@ var translationMap = map[string][]func(g 
*gremlingo.GraphTraversalSource, p map[
     
"g_VX1X_repeatXboth_simplePathX_untilXhasXname_peterX_or_loops_isX2XX_hasXname_peterX_path_byXnameX":
 {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) 
*gremlingo.GraphTraversal {return 
g.V(p["vid1"]).Repeat(gremlingo.T__.Both().SimplePath()).Until(gremlingo.T__.Has("name",
 "peter").Or().Loops().Is(2)).Has("name", "peter").Path().By("name")}}, 
     
"g_VX1X_repeatXboth_simplePathX_untilXhasXname_peterX_and_loops_isX3XX_hasXname_peterX_path_byXnameX":
 {func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) 
*gremlingo.GraphTraversal {return 
g.V(p["vid1"]).Repeat(gremlingo.T__.Both().SimplePath()).Until(gremlingo.T__.Has("name",
 "peter").And().Loops().Is(3)).Has("name", "peter").Path().By("name")}}, 
     "g_V_emitXhasXname_markoX_or_loops_isX2XX_repeatXoutX_valuesXnameX": 
{func(g *gremlingo.GraphTraversalSource, p map[string]interface{}) 
*gremlingo.GraphTraversal {return g.V().Emit(gremlingo.T__.Has("name", 
"marko").Or().Loops().Is(2)).Repeat(gremlingo.T__.Out()).Values("name")}}, 
+    "g_injectX__feature___test__nullX_lTrim": {func(g 
*gremlingo.GraphTraversalSource, p map[string]interface{}) 
*gremlingo.GraphTraversal {return g.Inject("  feature", " one test", nil, "", " 
").LTrim()}}, 
+    "g_injectX__feature__X_lTrim": {func(g *gremlingo.GraphTraversalSource, p 
map[string]interface{}) *gremlingo.GraphTraversal {return g.Inject("  feature  
").LTrim()}}, 
+    "g_injectXListXa_bXX_lTrim": {func(g *gremlingo.GraphTraversalSource, p 
map[string]interface{}) *gremlingo.GraphTraversal {return 
g.Inject(p["xx1"]).LTrim()}}, 
+    "g_V_valuesXnameX_lTrim": {func(g *gremlingo.GraphTraversalSource, p 
map[string]interface{}) *gremlingo.GraphTraversal {return 
g.AddV("person").Property("name", " marko ").Property("age", 
29).As("marko").AddV("person").Property("name", "  vadas  ").Property("age", 
27).As("vadas").AddV("software").Property("name", "  lop").Property("lang", 
"java").As("lop").AddV("person").Property("name", "josh  ").Property("age", 
32).As("josh").AddV("software").Property("name", "   ripple   ").Proper [...]
     "g_VX1X_mapXnameX": {func(g *gremlingo.GraphTraversalSource, p 
map[string]interface{}) *gremlingo.GraphTraversal {return 
g.V(p["vid1"]).Map(p["l1"])}}, 
     "g_VX1X_outE_label_mapXlengthX": {func(g *gremlingo.GraphTraversalSource, 
p map[string]interface{}) *gremlingo.GraphTraversal {return 
g.V(p["vid1"]).OutE().Label().Map(p["l1"])}}, 
     "g_VX1X_out_mapXnameX_mapXlengthX": {func(g 
*gremlingo.GraphTraversalSource, p map[string]interface{}) 
*gremlingo.GraphTraversal {return 
g.V(p["vid1"]).Out().Map(p["l1"]).Map(p["l2"])}}, 
@@ -882,10 +883,6 @@ var translationMap = map[string][]func(g 
*gremlingo.GraphTraversalSource, p map[
     "g_V_hasXageX_propertiesXage_nameX_value": {func(g 
*gremlingo.GraphTraversalSource, p map[string]interface{}) 
*gremlingo.GraphTraversal {return g.V().Has("age").Properties("age", 
"name").Value()}}, 
     "g_V_propertiesXname_age_nullX_value": {func(g 
*gremlingo.GraphTraversalSource, p map[string]interface{}) 
*gremlingo.GraphTraversal {return g.V().Properties("name", "age", 
nil).Value()}}, 
     "g_V_valuesXname_age_nullX": {func(g *gremlingo.GraphTraversalSource, p 
map[string]interface{}) *gremlingo.GraphTraversal {return g.V().Values("name", 
"age", nil)}}, 
-    "g_injectX__feature___test__nullX_rTrim": {func(g 
*gremlingo.GraphTraversalSource, p map[string]interface{}) 
*gremlingo.GraphTraversal {return g.Inject("feature  ", "one test ", nil, "", " 
").RTrim()}}, 
-    "g_injectX__feature__X_rTrim": {func(g *gremlingo.GraphTraversalSource, p 
map[string]interface{}) *gremlingo.GraphTraversal {return g.Inject("  feature  
").RTrim()}}, 
-    "g_injectXListXa_bXX_rTrim": {func(g *gremlingo.GraphTraversalSource, p 
map[string]interface{}) *gremlingo.GraphTraversal {return 
g.Inject(p["xx1"]).RTrim()}}, 
-    "g_V_valuesXnameX_rTrim": {func(g *gremlingo.GraphTraversalSource, p 
map[string]interface{}) *gremlingo.GraphTraversal {return 
g.AddV("person").Property("name", " marko ").Property("age", 
29).As("marko").AddV("person").Property("name", "  vadas  ").Property("age", 
27).As("vadas").AddV("software").Property("name", "  lop").Property("lang", 
"java").As("lop").AddV("person").Property("name", "josh  ").Property("age", 
32).As("josh").AddV("software").Property("name", "   ripple   ").Proper [...]
     "g_injectXthat_this_testX_replaceXh_jX": {func(g 
*gremlingo.GraphTraversalSource, p map[string]interface{}) 
*gremlingo.GraphTraversal {return g.Inject("that", "this", "test", 
nil).Replace("h", "j")}}, 
     "g_injectXListXa_bXcX_replaceXa_bX": {func(g 
*gremlingo.GraphTraversalSource, p map[string]interface{}) 
*gremlingo.GraphTraversal {return g.Inject(p["xx1"]).Replace("a", "b")}}, 
     "g_V_hasLabelXsoftwareX_valueXnameX_replaceXnull_iX": {func(g 
*gremlingo.GraphTraversalSource, p map[string]interface{}) 
*gremlingo.GraphTraversal {return 
g.V().HasLabel("software").Values("name").Replace(nil, "g")}}, 
@@ -893,6 +890,10 @@ var translationMap = map[string][]func(g 
*gremlingo.GraphTraversalSource, p map[
     "g_injectXfeature_test_nullX_reverse": {func(g 
*gremlingo.GraphTraversalSource, p map[string]interface{}) 
*gremlingo.GraphTraversal {return g.Inject("feature", "test one", 
nil).Reverse()}}, 
     "g_injectXListXa_bXX_reverse": {func(g *gremlingo.GraphTraversalSource, p 
map[string]interface{}) *gremlingo.GraphTraversal {return 
g.Inject(p["xx1"]).Reverse()}}, 
     "g_V_valuesXnameX_reverse": {func(g *gremlingo.GraphTraversalSource, p 
map[string]interface{}) *gremlingo.GraphTraversal {return 
g.V().Values("name").Reverse()}}, 
+    "g_injectX__feature___test__nullX_rTrim": {func(g 
*gremlingo.GraphTraversalSource, p map[string]interface{}) 
*gremlingo.GraphTraversal {return g.Inject("feature  ", "one test ", nil, "", " 
").RTrim()}}, 
+    "g_injectX__feature__X_rTrim": {func(g *gremlingo.GraphTraversalSource, p 
map[string]interface{}) *gremlingo.GraphTraversal {return g.Inject("  feature  
").RTrim()}}, 
+    "g_injectXListXa_bXX_rTrim": {func(g *gremlingo.GraphTraversalSource, p 
map[string]interface{}) *gremlingo.GraphTraversal {return 
g.Inject(p["xx1"]).RTrim()}}, 
+    "g_V_valuesXnameX_rTrim": {func(g *gremlingo.GraphTraversalSource, p 
map[string]interface{}) *gremlingo.GraphTraversal {return 
g.AddV("person").Property("name", " marko ").Property("age", 
29).As("marko").AddV("person").Property("name", "  vadas  ").Property("age", 
27).As("vadas").AddV("software").Property("name", "  lop").Property("lang", 
"java").As("lop").AddV("person").Property("name", "josh  ").Property("age", 
32).As("josh").AddV("software").Property("name", "   ripple   ").Proper [...]
     "g_VX1X_asXaX_outXknowsX_asXbX_selectXa_bX": {func(g 
*gremlingo.GraphTraversalSource, p map[string]interface{}) 
*gremlingo.GraphTraversal {return 
g.V(p["vid1"]).As("a").Out("knows").As("b").Select("a", "b")}}, 
     "g_VX1X_asXaX_outXknowsX_asXbX_selectXa_bX_byXnameX": {func(g 
*gremlingo.GraphTraversalSource, p map[string]interface{}) 
*gremlingo.GraphTraversal {return 
g.V(p["vid1"]).As("a").Out("knows").As("b").Select("a", "b").By("name")}}, 
     "g_VX1X_asXaX_outXknowsX_asXbX_selectXaX": {func(g 
*gremlingo.GraphTraversalSource, p map[string]interface{}) 
*gremlingo.GraphTraversal {return 
g.V(p["vid1"]).As("a").Out("knows").As("b").Select("a")}}, 
diff --git 
a/gremlin-javascript/src/main/javascript/gremlin-javascript/test/cucumber/gremlin.js
 
b/gremlin-javascript/src/main/javascript/gremlin-javascript/test/cucumber/gremlin.js
index 2fff0455c8..ef6d838d37 100644
--- 
a/gremlin-javascript/src/main/javascript/gremlin-javascript/test/cucumber/gremlin.js
+++ 
b/gremlin-javascript/src/main/javascript/gremlin-javascript/test/cucumber/gremlin.js
@@ -595,6 +595,7 @@ const gremlins = {
     g_injectXdatetimeXstrXX_dateAddXminute_10X: [function({g}) { return 
g.inject(new Date(1690934400000)).dateAdd(DT.minute,10) }], 
     g_injectXdatetimeXstrXX_dateAddXsecond_20X: [function({g}) { return 
g.inject(new Date(1690934400000)).dateAdd(DT.second,20) }], 
     g_injectXdatetimeXstrXX_dateAddXday_11X: [function({g}) { return 
g.inject(new Date(1693958400000)).dateAdd(DT.day,11) }], 
+    g_injectXdatetimeXXX_dateDiffXdatetimeXstrXX: [function({g}) { return 
g.inject(new Date(1697149678043)).dateDiff(new Date(1673481600000)).is(P.gt(0)) 
}], 
     g_injectXdatetimeXstr1XX_dateDiffXdatetimeXstr2XX: [function({g}) { return 
g.inject(new Date(1690934400000)).dateDiff(new Date(1691539200000)) }], 
     g_injectXdatetimeXstr1XX_dateDiffXinjectXdatetimeXstr2XXX: [function({g}) 
{ return g.inject(new Date(1691452800000)).dateDiff(__.inject(new 
Date(1690848000000))) }], 
     g_V_EX11X: [function({g, eid11}) { return g.V().E(eid11) }], 
@@ -629,10 +630,6 @@ const gremlins = {
     
g_V_hasLabelXsoftwareX_name_fold_orderXlocalX_index_unfold_order_byXtailXlocal_1XX:
 [function({g}) { return 
g.V().hasLabel("software").values("name").fold().order(Scope.local).index().unfold().order().by(__.tail(Scope.local,1))
 }], 
     g_V_hasLabelXpersonX_name_fold_orderXlocalX_index_withXmapX: 
[function({g}) { return 
g.V().hasLabel("person").values("name").fold().order(Scope.local).index().with_("~tinkerpop.index.indexer",1)
 }], 
     g_VX1X_valuesXageX_index_unfold_unfold: [function({g, vid1}) { return 
g.V(vid1).values("age").index().unfold().unfold() }], 
-    g_injectX__feature___test__nullX_lTrim: [function({g}) { return g.inject(" 
 feature"," one test",null,""," ").lTrim() }], 
-    g_injectX__feature__X_lTrim: [function({g}) { return g.inject("  feature  
").lTrim() }], 
-    g_injectXListXa_bXX_lTrim: [function({g, xx1}) { return 
g.inject(xx1).lTrim() }], 
-    g_V_valuesXnameX_lTrim: [function({g}) { return 
g.addV("person").property("name"," marko 
").property("age",29).as("marko").addV("person").property("name","  vadas  
").property("age",27).as("vadas").addV("software").property("name","  
lop").property("lang","java").as("lop").addV("person").property("name","josh  
").property("age",32).as("josh").addV("software").property("name","   ripple   
").property("lang","java").as("ripple").addV("person").property("name","peter").property("age",35
 [...]
     g_injectXfeature_test_nullX_length: [function({g}) { return 
g.inject("feature","test",null).length() }], 
     g_injectXListXa_bXX_length: [function({g, xx1}) { return 
g.inject(xx1).length() }], 
     g_V_valuesXnameX_length: [function({g}) { return 
g.V().values("name").length() }], 
@@ -640,6 +637,10 @@ const gremlins = {
     
g_VX1X_repeatXboth_simplePathX_untilXhasXname_peterX_or_loops_isX2XX_hasXname_peterX_path_byXnameX:
 [function({g, vid1}) { return 
g.V(vid1).repeat(__.both().simplePath()).until(__.has("name","peter").or().loops().is(2)).has("name","peter").path().by("name")
 }], 
     
g_VX1X_repeatXboth_simplePathX_untilXhasXname_peterX_and_loops_isX3XX_hasXname_peterX_path_byXnameX:
 [function({g, vid1}) { return 
g.V(vid1).repeat(__.both().simplePath()).until(__.has("name","peter").and().loops().is(3)).has("name","peter").path().by("name")
 }], 
     g_V_emitXhasXname_markoX_or_loops_isX2XX_repeatXoutX_valuesXnameX: 
[function({g}) { return 
g.V().emit(__.has("name","marko").or().loops().is(2)).repeat(__.out()).values("name")
 }], 
+    g_injectX__feature___test__nullX_lTrim: [function({g}) { return g.inject(" 
 feature"," one test",null,""," ").lTrim() }], 
+    g_injectX__feature__X_lTrim: [function({g}) { return g.inject("  feature  
").lTrim() }], 
+    g_injectXListXa_bXX_lTrim: [function({g, xx1}) { return 
g.inject(xx1).lTrim() }], 
+    g_V_valuesXnameX_lTrim: [function({g}) { return 
g.addV("person").property("name"," marko 
").property("age",29).as("marko").addV("person").property("name","  vadas  
").property("age",27).as("vadas").addV("software").property("name","  
lop").property("lang","java").as("lop").addV("person").property("name","josh  
").property("age",32).as("josh").addV("software").property("name","   ripple   
").property("lang","java").as("ripple").addV("person").property("name","peter").property("age",35
 [...]
     g_VX1X_mapXnameX: [function({g, l1, vid1}) { return g.V(vid1).map(l1) }], 
     g_VX1X_outE_label_mapXlengthX: [function({g, l1, vid1}) { return 
g.V(vid1).outE().label().map(l1) }], 
     g_VX1X_out_mapXnameX_mapXlengthX: [function({g, l1, l2, vid1}) { return 
g.V(vid1).out().map(l1).map(l2) }], 
@@ -902,10 +903,6 @@ const gremlins = {
     g_V_hasXageX_propertiesXage_nameX_value: [function({g}) { return 
g.V().has("age").properties("age","name").value() }], 
     g_V_propertiesXname_age_nullX_value: [function({g}) { return 
g.V().properties("name","age",null).value() }], 
     g_V_valuesXname_age_nullX: [function({g}) { return 
g.V().values("name","age",null) }], 
-    g_injectX__feature___test__nullX_rTrim: [function({g}) { return 
g.inject("feature  ","one test ",null,""," ").rTrim() }], 
-    g_injectX__feature__X_rTrim: [function({g}) { return g.inject("  feature  
").rTrim() }], 
-    g_injectXListXa_bXX_rTrim: [function({g, xx1}) { return 
g.inject(xx1).rTrim() }], 
-    g_V_valuesXnameX_rTrim: [function({g}) { return 
g.addV("person").property("name"," marko 
").property("age",29).as("marko").addV("person").property("name","  vadas  
").property("age",27).as("vadas").addV("software").property("name","  
lop").property("lang","java").as("lop").addV("person").property("name","josh  
").property("age",32).as("josh").addV("software").property("name","   ripple   
").property("lang","java").as("ripple").addV("person").property("name","peter").property("age",35
 [...]
     g_injectXthat_this_testX_replaceXh_jX: [function({g}) { return 
g.inject("that","this","test",null).replace("h","j") }], 
     g_injectXListXa_bXcX_replaceXa_bX: [function({g, xx1}) { return 
g.inject(xx1).replace("a","b") }], 
     g_V_hasLabelXsoftwareX_valueXnameX_replaceXnull_iX: [function({g}) { 
return g.V().hasLabel("software").values("name").replace(null,"g") }], 
@@ -913,6 +910,10 @@ const gremlins = {
     g_injectXfeature_test_nullX_reverse: [function({g}) { return 
g.inject("feature","test one",null).reverse() }], 
     g_injectXListXa_bXX_reverse: [function({g, xx1}) { return 
g.inject(xx1).reverse() }], 
     g_V_valuesXnameX_reverse: [function({g}) { return 
g.V().values("name").reverse() }], 
+    g_injectX__feature___test__nullX_rTrim: [function({g}) { return 
g.inject("feature  ","one test ",null,""," ").rTrim() }], 
+    g_injectX__feature__X_rTrim: [function({g}) { return g.inject("  feature  
").rTrim() }], 
+    g_injectXListXa_bXX_rTrim: [function({g, xx1}) { return 
g.inject(xx1).rTrim() }], 
+    g_V_valuesXnameX_rTrim: [function({g}) { return 
g.addV("person").property("name"," marko 
").property("age",29).as("marko").addV("person").property("name","  vadas  
").property("age",27).as("vadas").addV("software").property("name","  
lop").property("lang","java").as("lop").addV("person").property("name","josh  
").property("age",32).as("josh").addV("software").property("name","   ripple   
").property("lang","java").as("ripple").addV("person").property("name","peter").property("age",35
 [...]
     g_VX1X_asXaX_outXknowsX_asXbX_selectXa_bX: [function({g, vid1}) { return 
g.V(vid1).as("a").out("knows").as("b").select("a","b") }], 
     g_VX1X_asXaX_outXknowsX_asXbX_selectXa_bX_byXnameX: [function({g, vid1}) { 
return g.V(vid1).as("a").out("knows").as("b").select("a","b").by("name") }], 
     g_VX1X_asXaX_outXknowsX_asXbX_selectXaX: [function({g, vid1}) { return 
g.V(vid1).as("a").out("knows").as("b").select("a") }], 
diff --git a/gremlin-language/src/main/antlr4/Gremlin.g4 
b/gremlin-language/src/main/antlr4/Gremlin.g4
index 8d08eb1676..fe38cd5567 100644
--- a/gremlin-language/src/main/antlr4/Gremlin.g4
+++ b/gremlin-language/src/main/antlr4/Gremlin.g4
@@ -1676,6 +1676,7 @@ booleanLiteral
 
 dateLiteral
     : 'datetime' LPAREN stringArgument RPAREN
+    | 'datetime' LPAREN RPAREN
     ;
 
 nullLiteral
diff --git a/gremlin-python/src/main/python/radish/gremlin.py 
b/gremlin-python/src/main/python/radish/gremlin.py
index 71665597ae..67824c6680 100644
--- a/gremlin-python/src/main/python/radish/gremlin.py
+++ b/gremlin-python/src/main/python/radish/gremlin.py
@@ -577,6 +577,7 @@ world.gremlins = {
     'g_injectXdatetimeXstrXX_dateAddXminute_10X': [(lambda 
g:g.inject(datetime.datetime.utcfromtimestamp(1690934400000 / 
1000.0)).date_add(DT.minute,10))], 
     'g_injectXdatetimeXstrXX_dateAddXsecond_20X': [(lambda 
g:g.inject(datetime.datetime.utcfromtimestamp(1690934400000 / 
1000.0)).date_add(DT.second,20))], 
     'g_injectXdatetimeXstrXX_dateAddXday_11X': [(lambda 
g:g.inject(datetime.datetime.utcfromtimestamp(1693958400000 / 
1000.0)).date_add(DT.day,11))], 
+    'g_injectXdatetimeXXX_dateDiffXdatetimeXstrXX': [(lambda 
g:g.inject(datetime.datetime.utcfromtimestamp(1697149847363 / 
1000.0)).date_diff(datetime.datetime.utcfromtimestamp(1673481600000 / 
1000.0)).is_(P.gt(0)))], 
     'g_injectXdatetimeXstr1XX_dateDiffXdatetimeXstr2XX': [(lambda 
g:g.inject(datetime.datetime.utcfromtimestamp(1690934400000 / 
1000.0)).date_diff(datetime.datetime.utcfromtimestamp(1691539200000 / 
1000.0)))], 
     'g_injectXdatetimeXstr1XX_dateDiffXinjectXdatetimeXstr2XXX': [(lambda 
g:g.inject(datetime.datetime.utcfromtimestamp(1691452800000 / 
1000.0)).date_diff(__.inject(datetime.datetime.utcfromtimestamp(1690848000000 / 
1000.0))))], 
     'g_V_EX11X': [(lambda g, eid11=None:g.V().E(eid11))], 
@@ -611,10 +612,6 @@ world.gremlins = {
     
'g_V_hasLabelXsoftwareX_name_fold_orderXlocalX_index_unfold_order_byXtailXlocal_1XX':
 [(lambda 
g:g.V().hasLabel('software').name.fold().order(Scope.local).index().unfold().order().by(__.tail(Scope.local,1)))],
 
     'g_V_hasLabelXpersonX_name_fold_orderXlocalX_index_withXmapX': [(lambda 
g:g.V().hasLabel('person').name.fold().order(Scope.local).index().with_('~tinkerpop.index.indexer',1))],
 
     'g_VX1X_valuesXageX_index_unfold_unfold': [(lambda g, 
vid1=None:g.V(vid1).age.index().unfold().unfold())], 
-    'g_injectX__feature___test__nullX_lTrim': [(lambda g:g.inject('  
feature',' one test',None,'',' ').lTrim())], 
-    'g_injectX__feature__X_lTrim': [(lambda g:g.inject('  feature  
').lTrim())], 
-    'g_injectXListXa_bXX_lTrim': [(lambda g, xx1=None:g.inject(xx1).lTrim())], 
-    'g_V_valuesXnameX_lTrim': [(lambda g:g.addV('person').property('name',' 
marko ').property('age',29).as_('marko').addV('person').property('name','  
vadas  ').property('age',27).as_('vadas').addV('software').property('name','  
lop').property('lang','java').as_('lop').addV('person').property('name','josh  
').property('age',32).as_('josh').addV('software').property('name','   ripple   
').property('lang','java').as_('ripple').addV('person').property('name','peter').property('age',35).as_(
 [...]
     'g_injectXfeature_test_nullX_length': [(lambda 
g:g.inject('feature','test',None).length())], 
     'g_injectXListXa_bXX_length': [(lambda g, 
xx1=None:g.inject(xx1).length())], 
     'g_V_valuesXnameX_length': [(lambda g:g.V().name.length())], 
@@ -622,6 +619,10 @@ world.gremlins = {
     
'g_VX1X_repeatXboth_simplePathX_untilXhasXname_peterX_or_loops_isX2XX_hasXname_peterX_path_byXnameX':
 [(lambda g, 
vid1=None:g.V(vid1).repeat(__.both().simplePath()).until(__.has('name','peter').or_().loops().is_(2)).has('name','peter').path().by('name'))],
 
     
'g_VX1X_repeatXboth_simplePathX_untilXhasXname_peterX_and_loops_isX3XX_hasXname_peterX_path_byXnameX':
 [(lambda g, 
vid1=None:g.V(vid1).repeat(__.both().simplePath()).until(__.has('name','peter').and_().loops().is_(3)).has('name','peter').path().by('name'))],
 
     'g_V_emitXhasXname_markoX_or_loops_isX2XX_repeatXoutX_valuesXnameX': 
[(lambda 
g:g.V().emit(__.has('name','marko').or_().loops().is_(2)).repeat(__.out()).name)],
 
+    'g_injectX__feature___test__nullX_lTrim': [(lambda g:g.inject('  
feature',' one test',None,'',' ').lTrim())], 
+    'g_injectX__feature__X_lTrim': [(lambda g:g.inject('  feature  
').lTrim())], 
+    'g_injectXListXa_bXX_lTrim': [(lambda g, xx1=None:g.inject(xx1).lTrim())], 
+    'g_V_valuesXnameX_lTrim': [(lambda g:g.addV('person').property('name',' 
marko ').property('age',29).as_('marko').addV('person').property('name','  
vadas  ').property('age',27).as_('vadas').addV('software').property('name','  
lop').property('lang','java').as_('lop').addV('person').property('name','josh  
').property('age',32).as_('josh').addV('software').property('name','   ripple   
').property('lang','java').as_('ripple').addV('person').property('name','peter').property('age',35).as_(
 [...]
     'g_VX1X_mapXnameX': [(lambda g, l1=None,vid1=None:g.V(vid1).map(l1))], 
     'g_VX1X_outE_label_mapXlengthX': [(lambda g, 
l1=None,vid1=None:g.V(vid1).outE().label().map(l1))], 
     'g_VX1X_out_mapXnameX_mapXlengthX': [(lambda g, 
l1=None,l2=None,vid1=None:g.V(vid1).out().map(l1).map(l2))], 
@@ -884,10 +885,6 @@ world.gremlins = {
     'g_V_hasXageX_propertiesXage_nameX_value': [(lambda 
g:g.V().has('age').properties('age','name').value())], 
     'g_V_propertiesXname_age_nullX_value': [(lambda 
g:g.V().properties('name','age',None).value())], 
     'g_V_valuesXname_age_nullX': [(lambda g:g.V().values('name','age',None))], 
-    'g_injectX__feature___test__nullX_rTrim': [(lambda g:g.inject('feature  
','one test ',None,'',' ').rTrim())], 
-    'g_injectX__feature__X_rTrim': [(lambda g:g.inject('  feature  
').rTrim())], 
-    'g_injectXListXa_bXX_rTrim': [(lambda g, xx1=None:g.inject(xx1).rTrim())], 
-    'g_V_valuesXnameX_rTrim': [(lambda g:g.addV('person').property('name',' 
marko ').property('age',29).as_('marko').addV('person').property('name','  
vadas  ').property('age',27).as_('vadas').addV('software').property('name','  
lop').property('lang','java').as_('lop').addV('person').property('name','josh  
').property('age',32).as_('josh').addV('software').property('name','   ripple   
').property('lang','java').as_('ripple').addV('person').property('name','peter').property('age',35).as_(
 [...]
     'g_injectXthat_this_testX_replaceXh_jX': [(lambda 
g:g.inject('that','this','test',None).replace('h','j'))], 
     'g_injectXListXa_bXcX_replaceXa_bX': [(lambda g, 
xx1=None:g.inject(xx1).replace('a','b'))], 
     'g_V_hasLabelXsoftwareX_valueXnameX_replaceXnull_iX': [(lambda 
g:g.V().hasLabel('software').name.replace(None,'g'))], 
@@ -895,6 +892,10 @@ world.gremlins = {
     'g_injectXfeature_test_nullX_reverse': [(lambda g:g.inject('feature','test 
one',None).reverse())], 
     'g_injectXListXa_bXX_reverse': [(lambda g, 
xx1=None:g.inject(xx1).reverse())], 
     'g_V_valuesXnameX_reverse': [(lambda g:g.V().name.reverse())], 
+    'g_injectX__feature___test__nullX_rTrim': [(lambda g:g.inject('feature  
','one test ',None,'',' ').rTrim())], 
+    'g_injectX__feature__X_rTrim': [(lambda g:g.inject('  feature  
').rTrim())], 
+    'g_injectXListXa_bXX_rTrim': [(lambda g, xx1=None:g.inject(xx1).rTrim())], 
+    'g_V_valuesXnameX_rTrim': [(lambda g:g.addV('person').property('name',' 
marko ').property('age',29).as_('marko').addV('person').property('name','  
vadas  ').property('age',27).as_('vadas').addV('software').property('name','  
lop').property('lang','java').as_('lop').addV('person').property('name','josh  
').property('age',32).as_('josh').addV('software').property('name','   ripple   
').property('lang','java').as_('ripple').addV('person').property('name','peter').property('age',35).as_(
 [...]
     'g_VX1X_asXaX_outXknowsX_asXbX_selectXa_bX': [(lambda g, 
vid1=None:g.V(vid1).as_('a').out('knows').as_('b').select('a','b'))], 
     'g_VX1X_asXaX_outXknowsX_asXbX_selectXa_bX_byXnameX': [(lambda g, 
vid1=None:g.V(vid1).as_('a').out('knows').as_('b').select('a','b').by('name'))],
 
     'g_VX1X_asXaX_outXknowsX_asXbX_selectXaX': [(lambda g, 
vid1=None:g.V(vid1).as_('a').out('knows').as_('b').select('a'))], 
diff --git 
a/gremlin-test/src/main/resources/org/apache/tinkerpop/gremlin/test/features/map/DateDiff.feature
 
b/gremlin-test/src/main/resources/org/apache/tinkerpop/gremlin/test/features/map/DateDiff.feature
index 0f49b8e094..b3a5d69e0b 100644
--- 
a/gremlin-test/src/main/resources/org/apache/tinkerpop/gremlin/test/features/map/DateDiff.feature
+++ 
b/gremlin-test/src/main/resources/org/apache/tinkerpop/gremlin/test/features/map/DateDiff.feature
@@ -18,6 +18,16 @@
 @StepClassMap @StepDateDiff
 Feature: Step - dateDiff()
 
+  @GraphComputerVerificationInjectionNotSupported
+  Scenario: g_injectXdatetimeXXX_dateDiffXdatetimeXstrXX
+    Given the empty graph
+    And the traversal of
+      """
+      g.inject(datetime()).dateDiff(datetime('2023-01-12T00:00:00Z')).is(gt(0))
+      """
+    When iterated to list
+    Then the result should have a count of 1
+
   @GraphComputerVerificationInjectionNotSupported
   Scenario: g_injectXdatetimeXstr1XX_dateDiffXdatetimeXstr2XX
     Given the empty graph

Reply via email to