This is an automated email from the ASF dual-hosted git repository.
andreac pushed a commit to branch 3.8-dev
in repository https://gitbox.apache.org/repos/asf/tinkerpop.git
The following commit(s) were added to refs/heads/3.8-dev by this push:
new 60f284047e [TINKERPOP-3212] Date manipulation consistency (#3267)
60f284047e is described below
commit 60f284047eb4f63593553472e40050faac356553
Author: andreachild <[email protected]>
AuthorDate: Thu Nov 6 12:45:49 2025 -0800
[TINKERPOP-3212] Date manipulation consistency (#3267)
https://issues.apache.org/jira/browse/TINKERPOP-3212
Improve date handling consistency and allow for round-trippable date
manipulation by changing asNumber() to convert dates to milliseconds since
epoch and dateDiff() to return milliseconds instead of seconds.
---
CHANGELOG.asciidoc | 2 +
docs/src/reference/the-traversal.asciidoc | 8 +++-
docs/src/upgrade/release-3.8.0.asciidoc | 33 +++++++++++++++-
.../process/traversal/step/map/AsNumberStep.java | 15 +++++--
.../process/traversal/step/map/DateDiffStep.java | 2 +-
.../traversal/step/map/AsNumberStepTest.java | 11 ++++++
.../traversal/step/map/DateDiffStepTest.java | 29 +++++++++-----
.../Gremlin.Net.IntegrationTest/Gherkin/Gremlin.cs | 4 ++
gremlin-go/driver/cucumber/gremlin.go | 4 ++
.../gremlin-javascript/test/cucumber/gremlin.js | 4 ++
gremlin-python/src/main/python/radish/gremlin.py | 4 ++
.../gremlin/test/features/data/DateTime.feature | 2 +-
.../gremlin/test/features/map/AsDate.feature | 24 ++++++++++-
.../gremlin/test/features/map/AsNumber.feature | 22 +++++++++++
.../gremlin/test/features/map/DateDiff.feature | 46 +++++++++++++++++++---
15 files changed, 185 insertions(+), 25 deletions(-)
diff --git a/CHANGELOG.asciidoc b/CHANGELOG.asciidoc
index 641cf47641..bee2ee232d 100644
--- a/CHANGELOG.asciidoc
+++ b/CHANGELOG.asciidoc
@@ -109,6 +109,8 @@ This release also includes changes from <<release-3-7-XXX,
3.7.XXX>>.
* Removed the `@RemoteOnly` testing tag in Gherkin as lambda tests have all
been moved to the Java test suite.
* Updated gremlin-javascript to use GraphBinary as default instead of
GraphSONv3
* Added the `asNumber()` step to perform number conversion.
+* Modified `asNumber()` to handle `OffsetDateTime` and `Date`
+* Modified `dateDiff()` to return milliseconds instead of seconds
* Changed `repeat()` to make `repeatTraversal` global rather than a mix of
local and global.
* Renamed many types in the grammar for consistent use of terms "Literal",
"Argument", and "Varargs".
* Changed `gremlin-net` so that System.Text.Json is only listed as an explicit
dependency when it is not available from the framework.
diff --git a/docs/src/reference/the-traversal.asciidoc
b/docs/src/reference/the-traversal.asciidoc
index dc32bc791b..8b8f94dc1c 100644
--- a/docs/src/reference/the-traversal.asciidoc
+++ b/docs/src/reference/the-traversal.asciidoc
@@ -853,6 +853,8 @@ String inputs are parsed into numeric values. By default,
the value will be pars
whole number, or as a double if it contains a decimal point. A
`NumberFormatException` will be thrown if the string
cannot be parsed into a valid number format.
+Date inputs are converted to milliseconds since epoch (January 1, 1970,
00:00:00 GMT).
+
All other input types will result in `IllegalArgumentException`.
[gremlin-groovy,modern]
@@ -860,11 +862,13 @@ All other input types will result in
`IllegalArgumentException`.
g.inject(1234).asNumber() <1>
g.inject(1.76d).asNumber() <2>
g.inject(1.76d).asNumber(GType.INT) <3>
+g.inject("2023-08-02T00:00:00Z").asDate().asNumber() <4>
----
<1> An int will be passed through.
<2> A double will be passed through.
<3> A double is converted into an int.
+<4> A date is converted into milliseconds since epoch.
[NOTE, caption=Java]
====
@@ -1516,7 +1520,7 @@
link:++https://tinkerpop.apache.org/javadocs/x.y.z/core/org/apache/tinkerpop/gre
[[dateDiff-step]]
=== DateDiff Step
-The `dateDiff()`-step (*map*) returns the difference between two Dates in
epoch time.
+The `dateDiff()`-step (*map*) returns the difference between two Dates in
epoch time in milliseconds.
If the incoming traverser is not a Date or OffsetDateTime, then an
`IllegalArgumentException` will be thrown.
[gremlin-groovy,modern]
@@ -1524,7 +1528,7 @@ If the incoming traverser is not a Date or
OffsetDateTime, then an `IllegalArgum
g.inject("2023-08-02T00:00:00Z").asDate().dateDiff(constant("2023-08-03T00:00:00Z").asDate())
<1>
----
-<1> Find difference between two dates
+<1> Find difference between two dates in milliseconds
*Additional References*
diff --git a/docs/src/upgrade/release-3.8.0.asciidoc
b/docs/src/upgrade/release-3.8.0.asciidoc
index c5547429a1..4a0335a44a 100644
--- a/docs/src/upgrade/release-3.8.0.asciidoc
+++ b/docs/src/upgrade/release-3.8.0.asciidoc
@@ -49,6 +49,7 @@ upgrade plan.
|Breaking |New Type Default |<<float-defaults-to-double,Float Defaults to
Double>>
|Breaking |Step Replacement
|<<removal-of-aggregate-with-scope-and-store,Removal of `aggregate()` with
`Scope` and `store()`>>
|Breaking |Step Replacement |<<none-and-discard,none() and discard()>>
+|Breaking |Step Behavior Change
|<<datediff-step-returns-milliseconds,dateDiff() Step Returns Milliseconds>>
|Breaking |Step Behavior Change
|<<repeat-step-global-children-semantics-change,repeat() Step Global Children
Semantics Change>>
|Breaking |Step Behavior Change
|<<modified-limit-skip-range-semantics-in-repeat,Modified limit() skip()
range() Semantics in repeat()>>
|Breaking |Step Behavior Change |<<split-on-empty-string,split() on Empty
String>>
@@ -306,6 +307,28 @@ or 'd') as Double by default. Users who need `BigDecimal`
precision can still us
==== Modified Step Behavior
+===== dateDiff() Step Returns Milliseconds
+
+The `dateDiff()` step has been changed to return milliseconds instead of
seconds for consistency with the `asDate()`
+step which accepts numbers in milliseconds since epoch (January 1, 1970,
00:00:00 GMT) and the new `asNumber()` step
+which converts dates to milliseconds since epoch.
+
+[source,text]
+----
+// In 3.7.x seconds are returned
+gremlin>
g.inject("2023-08-02T00:00:00Z").asDate().dateDiff(constant("2023-08-03T00:00:00Z").asDate())
+==>-86400
+
+// In 3.8.0 milliseconds are returned
+gremlin>
g.inject("2023-08-02T00:00:00Z").asDate().dateDiff(constant("2023-08-03T00:00:00Z").asDate())
+==>-86400000
+// math() and asNumber() steps can be used to obtain seconds instead of
milliseconds
+gremlin>
g.withSideEffect("x",1000).inject("2023-08-02T00:00:00Z").asDate().dateDiff(constant("2023-08-03T00:00:00Z").asDate()).math("_/x").asNumber(GType.LONG)
+==>-86400
+----
+
+See: link:https://issues.apache.org/jira/browse/TINKERPOP-3212[TINKERPOP-3212]
+
===== Changes to `repeat()`
[[repeat-step-global-children-semantics-change]]
@@ -1318,7 +1341,7 @@ The new `asNumber()` step provides type casting
functionality to Gremlin. It ser
strings and casts numbers into desired types. For the convenience of remote
traversals in GLVs, these available types
are denoted by a set of number tokens (`GType`).
-This new step will allow users to normalize their data by converting string
numbers and mixed numeric types to a
+This new step will allow users to normalize their data by converting string
numbers, dates, and mixed numeric types to a
consistent format, making it easier to perform downstream mathematical
operations. As an example:
[source,text]
@@ -1367,6 +1390,14 @@ gremlin> g.inject("128").asNumber(GType.BYTE)
==> ArithmeticException
----
+Dates will be converted to the number of milliseconds since epoch (January 1,
1970, 00:00:00 GMT):
+
+[source,text]
+----
+gremlin> g.inject("2023-08-02T00:00:00Z").asDate().asNumber()
+==>1690934400000
+----
+
All other input types will result in `IllegalArgumentException`:
[source,text]
----
diff --git
a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/AsNumberStep.java
b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/AsNumberStep.java
index e025d57a40..63c4990fe6 100644
---
a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/AsNumberStep.java
+++
b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/AsNumberStep.java
@@ -18,6 +18,8 @@
*/
package org.apache.tinkerpop.gremlin.process.traversal.step.map;
+import java.time.OffsetDateTime;
+import java.util.Date;
import org.apache.commons.lang3.math.NumberUtils;
import org.apache.tinkerpop.gremlin.process.traversal.Traversal;
import org.apache.tinkerpop.gremlin.process.traversal.Traverser;
@@ -53,12 +55,17 @@ public class AsNumberStep<S> extends ScalarMapStep<S,
Number> {
protected Number map(final Traverser.Admin<S> traverser) {
final Object object = traverser.get();
if (object == null) return null;
+ Number number = null;
if (object instanceof String) {
- String numberText = (String) object;
- Number number = parseNumber(numberText);
- return typeToken == null ? number : castNumber(number, typeToken);
+ number = parseNumber((String) object);
} else if (object instanceof Number) {
- Number number = (Number) object;
+ number = (Number) object;
+ } else if (object instanceof Date) {
+ number = ((Date) object).toInstant().toEpochMilli();
+ } else if (object instanceof OffsetDateTime) {
+ number = ((OffsetDateTime) object).toInstant().toEpochMilli();
+ }
+ if (number != null) {
return typeToken == null ? number : castNumber(number, typeToken);
}
throw new IllegalArgumentException(String.format("Can't parse type %s
as number.", object.getClass().getSimpleName()));
diff --git
a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/DateDiffStep.java
b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/DateDiffStep.java
index 0befbdbf32..19d0b40ed0 100644
---
a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/DateDiffStep.java
+++
b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/DateDiffStep.java
@@ -95,7 +95,7 @@ public final class DateDiffStep<S> extends ScalarMapStep<S,
Long> implements Tra
}
// let's not throw exception and assume null date == 0
- return otherDate == null ? date.toEpochSecond() :
Duration.between(otherDate, date).getSeconds();
+ return otherDate == null ? date.toInstant().toEpochMilli() :
Duration.between(otherDate, date).toMillis();
}
@Override
diff --git
a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/AsNumberStepTest.java
b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/AsNumberStepTest.java
index 7c8984214a..f4e2aebd89 100644
---
a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/AsNumberStepTest.java
+++
b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/AsNumberStepTest.java
@@ -18,6 +18,9 @@
*/
package org.apache.tinkerpop.gremlin.process.traversal.step.map;
+import java.time.LocalDateTime;
+import java.time.OffsetDateTime;
+import java.util.Date;
import org.apache.tinkerpop.gremlin.process.traversal.GType;
import org.apache.tinkerpop.gremlin.process.traversal.Traversal;
import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__;
@@ -31,6 +34,7 @@ import java.util.Collections;
import java.util.List;
import java.util.UUID;
+import static java.time.ZoneOffset.UTC;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNull;
@@ -61,6 +65,13 @@ public class AsNumberStepTest extends StepTest {
assertEquals((short) 1, __.__("1").asNumber(GType.SHORT).next());
assertEquals(1L, __.__("1").asNumber(GType.LONG).next());
assertEquals(3.14, __.__("3.14").asNumber(GType.DOUBLE).next());
//float to double
+ // round trip date to number
+ final OffsetDateTime date = OffsetDateTime.of(LocalDateTime.of(2025,
11, 3, 7, 20, 19, 0), UTC);
+ final long dateEpochMillis = date.toInstant().toEpochMilli();
+ assertEquals(date, __.__(date).asNumber().asDate().next());
+ assertEquals(dateEpochMillis,
__.__(dateEpochMillis).asDate().asNumber().next());
+ assertEquals(dateEpochMillis, __.__(new
Date(dateEpochMillis)).asNumber().next());
+ assertEquals(date, __.__(new
Date(dateEpochMillis)).asNumber().asDate().next());
// NumberUtils allows additional string processing
assertEquals(123.0f, __.__("123.").asNumber().next());
assertEquals(291, __.__("0x123").asNumber().next());
diff --git
a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/DateDiffStepTest.java
b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/DateDiffStepTest.java
index 5fb8e0120f..34daf561b8 100644
---
a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/DateDiffStepTest.java
+++
b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/DateDiffStepTest.java
@@ -18,6 +18,8 @@
*/
package org.apache.tinkerpop.gremlin.process.traversal.step.map;
+import java.time.Instant;
+import java.time.LocalDateTime;
import org.apache.tinkerpop.gremlin.process.traversal.Traversal;
import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__;
import org.apache.tinkerpop.gremlin.process.traversal.step.StepTest;
@@ -46,7 +48,7 @@ public class DateDiffStepTest extends StepTest {
final OffsetDateTime now = OffsetDateTime.now(UTC);
final OffsetDateTime other = now.plus(Duration.ofDays(7));
- assertEquals(604800L, (long) __.__(other).dateDiff(now).next());
+ assertEquals(604800000L, (long) __.__(other).dateDiff(now).next());
}
@Test
@@ -54,7 +56,7 @@ public class DateDiffStepTest extends StepTest {
final OffsetDateTime now = OffsetDateTime.now(UTC);
final OffsetDateTime other = now.plus(Duration.ofDays(7));
- assertEquals(-604800L, (long) __.__(now).dateDiff(other).next());
+ assertEquals(-604800000L, (long) __.__(now).dateDiff(other).next());
}
@Test
@@ -62,21 +64,21 @@ public class DateDiffStepTest extends StepTest {
final OffsetDateTime now = OffsetDateTime.now(UTC);
final OffsetDateTime other = now.plus(Duration.ofDays(7));
- assertEquals(-604800L, (long)
__.__(now).dateDiff(__.constant(other)).next());
+ assertEquals(-604800000L, (long)
__.__(now).dateDiff(__.constant(other)).next());
}
@Test
public void shouldHandleNullTraversalParam() {
final OffsetDateTime now = OffsetDateTime.now(UTC);
- assertEquals(now.toEpochSecond(), (long)
__.__(now).dateDiff(__.constant(null)).next());
+ assertEquals(now.toInstant().toEpochMilli(), (long)
__.__(now).dateDiff(__.constant(null)).next());
}
@Test
public void shouldHandleNullDate() {
final OffsetDateTime now = OffsetDateTime.now(UTC);
- assertEquals(now.toEpochSecond(), (long)
__.__(now).dateDiff((OffsetDateTime) null).next());
+ assertEquals(now.toInstant().toEpochMilli(), (long)
__.__(now).dateDiff((OffsetDateTime) null).next());
}
@Test(expected = IllegalArgumentException.class)
@@ -94,7 +96,7 @@ public class DateDiffStepTest extends StepTest {
cal.add(Calendar.DAY_OF_MONTH, 7);
final Date other = cal.getTime();
- assertEquals(604800L, (long) __.__(other).dateDiff(now).next());
+ assertEquals(604800000L, (long) __.__(other).dateDiff(now).next());
}
@Test
@@ -107,7 +109,7 @@ public class DateDiffStepTest extends StepTest {
cal.add(Calendar.DAY_OF_MONTH, 7);
final Date other = cal.getTime();
- assertEquals(-604800L, (long) __.__(now).dateDiff(other).next());
+ assertEquals(-604800000L, (long) __.__(now).dateDiff(other).next());
}
@Test
@@ -120,25 +122,32 @@ public class DateDiffStepTest extends StepTest {
cal.add(Calendar.DAY_OF_MONTH, 7);
final Date other = cal.getTime();
- assertEquals(-604800L, (long)
__.__(now).dateDiff(__.constant(other)).next());
+ assertEquals(-604800000L, (long)
__.__(now).dateDiff(__.constant(other)).next());
}
@Test
public void shouldHandleNullTraversalParamWithDateCompatibility() {
final Date now = new Date();
- assertEquals(now.getTime() / 1000, (long)
__.__(now).dateDiff(__.constant(null)).next());
+ assertEquals(now.toInstant().toEpochMilli(), (long)
__.__(now).dateDiff(__.constant(null)).next());
}
@Test
public void shouldHandleNullDateWithDateCompatibility() {
final Date now = new Date();
- assertEquals(now.getTime() / 1000, (long) __.__(now).dateDiff((Date)
null).next());
+ assertEquals(now.toInstant().toEpochMilli(), (long)
__.__(now).dateDiff((Date) null).next());
}
@Test(expected = IllegalArgumentException.class)
public void shouldThrowWhenInputIsNull() {
__.__((Object) null).dateDiff(new Date()).next();
}
+
+ @Test
+ public void shouldRoundTripWithAsDate() {
+ final OffsetDateTime date = OffsetDateTime.of(LocalDateTime.of(2025,
11, 3, 7, 20, 19, 0), UTC);
+ final OffsetDateTime epoch = Instant.EPOCH.atOffset(UTC);
+ assertEquals(date,
__.__(date.toInstant().toEpochMilli()).asDate().dateDiff(epoch).asDate().next());
+ }
}
diff --git a/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/Gremlin.cs
b/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/Gremlin.cs
index be7233eb54..cfe8d03945 100644
--- a/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/Gremlin.cs
+++ b/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/Gremlin.cs
@@ -944,6 +944,7 @@ namespace Gremlin.Net.IntegrationTest.Gherkin
{"g_injectX1_2X_asDate", new List<Func<GraphTraversalSource,
IDictionary<string, object>, ITraversal>> {(g,p) =>g.Inject<object>(new
List<object> { 1, 2 }).AsDate()}},
{"g_injectXnullX_asDate", new List<Func<GraphTraversalSource,
IDictionary<string, object>, ITraversal>> {(g,p)
=>g.Inject<object>(null).AsDate()}},
{"g_injectXinvalidstrX_asDate", new
List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>>
{(g,p) =>g.Inject<object>("This String is not an ISO 8601 Date").AsDate()}},
+ {"g_V_valuesXbirthdayX_asDate_asNumber_asDate", new
List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>>
{(g,p) =>g.AddV("person").Property("name", "alice").Property("birthday",
"2020-08-02").AddV("person").Property("name", "john").Property("birthday",
"1988-12-10").AddV("person").Property("name", "charlie").Property("birthday",
"2002-02-01").AddV("person").Property("name", "suzy").Property("birthday",
"1965-10-31"), (g,p) =>g.V().Values<object>("birth [...]
{"g_injectX5bX_asNumber", new List<Func<GraphTraversalSource,
IDictionary<string, object>, ITraversal>> {(g,p) =>g.Inject<object>((sbyte)
5).AsNumber()}},
{"g_injectX5sX_asNumber", new List<Func<GraphTraversalSource,
IDictionary<string, object>, ITraversal>> {(g,p) =>g.Inject<object>((short)
5).AsNumber()}},
{"g_injectX5iX_asNumber", new List<Func<GraphTraversalSource,
IDictionary<string, object>, ITraversal>> {(g,p)
=>g.Inject<object>(5).AsNumber()}},
@@ -970,6 +971,7 @@ namespace Gremlin.Net.IntegrationTest.Gherkin
{"g_V_asXaX_outXknowsX_asXbX_mathXa_plus_bX_byXageX_asNumberXGType_INTX", new
List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>>
{(g,p) =>g.V().As("a").Out("knows").As("b").Math("a +
b").By("age").AsNumber(GType.Int)}},
{"g_withSideEffectXx_100X_V_age_mathX__plus_xX_asNumberXGType_LONGX", new
List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>>
{(g,p) =>g.WithSideEffect("x", 100).V().Values<object>("age").Math("_ +
x").AsNumber(GType.Long)}},
{"g_V_valuesXageX_asString_asNumberXGType_DOUBLEX", new
List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>>
{(g,p) =>g.V().Values<object>("age").AsString().AsNumber(GType.Double)}},
+ {"g_V_valuesXbirthdayX_asNumber_asDate_asNumber", new
List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>>
{(g,p) =>g.AddV("person").Property("name", "alice").Property("birthday",
1596326400000).AddV("person").Property("name", "john").Property("birthday",
597715200000).AddV("person").Property("name", "charlie").Property("birthday",
1012521600000).AddV("person").Property("name", "suzy").Property("birthday",
-131587200000), (g,p) =>g.V().Values<object>(" [...]
{"g_injectX1_2X_asString", new List<Func<GraphTraversalSource,
IDictionary<string, object>, ITraversal>> {(g,p) =>g.Inject<object>(1,
2).AsString()}},
{"g_injectX1_2X_asStringXlocalX", new
List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>>
{(g,p) =>g.Inject<object>(1, 2).AsString<object>(Scope.Local)}},
{"g_injectXlist_1_2X_asStringXlocalX", new
List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>>
{(g,p) =>g.Inject<object>(new List<object> { 1, 2
}).AsString<object>(Scope.Local)}},
@@ -1085,6 +1087,8 @@ namespace Gremlin.Net.IntegrationTest.Gherkin
{"g_injectXdatetimeXstr1XX_dateDiffXdatetimeXstr2XX", new
List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>>
{(g,p) =>g.Inject<object>(DateTimeOffset.Parse("2023-08-02T00:00Z"),
DateTimeOffset.Parse("2023-08-02T00:00Z")).DateDiff(DateTimeOffset.Parse("2023-08-09T00:00Z"))}},
{"g_injectXdatetimeXstr1XX_dateDiffXconstantXdatetimeXstr2XXX",
new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>>
{(g,p) =>g.Inject<object>(DateTimeOffset.Parse("2023-08-08T00:00Z"),
DateTimeOffset.Parse("2023-08-08T00:00Z")).DateDiff(__.Constant<object>(DateTimeOffset.Parse("2023-08-01T00:00Z")))}},
{"g_injectXdatetimeXstr1XX_dateDiffXinjectXdatetimeXstr2XXX",
new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>>
{(g,p) =>g.Inject<object>(DateTimeOffset.Parse("2023-08-08T00:00Z"),
DateTimeOffset.Parse("2023-08-08T00:00Z")).DateDiff(__.Inject(DateTimeOffset.Parse("2023-10-11T00:00Z")))}},
+
{"g_V_valuesXbirthdayX_asDate_dateDiffXdatetimeX19700101T0000ZXX", new
List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>>
{(g,p) =>g.AddV("person").Property("name", "alice").Property("birthday",
"1596326400000").AddV("person").Property("name", "john").Property("birthday",
"597715200000").AddV("person").Property("name", "charlie").Property("birthday",
"1012521600000").AddV("person").Property("name", "suzy").Property("birthday",
"-131587200000"), (g,p) [...]
+
{"g_V_hasXname_aliceX_valuesXbirthdayX_asDate_dateDiffXconstantXnullXX", new
List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>>
{(g,p) =>g.AddV("person").Property("name", "alice").Property("birthday",
1596326400000), (g,p) =>g.V().Has("name",
"alice").Values<object>("birthday").AsDate().DateDiff(__.Constant<object>(null))}},
{"g_injectXnullX_differenceXinjectX1XX", new
List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>>
{(g,p) =>g.Inject<object>(null).Difference(__.Inject(1))}},
{"g_V_valuesXnameX_differenceXV_foldX", new
List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>>
{(g,p) =>g.V().Values<object>("name").Difference(__.V().Fold())}},
{"g_V_fold_differenceXconstantXnullXX", new
List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>>
{(g,p) =>g.V().Fold().Difference(__.Constant<object>(null))}},
diff --git a/gremlin-go/driver/cucumber/gremlin.go
b/gremlin-go/driver/cucumber/gremlin.go
index 84c97cad85..63119f6df3 100644
--- a/gremlin-go/driver/cucumber/gremlin.go
+++ b/gremlin-go/driver/cucumber/gremlin.go
@@ -914,6 +914,7 @@ var translationMap = map[string][]func(g
*gremlingo.GraphTraversalSource, p map[
"g_injectX1_2X_asDate": {func(g *gremlingo.GraphTraversalSource, p
map[string]interface{}) *gremlingo.GraphTraversal {return
g.Inject([]interface{}{1, 2}).AsDate()}},
"g_injectXnullX_asDate": {func(g *gremlingo.GraphTraversalSource, p
map[string]interface{}) *gremlingo.GraphTraversal {return
g.Inject(nil).AsDate()}},
"g_injectXinvalidstrX_asDate": {func(g *gremlingo.GraphTraversalSource, p
map[string]interface{}) *gremlingo.GraphTraversal {return g.Inject("This String
is not an ISO 8601 Date").AsDate()}},
+ "g_V_valuesXbirthdayX_asDate_asNumber_asDate": {func(g
*gremlingo.GraphTraversalSource, p map[string]interface{})
*gremlingo.GraphTraversal {return g.AddV("person").Property("name",
"alice").Property("birthday", "2020-08-02").AddV("person").Property("name",
"john").Property("birthday", "1988-12-10").AddV("person").Property("name",
"charlie").Property("birthday", "2002-02-01").AddV("person").Property("name",
"suzy").Property("birthday", "1965-10-31")}, func(g *gremlingo.GraphTraversal
[...]
"g_injectX5bX_asNumber": {func(g *gremlingo.GraphTraversalSource, p
map[string]interface{}) *gremlingo.GraphTraversal {return
g.Inject(int8(5)).AsNumber()}},
"g_injectX5sX_asNumber": {func(g *gremlingo.GraphTraversalSource, p
map[string]interface{}) *gremlingo.GraphTraversal {return
g.Inject(int16(5)).AsNumber()}},
"g_injectX5iX_asNumber": {func(g *gremlingo.GraphTraversalSource, p
map[string]interface{}) *gremlingo.GraphTraversal {return
g.Inject(int32(5)).AsNumber()}},
@@ -940,6 +941,7 @@ var translationMap = map[string][]func(g
*gremlingo.GraphTraversalSource, p map[
"g_V_asXaX_outXknowsX_asXbX_mathXa_plus_bX_byXageX_asNumberXGType_INTX":
{func(g *gremlingo.GraphTraversalSource, p map[string]interface{})
*gremlingo.GraphTraversal {return g.V().As("a").Out("knows").As("b").Math("a +
b").By("age").AsNumber(gremlingo.GType.Int)}},
"g_withSideEffectXx_100X_V_age_mathX__plus_xX_asNumberXGType_LONGX":
{func(g *gremlingo.GraphTraversalSource, p map[string]interface{})
*gremlingo.GraphTraversal {return g.WithSideEffect("x",
100).V().Values("age").Math("_ + x").AsNumber(gremlingo.GType.Long)}},
"g_V_valuesXageX_asString_asNumberXGType_DOUBLEX": {func(g
*gremlingo.GraphTraversalSource, p map[string]interface{})
*gremlingo.GraphTraversal {return
g.V().Values("age").AsString().AsNumber(gremlingo.GType.Double)}},
+ "g_V_valuesXbirthdayX_asNumber_asDate_asNumber": {func(g
*gremlingo.GraphTraversalSource, p map[string]interface{})
*gremlingo.GraphTraversal {return g.AddV("person").Property("name",
"alice").Property("birthday", 1596326400000).AddV("person").Property("name",
"john").Property("birthday", 597715200000).AddV("person").Property("name",
"charlie").Property("birthday", 1012521600000).AddV("person").Property("name",
"suzy").Property("birthday", -131587200000)}, func(g *gremlingo.GraphTrav [...]
"g_injectX1_2X_asString": {func(g *gremlingo.GraphTraversalSource, p
map[string]interface{}) *gremlingo.GraphTraversal {return g.Inject(1,
2).AsString()}},
"g_injectX1_2X_asStringXlocalX": {func(g *gremlingo.GraphTraversalSource,
p map[string]interface{}) *gremlingo.GraphTraversal {return g.Inject(1,
2).AsString(gremlingo.Scope.Local)}},
"g_injectXlist_1_2X_asStringXlocalX": {func(g
*gremlingo.GraphTraversalSource, p map[string]interface{})
*gremlingo.GraphTraversal {return g.Inject([]interface{}{1,
2}).AsString(gremlingo.Scope.Local)}},
@@ -1055,6 +1057,8 @@ var translationMap = map[string][]func(g
*gremlingo.GraphTraversalSource, p map[
"g_injectXdatetimeXstr1XX_dateDiffXdatetimeXstr2XX": {func(g
*gremlingo.GraphTraversalSource, p map[string]interface{})
*gremlingo.GraphTraversal {return g.Inject(time.Date(2023, 8, 2, 0, 0, 0, 0,
time.FixedZone("UTC+00:00", 0)), time.Date(2023, 8, 2, 0, 0, 0, 0,
time.FixedZone("UTC+00:00", 0))).DateDiff(time.Date(2023, 8, 9, 0, 0, 0, 0,
time.FixedZone("UTC+00:00", 0)))}},
"g_injectXdatetimeXstr1XX_dateDiffXconstantXdatetimeXstr2XXX": {func(g
*gremlingo.GraphTraversalSource, p map[string]interface{})
*gremlingo.GraphTraversal {return g.Inject(time.Date(2023, 8, 8, 0, 0, 0, 0,
time.FixedZone("UTC+00:00", 0)), time.Date(2023, 8, 8, 0, 0, 0, 0,
time.FixedZone("UTC+00:00",
0))).DateDiff(gremlingo.T__.Constant(time.Date(2023, 8, 1, 0, 0, 0, 0,
time.FixedZone("UTC+00:00", 0))))}},
"g_injectXdatetimeXstr1XX_dateDiffXinjectXdatetimeXstr2XXX": {func(g
*gremlingo.GraphTraversalSource, p map[string]interface{})
*gremlingo.GraphTraversal {return g.Inject(time.Date(2023, 8, 8, 0, 0, 0, 0,
time.FixedZone("UTC+00:00", 0)), time.Date(2023, 8, 8, 0, 0, 0, 0,
time.FixedZone("UTC+00:00", 0))).DateDiff(gremlingo.T__.Inject(time.Date(2023,
10, 11, 0, 0, 0, 0, time.FixedZone("UTC+00:00", 0))))}},
+ "g_V_valuesXbirthdayX_asDate_dateDiffXdatetimeX19700101T0000ZXX": {func(g
*gremlingo.GraphTraversalSource, p map[string]interface{})
*gremlingo.GraphTraversal {return g.AddV("person").Property("name",
"alice").Property("birthday", "1596326400000").AddV("person").Property("name",
"john").Property("birthday", "597715200000").AddV("person").Property("name",
"charlie").Property("birthday",
"1012521600000").AddV("person").Property("name", "suzy").Property("birthday",
"-131587200000")}, fu [...]
+ "g_V_hasXname_aliceX_valuesXbirthdayX_asDate_dateDiffXconstantXnullXX":
{func(g *gremlingo.GraphTraversalSource, p map[string]interface{})
*gremlingo.GraphTraversal {return g.AddV("person").Property("name",
"alice").Property("birthday", 1596326400000)}, func(g
*gremlingo.GraphTraversalSource, p map[string]interface{})
*gremlingo.GraphTraversal {return g.V().Has("name",
"alice").Values("birthday").AsDate().DateDiff(gremlingo.T__.Constant(nil))}},
"g_injectXnullX_differenceXinjectX1XX": {func(g
*gremlingo.GraphTraversalSource, p map[string]interface{})
*gremlingo.GraphTraversal {return
g.Inject(nil).Difference(gremlingo.T__.Inject(1))}},
"g_V_valuesXnameX_differenceXV_foldX": {func(g
*gremlingo.GraphTraversalSource, p map[string]interface{})
*gremlingo.GraphTraversal {return
g.V().Values("name").Difference(gremlingo.T__.V().Fold())}},
"g_V_fold_differenceXconstantXnullXX": {func(g
*gremlingo.GraphTraversalSource, p map[string]interface{})
*gremlingo.GraphTraversal {return
g.V().Fold().Difference(gremlingo.T__.Constant(nil))}},
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 f75d6bcee3..5e0fc66f47 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
@@ -945,6 +945,7 @@ const gremlins = {
g_injectX1_2X_asDate: [function({g}) { return g.inject([1, 2]).asDate()
}],
g_injectXnullX_asDate: [function({g}) { return g.inject(null).asDate() }],
g_injectXinvalidstrX_asDate: [function({g}) { return g.inject("This String
is not an ISO 8601 Date").asDate() }],
+ g_V_valuesXbirthdayX_asDate_asNumber_asDate: [function({g}) { return
g.addV("person").property("name", "alice").property("birthday",
"2020-08-02").addV("person").property("name", "john").property("birthday",
"1988-12-10").addV("person").property("name", "charlie").property("birthday",
"2002-02-01").addV("person").property("name", "suzy").property("birthday",
"1965-10-31") }, function({g}) { return
g.V().values("birthday").asDate().asNumber().asDate() }],
g_injectX5bX_asNumber: [function({g}) { return g.inject(5).asNumber() }],
g_injectX5sX_asNumber: [function({g}) { return g.inject(5).asNumber() }],
g_injectX5iX_asNumber: [function({g}) { return g.inject(5).asNumber() }],
@@ -971,6 +972,7 @@ const gremlins = {
g_V_asXaX_outXknowsX_asXbX_mathXa_plus_bX_byXageX_asNumberXGType_INTX:
[function({g}) { return g.V().as("a").out("knows").as("b").math("a +
b").by("age").asNumber(GType.int) }],
g_withSideEffectXx_100X_V_age_mathX__plus_xX_asNumberXGType_LONGX:
[function({g}) { return g.withSideEffect("x", 100).V().values("age").math("_ +
x").asNumber(GType.long) }],
g_V_valuesXageX_asString_asNumberXGType_DOUBLEX: [function({g}) { return
g.V().values("age").asString().asNumber(GType.double) }],
+ g_V_valuesXbirthdayX_asNumber_asDate_asNumber: [function({g}) { return
g.addV("person").property("name", "alice").property("birthday",
1596326400000).addV("person").property("name", "john").property("birthday",
597715200000).addV("person").property("name", "charlie").property("birthday",
1012521600000).addV("person").property("name", "suzy").property("birthday",
-131587200000) }, function({g}) { return
g.V().values("birthday").asNumber().asDate().asNumber() }],
g_injectX1_2X_asString: [function({g}) { return g.inject(1, 2).asString()
}],
g_injectX1_2X_asStringXlocalX: [function({g}) { return g.inject(1,
2).asString(Scope.local) }],
g_injectXlist_1_2X_asStringXlocalX: [function({g}) { return g.inject([1,
2]).asString(Scope.local) }],
@@ -1086,6 +1088,8 @@ const gremlins = {
g_injectXdatetimeXstr1XX_dateDiffXdatetimeXstr2XX: [function({g}) { return
g.inject(new Date('2023-08-02T00:00Z'), new
Date('2023-08-02T00:00Z')).dateDiff(new Date('2023-08-09T00:00Z')) }],
g_injectXdatetimeXstr1XX_dateDiffXconstantXdatetimeXstr2XXX:
[function({g}) { return g.inject(new Date('2023-08-08T00:00Z'), new
Date('2023-08-08T00:00Z')).dateDiff(__.constant(new Date('2023-08-01T00:00Z')))
}],
g_injectXdatetimeXstr1XX_dateDiffXinjectXdatetimeXstr2XXX: [function({g})
{ return g.inject(new Date('2023-08-08T00:00Z'), new
Date('2023-08-08T00:00Z')).dateDiff(__.inject(new Date('2023-10-11T00:00Z')))
}],
+ g_V_valuesXbirthdayX_asDate_dateDiffXdatetimeX19700101T0000ZXX:
[function({g}) { return g.addV("person").property("name",
"alice").property("birthday", "1596326400000").addV("person").property("name",
"john").property("birthday", "597715200000").addV("person").property("name",
"charlie").property("birthday",
"1012521600000").addV("person").property("name", "suzy").property("birthday",
"-131587200000") }, function({g}) { return
g.V().values("birthday").asNumber().asDate().dateDiff(new [...]
+ g_V_hasXname_aliceX_valuesXbirthdayX_asDate_dateDiffXconstantXnullXX:
[function({g}) { return g.addV("person").property("name",
"alice").property("birthday", 1596326400000) }, function({g}) { return
g.V().has("name",
"alice").values("birthday").asDate().dateDiff(__.constant(null)) }],
g_injectXnullX_differenceXinjectX1XX: [function({g}) { return
g.inject(null).difference(__.inject(1)) }],
g_V_valuesXnameX_differenceXV_foldX: [function({g}) { return
g.V().values("name").difference(__.V().fold()) }],
g_V_fold_differenceXconstantXnullXX: [function({g}) { return
g.V().fold().difference(__.constant(null)) }],
diff --git a/gremlin-python/src/main/python/radish/gremlin.py
b/gremlin-python/src/main/python/radish/gremlin.py
index a1eddde85f..f371334d8f 100644
--- a/gremlin-python/src/main/python/radish/gremlin.py
+++ b/gremlin-python/src/main/python/radish/gremlin.py
@@ -917,6 +917,7 @@ world.gremlins = {
'g_injectX1_2X_asDate': [(lambda g:g.inject([1, 2]).as_date())],
'g_injectXnullX_asDate': [(lambda g:g.inject(None).as_date())],
'g_injectXinvalidstrX_asDate': [(lambda g:g.inject('This String is not an
ISO 8601 Date').as_date())],
+ 'g_V_valuesXbirthdayX_asDate_asNumber_asDate': [(lambda
g:g.add_v('person').property('name', 'alice').property('birthday',
'2020-08-02').add_v('person').property('name', 'john').property('birthday',
'1988-12-10').add_v('person').property('name', 'charlie').property('birthday',
'2002-02-01').add_v('person').property('name', 'suzy').property('birthday',
'1965-10-31')), (lambda
g:g.V().values('birthday').as_date().as_number().as_date())],
'g_injectX5bX_asNumber': [(lambda g:g.inject(5).as_number())],
'g_injectX5sX_asNumber': [(lambda g:g.inject(5).as_number())],
'g_injectX5iX_asNumber': [(lambda g:g.inject(5).as_number())],
@@ -943,6 +944,7 @@ world.gremlins = {
'g_V_asXaX_outXknowsX_asXbX_mathXa_plus_bX_byXageX_asNumberXGType_INTX':
[(lambda g:g.V().as_('a').out('knows').as_('b').math('a +
b').by('age').as_number(GType.INT))],
'g_withSideEffectXx_100X_V_age_mathX__plus_xX_asNumberXGType_LONGX':
[(lambda g:g.with_side_effect('x', 100).V().values('age').math('_ +
x').as_number(GType.LONG))],
'g_V_valuesXageX_asString_asNumberXGType_DOUBLEX': [(lambda
g:g.V().values('age').as_string().as_number(GType.DOUBLE))],
+ 'g_V_valuesXbirthdayX_asNumber_asDate_asNumber': [(lambda
g:g.add_v('person').property('name', 'alice').property('birthday',
long(1596326400000)).add_v('person').property('name',
'john').property('birthday',
long(597715200000)).add_v('person').property('name',
'charlie').property('birthday',
long(1012521600000)).add_v('person').property('name',
'suzy').property('birthday', long(-131587200000))), (lambda
g:g.V().values('birthday').as_number().as_date().as_number())],
'g_injectX1_2X_asString': [(lambda g:g.inject(1, 2).as_string())],
'g_injectX1_2X_asStringXlocalX': [(lambda g:g.inject(1,
2).as_string(Scope.local))],
'g_injectXlist_1_2X_asStringXlocalX': [(lambda g:g.inject([1,
2]).as_string(Scope.local))],
@@ -1058,6 +1060,8 @@ world.gremlins = {
'g_injectXdatetimeXstr1XX_dateDiffXdatetimeXstr2XX': [(lambda
g:g.inject(datetime.datetime.fromisoformat('2023-08-02T00:00+00:00'),
datetime.datetime.fromisoformat('2023-08-02T00:00+00:00')).date_diff(datetime.datetime.fromisoformat('2023-08-09T00:00+00:00')))],
'g_injectXdatetimeXstr1XX_dateDiffXconstantXdatetimeXstr2XXX': [(lambda
g:g.inject(datetime.datetime.fromisoformat('2023-08-08T00:00+00:00'),
datetime.datetime.fromisoformat('2023-08-08T00:00+00:00')).date_diff(__.constant(datetime.datetime.fromisoformat('2023-08-01T00:00+00:00'))))],
'g_injectXdatetimeXstr1XX_dateDiffXinjectXdatetimeXstr2XXX': [(lambda
g:g.inject(datetime.datetime.fromisoformat('2023-08-08T00:00+00:00'),
datetime.datetime.fromisoformat('2023-08-08T00:00+00:00')).date_diff(__.inject(datetime.datetime.fromisoformat('2023-10-11T00:00+00:00'))))],
+ 'g_V_valuesXbirthdayX_asDate_dateDiffXdatetimeX19700101T0000ZXX': [(lambda
g:g.add_v('person').property('name', 'alice').property('birthday',
'1596326400000').add_v('person').property('name', 'john').property('birthday',
'597715200000').add_v('person').property('name',
'charlie').property('birthday',
'1012521600000').add_v('person').property('name', 'suzy').property('birthday',
'-131587200000')), (lambda
g:g.V().values('birthday').as_number().as_date().date_diff(datetime.datetime.fro
[...]
+ 'g_V_hasXname_aliceX_valuesXbirthdayX_asDate_dateDiffXconstantXnullXX':
[(lambda g:g.add_v('person').property('name', 'alice').property('birthday',
long(1596326400000))), (lambda g:g.V().has('name',
'alice').values('birthday').as_date().date_diff(__.constant(None)))],
'g_injectXnullX_differenceXinjectX1XX': [(lambda
g:g.inject(None).difference(__.inject(1)))],
'g_V_valuesXnameX_differenceXV_foldX': [(lambda
g:g.V().values('name').difference(__.V().fold()))],
'g_V_fold_differenceXconstantXnullXX': [(lambda
g:g.V().fold().difference(__.constant(None)))],
diff --git
a/gremlin-test/src/main/resources/org/apache/tinkerpop/gremlin/test/features/data/DateTime.feature
b/gremlin-test/src/main/resources/org/apache/tinkerpop/gremlin/test/features/data/DateTime.feature
index e6b6722109..a2cd4c65fa 100644
---
a/gremlin-test/src/main/resources/org/apache/tinkerpop/gremlin/test/features/data/DateTime.feature
+++
b/gremlin-test/src/main/resources/org/apache/tinkerpop/gremlin/test/features/data/DateTime.feature
@@ -61,7 +61,7 @@ Feature: Data - DATETIME
When iterated to list
Then the result should be unordered
| result |
- | d[-30].l |
+ | d[-30000].l |
Scenario:
g_V_valuesXdatetimeX_isXtypeOfXGType_DATETIMEXX_whereXisXgtXdatetimeX2020_01_01XXXX
Given the empty graph
diff --git
a/gremlin-test/src/main/resources/org/apache/tinkerpop/gremlin/test/features/map/AsDate.feature
b/gremlin-test/src/main/resources/org/apache/tinkerpop/gremlin/test/features/map/AsDate.feature
index 0e01fb9251..1a1e9f3168 100644
---
a/gremlin-test/src/main/resources/org/apache/tinkerpop/gremlin/test/features/map/AsDate.feature
+++
b/gremlin-test/src/main/resources/org/apache/tinkerpop/gremlin/test/features/map/AsDate.feature
@@ -104,4 +104,26 @@ Feature: Step - asDate()
g.inject('This String is not an ISO 8601 Date').asDate()
"""
When iterated to list
- Then the traversal will raise an error with message containing text of
"Can't parse"
\ No newline at end of file
+ Then the traversal will raise an error with message containing text of
"Can't parse"
+
+ # asDate should be round-trippable with asNumber
+ Scenario: g_V_valuesXbirthdayX_asDate_asNumber_asDate
+ Given the empty graph
+ And the graph initializer of
+ """
+ g.addV("person").property("name", "alice").property("birthday",
"2020-08-02").
+ addV("person").property("name", "john").property("birthday",
"1988-12-10").
+ addV("person").property("name","charlie").property("birthday",
"2002-02-01").
+ addV("person").property("name", "suzy").property("birthday",
"1965-10-31")
+ """
+ And the traversal of
+ """
+ g.V().values("birthday").asDate().asNumber().asDate()
+ """
+ When iterated to list
+ Then the result should be unordered
+ | result |
+ | dt[2020-08-02T00:00:00Z] |
+ | dt[1988-12-10T00:00:00Z] |
+ | dt[2002-02-01T00:00:00Z] |
+ | dt[1965-10-31T00:00:00Z] |
\ No newline at end of file
diff --git
a/gremlin-test/src/main/resources/org/apache/tinkerpop/gremlin/test/features/map/AsNumber.feature
b/gremlin-test/src/main/resources/org/apache/tinkerpop/gremlin/test/features/map/AsNumber.feature
index 831c0b8c4b..6b6680753b 100644
---
a/gremlin-test/src/main/resources/org/apache/tinkerpop/gremlin/test/features/map/AsNumber.feature
+++
b/gremlin-test/src/main/resources/org/apache/tinkerpop/gremlin/test/features/map/AsNumber.feature
@@ -325,3 +325,25 @@ Feature: Step - asNumber()
| d[27.0].d |
| d[32.0].d |
| d[35.0].d |
+
+ # asNumber should be round-trippable with asDate
+ Scenario: g_V_valuesXbirthdayX_asNumber_asDate_asNumber
+ Given the empty graph
+ And the graph initializer of
+ """
+ g.addV("person").property("name", "alice").property("birthday",
1596326400000).
+ addV("person").property("name", "john").property("birthday",
597715200000).
+ addV("person").property("name","charlie").property("birthday",
1012521600000).
+ addV("person").property("name", "suzy").property("birthday",
-131587200000)
+ """
+ And the traversal of
+ """
+ g.V().values("birthday").asNumber().asDate().asNumber()
+ """
+ When iterated to list
+ Then the result should be unordered
+ | result |
+ | d[597715200000].l |
+ | d[1596326400000].l |
+ | d[1012521600000].l |
+ | d[-131587200000].l |
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 5d115b351c..aa15c2e6b4 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
@@ -28,8 +28,8 @@ Feature: Step - dateDiff()
When iterated to list
Then the result should be unordered
| result |
- | d[-604800].l |
- | d[-604800].l |
+ | d[-604800000].l |
+ | d[-604800000].l |
@GraphComputerVerificationInjectionNotSupported
Scenario: g_injectXdatetimeXstr1XX_dateDiffXconstantXdatetimeXstr2XXX
@@ -41,8 +41,8 @@ Feature: Step - dateDiff()
When iterated to list
Then the result should be unordered
| result |
- | d[604800].l |
- | d[604800].l |
+ | d[604800000].l |
+ | d[604800000].l |
@GraphComputerVerificationInjectionNotSupported
Scenario: g_injectXdatetimeXstr1XX_dateDiffXinjectXdatetimeXstr2XXX
@@ -55,4 +55,40 @@ Feature: Step - dateDiff()
Then the result should be unordered
| result |
| d[0].l |
- | d[0].l |
\ No newline at end of file
+ | d[0].l |
+
+ Scenario: g_V_valuesXbirthdayX_asDate_dateDiffXdatetimeX19700101T0000ZXX
+ Given the empty graph
+ And the graph initializer of
+ """
+ g.addV("person").property("name", "alice").property("birthday",
"1596326400000").
+ addV("person").property("name", "john").property("birthday",
"597715200000").
+ addV("person").property("name","charlie").property("birthday",
"1012521600000").
+ addV("person").property("name", "suzy").property("birthday",
"-131587200000")
+ """
+ And the traversal of
+ """
+
g.V().values("birthday").asNumber().asDate().dateDiff(datetime("1970-01-01T00:00Z"))
+ """
+ When iterated to list
+ Then the result should be unordered
+ | result |
+ | d[597715200000].l |
+ | d[1596326400000].l |
+ | d[1012521600000].l |
+ | d[-131587200000].l |
+
+ Scenario:
g_V_hasXname_aliceX_valuesXbirthdayX_asDate_dateDiffXconstantXnullXX
+ Given the empty graph
+ And the graph initializer of
+ """
+ g.addV("person").property("name", "alice").property("birthday",
1596326400000)
+ """
+ And the traversal of
+ """
+ g.V().has("name",
"alice").values("birthday").asDate().dateDiff(__.constant(null))
+ """
+ When iterated to list
+ Then the result should be unordered
+ | result |
+ | d[1596326400000].l |
\ No newline at end of file