diff --git a/hugegraph-core/src/main/java/com/baidu/hugegraph/type/define/DataType.java b/hugegraph-core/src/main/java/com/baidu/hugegraph/type/define/DataType.java index edde77feeb..c39f1fdddb 100644 --- a/hugegraph-core/src/main/java/com/baidu/hugegraph/type/define/DataType.java +++ b/hugegraph-core/src/main/java/com/baidu/hugegraph/type/define/DataType.java @@ -20,12 +20,10 @@ package com.baidu.hugegraph.type.define; import java.io.Serializable; -import java.text.ParseException; import java.util.Date; import java.util.UUID; -import com.baidu.hugegraph.io.HugeGraphSONModule; -import com.baidu.hugegraph.util.E; +import com.baidu.hugegraph.util.DateUtil; public enum DataType implements SerialEnum { @@ -132,13 +130,7 @@ public Date valueToDate(V value) { if (value instanceof Number) { return new Date(((Number) value).longValue()); } else if (value instanceof String) { - try { - return HugeGraphSONModule.DATE_FORMAT.parse((String) value); - } catch (ParseException e) { - E.checkArgument(false, "%s, expect format: %s", - e.getMessage(), - HugeGraphSONModule.DATE_FORMAT.toPattern()); - } + return DateUtil.parse((String) value); } } return null; diff --git a/hugegraph-core/src/main/java/com/baidu/hugegraph/util/DateUtil.java b/hugegraph-core/src/main/java/com/baidu/hugegraph/util/DateUtil.java new file mode 100644 index 0000000000..f6ff4088c9 --- /dev/null +++ b/hugegraph-core/src/main/java/com/baidu/hugegraph/util/DateUtil.java @@ -0,0 +1,89 @@ +/* + * Copyright 2017 HugeGraph Authors + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with this + * work for additional information regarding copyright ownership. The ASF + * licenses this file to You under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + */ + +package com.baidu.hugegraph.util; + +import java.text.ParseException; +import java.util.Date; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +import com.baidu.hugegraph.date.SafeDateFormat; +import com.google.common.collect.ImmutableMap; + +public final class DateUtil { + + private static final Map VALID_DFS = ImmutableMap.of( + "^\\d{4}-\\d{1,2}-\\d{1,2}", + "yyyy-MM-dd", + "^\\d{4}-\\d{1,2}-\\d{1,2}\\s\\d{2}:\\d{2}:\\d{2}", + "yyyy-MM-dd HH:mm:ss", + "^\\d{4}-\\d{1,2}-\\d{1,2}\\s\\d{2}:\\d{2}:\\d{2}\\.\\d{3}", + "yyyy-MM-dd HH:mm:ss.SSS" + ); + + private static final Map DATE_FORMATS = + new ConcurrentHashMap<>(); + + public static Date parse(String value) { + for (Map.Entry entry : VALID_DFS.entrySet()) { + if (value.matches(entry.getKey())) { + try { + return parse(value, entry.getValue()); + } catch (ParseException e) { + throw new IllegalArgumentException(String.format( + "%s, expect format: %s", + e.getMessage(), entry.getValue())); + } + } + } + throw new IllegalArgumentException(String.format( + "Expect date formats are: %s, but got '%s'", + VALID_DFS.values(), value)); + } + + public static Date parse(String value, String df) throws ParseException { + SafeDateFormat dateFormat = getDateFormat(df); + return dateFormat.parse(value); + } + + private static SafeDateFormat getDateFormat(String df) { + SafeDateFormat dateFormat = DATE_FORMATS.get(df); + if (dateFormat == null) { + dateFormat = new SafeDateFormat(df); + /* + * Specify whether or not date/time parsing is to be lenient. + * With lenient parsing, the parser may use heuristics to interpret + * inputs that do not precisely match this object's format. + * With strict parsing, inputs must match this object's format. + */ + dateFormat.setLenient(false); + SafeDateFormat previous = DATE_FORMATS.putIfAbsent(df, dateFormat); + if (previous != null) { + dateFormat = previous; + } + } + return dateFormat; + } + + public static Object toPattern(String df) { + SafeDateFormat dateFormat = getDateFormat(df); + return dateFormat.toPattern(); + } +} diff --git a/hugegraph-test/src/main/java/com/baidu/hugegraph/core/EdgeCoreTest.java b/hugegraph-test/src/main/java/com/baidu/hugegraph/core/EdgeCoreTest.java index ed8cc8f68b..30302c34b1 100644 --- a/hugegraph-test/src/main/java/com/baidu/hugegraph/core/EdgeCoreTest.java +++ b/hugegraph-test/src/main/java/com/baidu/hugegraph/core/EdgeCoreTest.java @@ -1222,9 +1222,9 @@ public void testQueryByDateProperty() { Vertex java3 = graph.addVertex(T.label, "book", "name", "java-3"); Date[] dates = new Date[]{ - Utils.date("2012-01-01 12:30:00.100"), - Utils.date("2013-01-01 12:30:00.100"), - Utils.date("2014-01-01 12:30:00.100") + Utils.date("2012-01-01 00:00:00.000"), + Utils.date("2013-01-01 00:00:00.000"), + Utils.date("2014-01-01 00:00:00.000") }; louise.addEdge("buy", java1, "place", "haidian", "date", dates[0]); @@ -1272,9 +1272,9 @@ public void testQueryByDatePropertyInString() { Vertex java3 = graph.addVertex(T.label, "book", "name", "java-3"); String[] dates = new String[]{ - "2012-01-01 12:30:00.100", - "2013-01-01 12:30:00.100", - "2014-01-01 12:30:00.100" + "2012-01-01 00:00:00.000", + "2013-01-01 00:00:00.000", + "2014-01-01 00:00:00.000" }; louise.addEdge("buy", java1, "place", "haidian", "date", dates[0]); @@ -1324,9 +1324,9 @@ public void testQueryByUnionHasDate() { Vertex java3 = graph.addVertex(T.label, "book", "name", "java-3"); String[] dates = new String[]{ - "2012-01-01 12:30:00.100", - "2013-01-01 12:30:00.100", - "2014-01-01 12:30:00.100" + "2012-01-01 00:00:00.000", + "2013-01-01 00:00:00.000", + "2014-01-01 00:00:00.000" }; louise.addEdge("buy", java1, "place", "haidian", "date", dates[0]); @@ -1354,6 +1354,56 @@ public void testQueryByUnionHasDate() { Assert.assertEquals(2, edges.size()); } + @Test + public void testQueryByDatePropertyInMultiFormatString() { + HugeGraph graph = graph(); + SchemaManager schema = graph.schema(); + + schema.edgeLabel("buy") + .properties("place", "date") + .link("person", "book") + .create(); + schema.indexLabel("buyByDate").onE("buy").by("date").range().create(); + + Vertex louise = graph.addVertex(T.label, "person", "name", "Louise", + "city", "Beijing", "age", 21); + Vertex jeff = graph.addVertex(T.label, "person", "name", "Jeff", + "city", "Beijing", "age", 22); + Vertex sean = graph.addVertex(T.label, "person", "name", "Sean", + "city", "Beijing", "age", 23); + + Vertex java1 = graph.addVertex(T.label, "book", "name", "java-1"); + Vertex java2 = graph.addVertex(T.label, "book", "name", "java-2"); + Vertex java3 = graph.addVertex(T.label, "book", "name", "java-3"); + + String[] dates = new String[]{ + "2012-01-01", + "2013-01-01 00:00:00", + "2014-01-01 00:00:00.000" + }; + + louise.addEdge("buy", java1, "place", "haidian", "date", dates[0]); + jeff.addEdge("buy", java2, "place", "chaoyang", "date", dates[1]); + sean.addEdge("buy", java3, "place", "chaoyang", "date", dates[2]); + + List edges = graph.traversal().E().hasLabel("buy") + .has("date", dates[0]) + .toList(); + Assert.assertEquals(1, edges.size()); + Assert.assertEquals(Utils.date(dates[0]), edges.get(0).value("date")); + + edges = graph.traversal().E().hasLabel("buy") + .has("date", P.gt(dates[0])) + .toList(); + Assert.assertEquals(2, edges.size()); + + edges = graph.traversal().E().hasLabel("buy") + .has("date", P.between(dates[1], dates[2])) + .toList(); + Assert.assertEquals(1, edges.size()); + Assert.assertEquals(Utils.date(dates[1]), edges.get(0).value("date")); + } + @Test public void testQueryByOutEWithDateProperty() { HugeGraph graph = graph(); @@ -1377,9 +1427,9 @@ public void testQueryByOutEWithDateProperty() { Vertex java3 = graph.addVertex(T.label, "book", "name", "java-3"); String[] dates = new String[]{ - "2012-01-01 12:30:00.100", - "2013-01-01 12:30:00.100", - "2014-01-01 12:30:00.100" + "2012-01-01 00:00:00.000", + "2013-01-01 00:00:00.000", + "2014-01-01 00:00:00.000" }; louise.addEdge("buy", java1, "place", "haidian", "date", dates[0]); diff --git a/hugegraph-test/src/main/java/com/baidu/hugegraph/core/PropertyCoreTest.java b/hugegraph-test/src/main/java/com/baidu/hugegraph/core/PropertyCoreTest.java index aa5c81eee5..fe55396dc6 100644 --- a/hugegraph-test/src/main/java/com/baidu/hugegraph/core/PropertyCoreTest.java +++ b/hugegraph-test/src/main/java/com/baidu/hugegraph/core/PropertyCoreTest.java @@ -19,6 +19,7 @@ package com.baidu.hugegraph.core; +import java.text.ParseException; import java.util.Date; import java.util.UUID; @@ -31,6 +32,7 @@ import com.baidu.hugegraph.HugeGraph; import com.baidu.hugegraph.schema.SchemaManager; +import com.baidu.hugegraph.testutil.Utils; public abstract class PropertyCoreTest extends BaseCoreTest { @@ -155,9 +157,17 @@ public void testTypeBlob() { } @Test - public void testTypeDate() { + public void testTypeDate() throws ParseException { Date time = new Date(); Assert.assertEquals(time, property("time", time)); + + Date expected = Utils.date("2018-12-12 00:00:00.000"); + String date = "2018-12-12"; + Assert.assertEquals(expected, property("time", date)); + date = "2018-12-12 00:00:00"; + Assert.assertEquals(expected, property("time", date)); + date = "2018-12-12 00:00:00.000"; + Assert.assertEquals(expected, property("time", date)); } @Test diff --git a/hugegraph-test/src/main/java/com/baidu/hugegraph/core/VertexCoreTest.java b/hugegraph-test/src/main/java/com/baidu/hugegraph/core/VertexCoreTest.java index 2e282f365e..9de04b8b74 100644 --- a/hugegraph-test/src/main/java/com/baidu/hugegraph/core/VertexCoreTest.java +++ b/hugegraph-test/src/main/java/com/baidu/hugegraph/core/VertexCoreTest.java @@ -1346,11 +1346,11 @@ public void testQueryByDateProperty() { List vertices = null; Date[] dates = new Date[]{ - Utils.date("2012-01-01 12:30:00.100"), - Utils.date("2013-01-01 12:30:00.100"), - Utils.date("2014-01-01 12:30:00.100"), - Utils.date("2015-01-01 12:30:00.100"), - Utils.date("2016-01-01 12:30:00.100") + Utils.date("2012-01-01 00:00:00.000"), + Utils.date("2013-01-01 00:00:00.000"), + Utils.date("2014-01-01 00:00:00.000"), + Utils.date("2015-01-01 00:00:00.000"), + Utils.date("2016-01-01 00:00:00.000") }; vertices = graph.traversal().V().hasLabel("person") @@ -1380,11 +1380,11 @@ public void testQueryByDatePropertyInString() { List vertices = null; String[] dates = new String[]{ - "2012-01-01 12:30:00.100", - "2013-01-01 12:30:00.100", - "2014-01-01 12:30:00.100", - "2015-01-01 12:30:00.100", - "2016-01-01 12:30:00.100" + "2012-01-01 00:00:00.000", + "2013-01-01 00:00:00.000", + "2014-01-01 00:00:00.000", + "2015-01-01 00:00:00.000", + "2016-01-01 00:00:00.000" }; vertices = graph.traversal().V().hasLabel("person") @@ -1418,11 +1418,11 @@ public void testQueryByUnionHasDate() { List vertices = null; String[] dates = new String[]{ - "2012-01-01 12:30:00.100", - "2013-01-01 12:30:00.100", - "2014-01-01 12:30:00.100", - "2015-01-01 12:30:00.100", - "2016-01-01 12:30:00.100" + "2012-01-01 00:00:00.000", + "2013-01-01 00:00:00.000", + "2014-01-01 00:00:00.000", + "2015-01-01 00:00:00.000", + "2016-01-01 00:00:00.000" }; vertices = g.V() @@ -1447,6 +1447,42 @@ public void testQueryByUnionHasDate() { Assert.assertEquals(2, vertices.size()); } + @Test + public void testQueryByDatePropertyInMultiFormatString() { + HugeGraph graph = graph(); + initPersonIndex(false); + init5Persons(); + + List vertices = null; + + String[] dates = new String[]{ + "2012-01-01", + "2013-01-01 00:00:00.000", + "2014-01-01 00:00:00.000", + "2015-01-01 00:00:00", + "2016-01-01 00:00:00.000" + }; + + vertices = graph.traversal().V().hasLabel("person") + .has("birth", dates[0]) + .toList(); + Assert.assertEquals(1, vertices.size()); + Assert.assertEquals(Utils.date(dates[0]), + vertices.get(0).value("birth")); + + vertices = graph.traversal().V().hasLabel("person") + .has("birth", P.gt(dates[0])) + .toList(); + Assert.assertEquals(4, vertices.size()); + + vertices = graph.traversal().V().hasLabel("person") + .has("birth", P.between(dates[3], dates[4])) + .toList(); + Assert.assertEquals(1, vertices.size()); + Assert.assertEquals(Utils.date(dates[3]), + vertices.get(0).value("birth")); + } + @Test public void testQueryByTextContainsProperty() { HugeGraph graph = graph(); @@ -3336,19 +3372,19 @@ private void init5Persons() { graph.addVertex(T.label, "person", "name", "Baby", "city", "Hongkong", "age", 3, - "birth", Utils.date("2012-01-01 12:30:00.100")); + "birth", Utils.date("2012-01-01")); graph.addVertex(T.label, "person", "name", "James", "city", "Beijing", "age", 19, - "birth", Utils.date("2013-01-01 12:30:00.100")); + "birth", Utils.date("2013-01-01 00:00:00.000")); graph.addVertex(T.label, "person", "name", "Tom Cat", "city", "Beijing", "age", 20, - "birth", Utils.date("2014-01-01 12:30:00.100")); + "birth", Utils.date("2014-01-01 00:00:00")); graph.addVertex(T.label, "person", "name", "Lisa", "city", "Beijing", "age", 20, - "birth", Utils.date("2015-01-01 12:30:00.100")); + "birth", Utils.date("2015-01-01 00:00:00.000")); graph.addVertex(T.label, "person", "name", "Hebe", "city", "Taipei", "age", 21, - "birth", Utils.date("2016-01-01 12:30:00.100")); + "birth", Utils.date("2016-01-01 00:00:00.000")); graph.tx().commit(); } diff --git a/hugegraph-test/src/main/java/com/baidu/hugegraph/testutil/Utils.java b/hugegraph-test/src/main/java/com/baidu/hugegraph/testutil/Utils.java index 2ac724d3f8..a3342dbde2 100644 --- a/hugegraph-test/src/main/java/com/baidu/hugegraph/testutil/Utils.java +++ b/hugegraph-test/src/main/java/com/baidu/hugegraph/testutil/Utils.java @@ -19,7 +19,6 @@ package com.baidu.hugegraph.testutil; -import java.text.ParseException; import java.util.Date; import java.util.List; @@ -29,9 +28,9 @@ import com.baidu.hugegraph.HugeFactory; import com.baidu.hugegraph.HugeGraph; import com.baidu.hugegraph.backend.id.Id; -import com.baidu.hugegraph.io.HugeGraphSONModule; import com.baidu.hugegraph.testutil.FakeObjects.FakeEdge; import com.baidu.hugegraph.testutil.FakeObjects.FakeVertex; +import com.baidu.hugegraph.util.DateUtil; public class Utils { @@ -79,11 +78,6 @@ public static boolean contains(List edges, FakeEdge fakeEdge) { } public static Date date(String rawDate) { - try { - return HugeGraphSONModule.DATE_FORMAT.parse(rawDate); - } catch (ParseException e) { - throw new IllegalArgumentException(String.format( - "Invalid date '%s'", rawDate)); - } + return DateUtil.parse(rawDate); } }