You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@shardingsphere.apache.org by zh...@apache.org on 2024/11/17 13:30:12 UTC

(shardingsphere) branch master updated: Add TemporalParser (#33698)

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

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


The following commit(s) were added to refs/heads/master by this push:
     new 53fc0f7cdb8 Add TemporalParser (#33698)
53fc0f7cdb8 is described below

commit 53fc0f7cdb8196b90abdd9a419f44f4a5aed7c6d
Author: Liang Zhang <zh...@apache.org>
AuthorDate: Sun Nov 17 21:30:06 2024 +0800

    Add TemporalParser (#33698)
    
    * Add TemporalParser
---
 .../datetime/IntervalShardingAlgorithm.java        | 279 +++------------------
 .../datetime/temporal/TemporalHandler.java         |  67 +++++
 .../datetime/temporal/TemporalHandlerFactory.java  |  62 +++++
 .../temporal/type/LocalDateTemporalHandler.java    |  52 ++++
 .../type/LocalDateTimeTemporalHandler.java         |  51 ++++
 .../temporal/type/LocalTimeTemporalHandler.java    |  52 ++++
 .../temporal/type/MonthTemporalHandler.java        |  58 +++++
 .../temporal/type/YearMonthTemporalHandler.java    |  51 ++++
 .../temporal/type/YearTemporalHandler.java         |  51 ++++
 .../datetime/IntervalShardingAlgorithmTest.java    |   3 +-
 10 files changed, 484 insertions(+), 242 deletions(-)

diff --git a/features/sharding/core/src/main/java/org/apache/shardingsphere/sharding/algorithm/sharding/datetime/IntervalShardingAlgorithm.java b/features/sharding/core/src/main/java/org/apache/shardingsphere/sharding/algorithm/sharding/datetime/IntervalShardingAlgorithm.java
index 2e7bb54dc07..deee7ca06dd 100644
--- a/features/sharding/core/src/main/java/org/apache/shardingsphere/sharding/algorithm/sharding/datetime/IntervalShardingAlgorithm.java
+++ b/features/sharding/core/src/main/java/org/apache/shardingsphere/sharding/algorithm/sharding/datetime/IntervalShardingAlgorithm.java
@@ -22,6 +22,8 @@ import com.google.common.collect.Range;
 import org.apache.shardingsphere.infra.algorithm.core.exception.AlgorithmInitializationException;
 import org.apache.shardingsphere.infra.exception.core.ShardingSpherePreconditions;
 import org.apache.shardingsphere.infra.exception.generic.UnsupportedSQLOperationException;
+import org.apache.shardingsphere.sharding.algorithm.sharding.datetime.temporal.TemporalHandler;
+import org.apache.shardingsphere.sharding.algorithm.sharding.datetime.temporal.TemporalHandlerFactory;
 import org.apache.shardingsphere.sharding.api.sharding.standard.PreciseShardingValue;
 import org.apache.shardingsphere.sharding.api.sharding.standard.RangeShardingValue;
 import org.apache.shardingsphere.sharding.api.sharding.standard.StandardShardingAlgorithm;
@@ -29,23 +31,15 @@ import org.apache.shardingsphere.sharding.exception.data.InvalidDatetimeFormatEx
 import org.apache.shardingsphere.sharding.exception.data.NullShardingValueException;
 
 import java.time.Instant;
-import java.time.LocalDate;
 import java.time.LocalDateTime;
-import java.time.LocalTime;
-import java.time.Month;
-import java.time.Year;
-import java.time.YearMonth;
 import java.time.ZoneId;
 import java.time.format.DateTimeFormatter;
 import java.time.format.DateTimeParseException;
-import java.time.temporal.ChronoField;
 import java.time.temporal.ChronoUnit;
 import java.time.temporal.TemporalAccessor;
-import java.time.temporal.TemporalQueries;
 import java.util.Collection;
 import java.util.HashSet;
 import java.util.Properties;
-import java.util.Set;
 import java.util.stream.Collectors;
 
 /**
@@ -133,230 +127,51 @@ public final class IntervalShardingAlgorithm implements StandardShardingAlgorith
     @Override
     public String doSharding(final Collection<String> availableTargetNames, final PreciseShardingValue<Comparable<?>> shardingValue) {
         ShardingSpherePreconditions.checkNotNull(shardingValue.getValue(), NullShardingValueException::new);
-        return doSharding(availableTargetNames, Range.singleton(shardingValue.getValue())).stream().findFirst().orElse(null);
+        Range<Comparable<?>> range = Range.singleton(shardingValue.getValue());
+        return getMatchedTables(availableTargetNames, range).stream().findFirst().orElse(null);
     }
     
     @Override
     public Collection<String> doSharding(final Collection<String> availableTargetNames, final RangeShardingValue<Comparable<?>> shardingValue) {
-        return doSharding(availableTargetNames, shardingValue.getValueRange());
-    }
-    
-    private Collection<String> doSharding(final Collection<String> availableTargetNames, final Range<Comparable<?>> range) {
-        TemporalAccessor calculateTime = dateTimeLower;
-        if (!calculateTime.isSupported(ChronoField.NANO_OF_DAY)) {
-            if (calculateTime.isSupported(ChronoField.EPOCH_DAY)) {
-                return doShardingInLocalDate(availableTargetNames, range, calculateTime);
-            }
-            if (calculateTime.isSupported(ChronoField.YEAR) && calculateTime.isSupported(ChronoField.MONTH_OF_YEAR)) {
-                return doShardingInYearMonth(availableTargetNames, range, calculateTime);
-            }
-            if (calculateTime.isSupported(ChronoField.YEAR)) {
-                return doShardingInYear(availableTargetNames, range, calculateTime);
-            }
-            if (calculateTime.isSupported(ChronoField.MONTH_OF_YEAR)) {
-                return doShardingInMonth(availableTargetNames, range, calculateTime);
-            }
-        }
-        if (!calculateTime.isSupported(ChronoField.EPOCH_DAY)) {
-            return doShardingInLocalTime(availableTargetNames, range, calculateTime);
-        }
-        return doShardingInLocalDateTime(availableTargetNames, range, calculateTime);
-    }
-    
-    private Collection<String> doShardingInLocalDateTime(final Collection<String> availableTargetNames, final Range<Comparable<?>> range, final TemporalAccessor calculateTime) {
-        Set<String> result = new HashSet<>();
-        LocalDateTime calculateTimeAsView = LocalDateTime.from(calculateTime);
-        LocalDateTime dateTimeUpperAsLocalDateTime = LocalDateTime.from(dateTimeUpper);
-        LocalDateTime dateTimeLowerAsLocalDateTime = LocalDateTime.from(dateTimeLower);
-        while (!calculateTimeAsView.isAfter(dateTimeUpperAsLocalDateTime)) {
-            if (hasIntersection(Range.closedOpen(calculateTimeAsView, calculateTimeAsView.plus(stepAmount, stepUnit)), range, dateTimeLowerAsLocalDateTime, dateTimeUpperAsLocalDateTime)) {
-                result.addAll(getMatchedTables(calculateTimeAsView, availableTargetNames));
-            }
-            calculateTimeAsView = calculateTimeAsView.plus(stepAmount, stepUnit);
-        }
-        return result;
-    }
-    
-    private Collection<String> doShardingInLocalTime(final Collection<String> availableTargetNames, final Range<Comparable<?>> range, final TemporalAccessor calculateTime) {
-        Set<String> result = new HashSet<>();
-        LocalTime dateTimeUpperAsLocalTime = dateTimeUpper.query(TemporalQueries.localTime());
-        LocalTime dateTimeLowerAsLocalTime = dateTimeLower.query(TemporalQueries.localTime());
-        LocalTime calculateTimeAsView = calculateTime.query(TemporalQueries.localTime());
-        while (!calculateTimeAsView.isAfter(dateTimeUpperAsLocalTime)) {
-            if (hasIntersection(Range.closedOpen(calculateTimeAsView, calculateTimeAsView.plus(stepAmount, stepUnit)), range, dateTimeLowerAsLocalTime, dateTimeUpperAsLocalTime)) {
-                result.addAll(getMatchedTables(calculateTimeAsView, availableTargetNames));
-            }
-            calculateTimeAsView = calculateTimeAsView.plus(stepAmount, stepUnit);
-        }
-        return result;
-    }
-    
-    private Collection<String> doShardingInLocalDate(final Collection<String> availableTargetNames, final Range<Comparable<?>> range, final TemporalAccessor calculateTime) {
-        Set<String> result = new HashSet<>();
-        LocalDate dateTimeUpperAsLocalDate = dateTimeUpper.query(TemporalQueries.localDate());
-        LocalDate dateTimeLowerAsLocalDate = dateTimeLower.query(TemporalQueries.localDate());
-        LocalDate calculateTimeAsView = calculateTime.query(TemporalQueries.localDate());
-        while (!calculateTimeAsView.isAfter(dateTimeUpperAsLocalDate)) {
-            if (hasIntersection(Range.closedOpen(calculateTimeAsView, calculateTimeAsView.plus(stepAmount, stepUnit)), range, dateTimeLowerAsLocalDate, dateTimeUpperAsLocalDate)) {
-                result.addAll(getMatchedTables(calculateTimeAsView, availableTargetNames));
+        return getMatchedTables(availableTargetNames, shardingValue.getValueRange());
+    }
+    
+    @SuppressWarnings("unchecked")
+    private <T extends TemporalAccessor & Comparable<?>> Collection<String> getMatchedTables(final Collection<String> availableTargetNames, final Range<Comparable<?>> range) {
+        Collection<String> result = new HashSet<>();
+        TemporalHandler<T> temporalHandler = TemporalHandlerFactory.newInstance(dateTimeLower);
+        T dateTimeUpper = temporalHandler.convertTo(this.dateTimeUpper);
+        T dateTimeLower = temporalHandler.convertTo(this.dateTimeLower);
+        T calculateTimeAsView = temporalHandler.convertTo(this.dateTimeLower);
+        while (!temporalHandler.isAfter(calculateTimeAsView, dateTimeUpper, stepAmount)) {
+            if (hasIntersection(Range.closedOpen(calculateTimeAsView, temporalHandler.add(calculateTimeAsView, stepAmount, stepUnit)), range, dateTimeLower, dateTimeUpper, temporalHandler)) {
+                result.addAll(getMatchedTables(calculateTimeAsView, availableTargetNames, temporalHandler));
             }
-            calculateTimeAsView = calculateTimeAsView.plus(stepAmount, stepUnit);
+            calculateTimeAsView = temporalHandler.add(calculateTimeAsView, stepAmount, stepUnit);
         }
         return result;
     }
     
-    private Collection<String> doShardingInYear(final Collection<String> availableTargetNames, final Range<Comparable<?>> range, final TemporalAccessor calculateTime) {
-        Set<String> result = new HashSet<>();
-        Year dateTimeUpperAsYear = dateTimeUpper.query(Year::from);
-        Year dateTimeLowerAsYear = dateTimeLower.query(Year::from);
-        Year calculateTimeAsView = calculateTime.query(Year::from);
-        while (!calculateTimeAsView.isAfter(dateTimeUpperAsYear)) {
-            if (hasIntersection(Range.closedOpen(calculateTimeAsView, calculateTimeAsView.plus(stepAmount, stepUnit)), range, dateTimeLowerAsYear, dateTimeUpperAsYear)) {
-                result.addAll(getMatchedTables(calculateTimeAsView, availableTargetNames));
-            }
-            calculateTimeAsView = calculateTimeAsView.plus(stepAmount, stepUnit);
-        }
-        return result;
+    private <T extends TemporalAccessor & Comparable<?>> Collection<String> getMatchedTables(final TemporalAccessor calculateTimeAsView,
+                                                                                             final Collection<String> availableTargetNames, final TemporalHandler<T> temporalHandler) {
+        return availableTargetNames.parallelStream().filter(each -> each.endsWith(tableSuffixPattern.format(temporalHandler.convertTo(calculateTimeAsView)))).collect(Collectors.toSet());
     }
     
-    private Collection<String> doShardingInMonth(final Collection<String> availableTargetNames, final Range<Comparable<?>> range, final TemporalAccessor calculateTime) {
-        Set<String> result = new HashSet<>();
-        Month dateTimeUpperAsMonth = dateTimeUpper.query(Month::from);
-        Month dateTimeLowerAsMonth = dateTimeLower.query(Month::from);
-        Month calculateTimeAsView = calculateTime.query(Month::from);
-        while (calculateTimeAsView.getValue() <= dateTimeUpperAsMonth.getValue() && (calculateTimeAsView.getValue() + stepAmount) <= Month.DECEMBER.getValue()) {
-            if (hasIntersection(Range.closedOpen(calculateTimeAsView, calculateTimeAsView.plus(stepAmount)), range, dateTimeLowerAsMonth, dateTimeUpperAsMonth)) {
-                result.addAll(getMatchedTables(calculateTimeAsView, availableTargetNames));
-            }
-            calculateTimeAsView = calculateTimeAsView.plus(stepAmount);
-        }
-        return result;
-    }
-    
-    private Collection<String> doShardingInYearMonth(final Collection<String> availableTargetNames, final Range<Comparable<?>> range, final TemporalAccessor calculateTime) {
-        Set<String> result = new HashSet<>();
-        YearMonth dateTimeUpperAsYearMonth = dateTimeUpper.query(YearMonth::from);
-        YearMonth dateTimeLowerAsYearMonth = dateTimeLower.query(YearMonth::from);
-        YearMonth calculateTimeAsView = calculateTime.query(YearMonth::from);
-        while (!calculateTimeAsView.isAfter(dateTimeUpperAsYearMonth)) {
-            if (hasIntersection(Range.closedOpen(calculateTimeAsView, calculateTimeAsView.plus(stepAmount, stepUnit)), range, dateTimeLowerAsYearMonth, dateTimeUpperAsYearMonth)) {
-                result.addAll(getMatchedTables(calculateTimeAsView, availableTargetNames));
-            }
-            calculateTimeAsView = calculateTimeAsView.plus(stepAmount, stepUnit);
-        }
-        return result;
-    }
-    
-    private boolean hasIntersection(final Range<LocalDateTime> calculateRange, final Range<Comparable<?>> range, final LocalDateTime dateTimeLower, final LocalDateTime dateTimeUpper) {
-        LocalDateTime lower = range.hasLowerBound() ? parseLocalDateTime(range.lowerEndpoint()) : dateTimeLower;
-        LocalDateTime upper = range.hasUpperBound() ? parseLocalDateTime(range.upperEndpoint()) : dateTimeUpper;
+    private <T extends TemporalAccessor & Comparable<?>> boolean hasIntersection(final Range<T> calculateRange, final Range<Comparable<?>> range,
+                                                                                 final T temporalLower, final T temporalUpper, final TemporalHandler<T> temporalHandler) {
+        T lower = range.hasLowerBound() ? parseTemporal(range.lowerEndpoint(), temporalHandler) : temporalLower;
+        T upper = range.hasUpperBound() ? parseTemporal(range.upperEndpoint(), temporalHandler) : temporalUpper;
         BoundType lowerBoundType = range.hasLowerBound() ? range.lowerBoundType() : BoundType.CLOSED;
         BoundType upperBoundType = range.hasUpperBound() ? range.upperBoundType() : BoundType.CLOSED;
-        Range<LocalDateTime> dateTimeRange = Range.range(lower, lowerBoundType, upper, upperBoundType);
+        Range<T> dateTimeRange = Range.range(lower, lowerBoundType, upper, upperBoundType);
         return calculateRange.isConnected(dateTimeRange) && !calculateRange.intersection(dateTimeRange).isEmpty();
     }
     
-    private boolean hasIntersection(final Range<LocalDate> calculateRange, final Range<Comparable<?>> range, final LocalDate dateTimeLower, final LocalDate dateTimeUpper) {
-        LocalDate lower = range.hasLowerBound() ? parseLocalDate(range.lowerEndpoint()) : dateTimeLower;
-        LocalDate upper = range.hasUpperBound() ? parseLocalDate(range.upperEndpoint()) : dateTimeUpper;
-        BoundType lowerBoundType = range.hasLowerBound() ? range.lowerBoundType() : BoundType.CLOSED;
-        BoundType upperBoundType = range.hasUpperBound() ? range.upperBoundType() : BoundType.CLOSED;
-        Range<LocalDate> dateTimeRange = Range.range(lower, lowerBoundType, upper, upperBoundType);
-        return calculateRange.isConnected(dateTimeRange) && !calculateRange.intersection(dateTimeRange).isEmpty();
-    }
-    
-    private boolean hasIntersection(final Range<LocalTime> calculateRange, final Range<Comparable<?>> range, final LocalTime dateTimeLower, final LocalTime dateTimeUpper) {
-        LocalTime lower = range.hasLowerBound() ? parseLocalTime(range.lowerEndpoint()) : dateTimeLower;
-        LocalTime upper = range.hasUpperBound() ? parseLocalTime(range.upperEndpoint()) : dateTimeUpper;
-        BoundType lowerBoundType = range.hasLowerBound() ? range.lowerBoundType() : BoundType.CLOSED;
-        BoundType upperBoundType = range.hasUpperBound() ? range.upperBoundType() : BoundType.CLOSED;
-        Range<LocalTime> dateTimeRange = Range.range(lower, lowerBoundType, upper, upperBoundType);
-        return calculateRange.isConnected(dateTimeRange) && !calculateRange.intersection(dateTimeRange).isEmpty();
-    }
-    
-    private boolean hasIntersection(final Range<Year> calculateRange, final Range<Comparable<?>> range, final Year dateTimeLower, final Year dateTimeUpper) {
-        Year lower = range.hasLowerBound() ? parseYear(range.lowerEndpoint()) : dateTimeLower;
-        Year upper = range.hasUpperBound() ? parseYear(range.upperEndpoint()) : dateTimeUpper;
-        BoundType lowerBoundType = range.hasLowerBound() ? range.lowerBoundType() : BoundType.CLOSED;
-        BoundType upperBoundType = range.hasUpperBound() ? range.upperBoundType() : BoundType.CLOSED;
-        Range<Year> dateTimeRange = Range.range(lower, lowerBoundType, upper, upperBoundType);
-        return calculateRange.isConnected(dateTimeRange) && !calculateRange.intersection(dateTimeRange).isEmpty();
-    }
-    
-    private boolean hasIntersection(final Range<Month> calculateRange, final Range<Comparable<?>> range, final Month dateTimeLower, final Month dateTimeUpper) {
-        Month lower = range.hasLowerBound() ? parseMonth(range.lowerEndpoint()) : dateTimeLower;
-        Month upper = range.hasUpperBound() ? parseMonth(range.upperEndpoint()) : dateTimeUpper;
-        BoundType lowerBoundType = range.hasLowerBound() ? range.lowerBoundType() : BoundType.CLOSED;
-        BoundType upperBoundType = range.hasUpperBound() ? range.upperBoundType() : BoundType.CLOSED;
-        Range<Month> dateTimeRange = Range.range(lower, lowerBoundType, upper, upperBoundType);
-        return calculateRange.isConnected(dateTimeRange) && !calculateRange.intersection(dateTimeRange).isEmpty();
-    }
-    
-    private boolean hasIntersection(final Range<YearMonth> calculateRange, final Range<Comparable<?>> range, final YearMonth dateTimeLower, final YearMonth dateTimeUpper) {
-        YearMonth lower = range.hasLowerBound() ? parseYearMonth(range.lowerEndpoint()) : dateTimeLower;
-        YearMonth upper = range.hasUpperBound() ? parseYearMonth(range.upperEndpoint()) : dateTimeUpper;
-        BoundType lowerBoundType = range.hasLowerBound() ? range.lowerBoundType() : BoundType.CLOSED;
-        BoundType upperBoundType = range.hasUpperBound() ? range.upperBoundType() : BoundType.CLOSED;
-        Range<YearMonth> dateTimeRange = Range.range(lower, lowerBoundType, upper, upperBoundType);
-        return calculateRange.isConnected(dateTimeRange) && !calculateRange.intersection(dateTimeRange).isEmpty();
-    }
-    
-    private LocalDateTime parseLocalDateTime(final Comparable<?> endpoint) {
-        String dateTimeText = getDateTimeText(endpoint);
-        return dateTimeText.length() >= dateTimePatternLength
-                ? LocalDateTime.parse(dateTimeText.substring(0, dateTimePatternLength), dateTimeFormatter)
-                : LocalDateTime.parse(dateTimeText, createRelaxedDateTimeFormatter(dateTimeText));
-    }
-    
-    private LocalDate parseLocalDate(final Comparable<?> endpoint) {
-        String dateTimeText = getDateTimeText(endpoint);
-        return dateTimeText.length() >= dateTimePatternLength
-                ? LocalDate.parse(dateTimeText.substring(0, dateTimePatternLength), dateTimeFormatter)
-                : LocalDate.parse(dateTimeText, createRelaxedDateTimeFormatter(dateTimeText));
-    }
-    
-    private LocalTime parseLocalTime(final Comparable<?> endpoint) {
-        String dateTimeText = getDateTimeText(endpoint);
-        return dateTimeText.length() >= dateTimePatternLength
-                ? LocalTime.parse(dateTimeText.substring(0, dateTimePatternLength), dateTimeFormatter)
-                : LocalTime.parse(dateTimeText, createRelaxedDateTimeFormatter(dateTimeText));
-    }
-    
-    private Year parseYear(final Comparable<?> endpoint) {
+    private <T extends TemporalAccessor> T parseTemporal(final Comparable<?> endpoint, final TemporalHandler<T> temporalHandler) {
         String dateTimeText = getDateTimeText(endpoint);
         return dateTimeText.length() >= dateTimePatternLength
-                ? Year.parse(dateTimeText.substring(0, dateTimePatternLength), dateTimeFormatter)
-                : Year.parse(dateTimeText, createRelaxedDateTimeFormatter(dateTimeText));
-    }
-    
-    private YearMonth parseYearMonth(final Comparable<?> endpoint) {
-        String dateTimeText = getDateTimeText(endpoint);
-        return dateTimeText.length() >= dateTimePatternLength
-                ? YearMonth.parse(dateTimeText.substring(0, dateTimePatternLength), dateTimeFormatter)
-                : YearMonth.parse(dateTimeText, createRelaxedDateTimeFormatter(dateTimeText));
-    }
-    
-    /**
-     * After the sharding key is formatted as a {@link String},
-     * if the length of the {@link String} is less than `datetime-pattern`,
-     * it usually means there is a problem with the sharding key.
-     * @param endpoint A class carrying time information with an unknown class name.
-     * @return {@link java.time.Month}
-     */
-    private Month parseMonth(final Comparable<?> endpoint) {
-        return Month.of(Integer.parseInt(getDateTimeText(endpoint).substring(0, dateTimePatternLength)));
-    }
-    
-    /**
-     * When the sharding key is a {@link String} and the length of this {@link String} is less than the `datetime-pattern` set by the algorithm,
-     * ShardingSphere will try to use a substring of `datetime-pattern` to parse the sharding key.
-     * This is to be compatible with the behavior of ORM libraries such as <a href="https://github.com/go-gorm/gorm">go-gorm/gorm</a>.
-     * @param dateTimeText Sharding key with class name {@link String}
-     * @return Child `datetime-pattern`, the pattern length is consistent with the shard key.
-     */
-    private DateTimeFormatter createRelaxedDateTimeFormatter(final String dateTimeText) {
-        String dateTimeFormatterString = dateTimePatternString.substring(0, dateTimeText.length());
-        return DateTimeFormatter.ofPattern(dateTimeFormatterString);
+                ? temporalHandler.parse(dateTimeText.substring(0, dateTimePatternLength), dateTimeFormatter)
+                : temporalHandler.parse(dateTimeText, createRelaxedDateTimeFormatter(dateTimeText));
     }
     
     private String getDateTimeText(final Comparable<?> endpoint) {
@@ -375,32 +190,16 @@ public final class IntervalShardingAlgorithm implements StandardShardingAlgorith
         return endpoint.toString();
     }
     
-    private Collection<String> getMatchedTables(final TemporalAccessor dateTime, final Collection<String> availableTargetNames) {
-        String tableSuffix;
-        if (!dateTime.isSupported(ChronoField.NANO_OF_DAY)) {
-            if (dateTime.isSupported(ChronoField.EPOCH_DAY)) {
-                tableSuffix = tableSuffixPattern.format(dateTime.query(TemporalQueries.localDate()));
-                return availableTargetNames.parallelStream().filter(each -> each.endsWith(tableSuffix)).collect(Collectors.toSet());
-            }
-            if (dateTime.isSupported(ChronoField.YEAR) && dateTime.isSupported(ChronoField.MONTH_OF_YEAR)) {
-                tableSuffix = tableSuffixPattern.format(dateTime.query(YearMonth::from));
-                return availableTargetNames.parallelStream().filter(each -> each.endsWith(tableSuffix)).collect(Collectors.toSet());
-            }
-            if (dateTime.isSupported(ChronoField.YEAR)) {
-                tableSuffix = tableSuffixPattern.format(dateTime.query(Year::from));
-                return availableTargetNames.parallelStream().filter(each -> each.endsWith(tableSuffix)).collect(Collectors.toSet());
-            }
-            if (dateTime.isSupported(ChronoField.MONTH_OF_YEAR)) {
-                tableSuffix = tableSuffixPattern.format(dateTime.query(Month::from));
-                return availableTargetNames.parallelStream().filter(each -> each.endsWith(tableSuffix)).collect(Collectors.toSet());
-            }
-        }
-        if (!dateTime.isSupported(ChronoField.EPOCH_DAY)) {
-            tableSuffix = dateTime.query(TemporalQueries.localTime()).format(tableSuffixPattern);
-            return availableTargetNames.parallelStream().filter(each -> each.endsWith(tableSuffix)).collect(Collectors.toSet());
-        }
-        tableSuffix = LocalDateTime.from(dateTime).format(tableSuffixPattern);
-        return availableTargetNames.parallelStream().filter(each -> each.endsWith(tableSuffix)).collect(Collectors.toSet());
+    /*
+     * When the sharding key is a {@link String} and the length of this {@link String} is less than the `datetime-pattern` set by the algorithm, ShardingSphere will try to use a substring of
+     * `datetime-pattern` to parse the sharding key. This is to be compatible with the behavior of ORM libraries such as <a href="https://github.com/go-gorm/gorm">go-gorm/gorm</a>.
+     *
+     * @param dateTimeText Sharding key with class name {@link String}
+     *
+     * @return Child `datetime-pattern`, the pattern length is consistent with the shard key.
+     */
+    private DateTimeFormatter createRelaxedDateTimeFormatter(final String dateTimeText) {
+        return DateTimeFormatter.ofPattern(dateTimePatternString.substring(0, dateTimeText.length()));
     }
     
     @Override
diff --git a/features/sharding/core/src/main/java/org/apache/shardingsphere/sharding/algorithm/sharding/datetime/temporal/TemporalHandler.java b/features/sharding/core/src/main/java/org/apache/shardingsphere/sharding/algorithm/sharding/datetime/temporal/TemporalHandler.java
new file mode 100644
index 00000000000..eba11286188
--- /dev/null
+++ b/features/sharding/core/src/main/java/org/apache/shardingsphere/sharding/algorithm/sharding/datetime/temporal/TemporalHandler.java
@@ -0,0 +1,67 @@
+/*
+ * 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 org.apache.shardingsphere.sharding.algorithm.sharding.datetime.temporal;
+
+import java.time.format.DateTimeFormatter;
+import java.time.temporal.TemporalAccessor;
+import java.time.temporal.TemporalUnit;
+
+/**
+ * Temporal handler.
+ * 
+ * @param <T> type of temporal
+ */
+public interface TemporalHandler<T extends TemporalAccessor> {
+    
+    /**
+     * Parse from text.
+     *
+     * @param text temporal text
+     * @param formatter date time formatter
+     * @return parsed temporal
+     */
+    T parse(CharSequence text, DateTimeFormatter formatter);
+    
+    /**
+     * Convert temporal.
+     *
+     * @param temporal to be converted temporal
+     * @return converted temporal
+     */
+    T convertTo(TemporalAccessor temporal);
+    
+    /**
+     * Judge whether temporal1 is after temporal2.
+     *
+     * @param temporal1 temporal1
+     * @param temporal2 temporal2
+     * @param stepAmount step amount
+     * @return is temporal1 after temporal2 or not
+     */
+    boolean isAfter(T temporal1, T temporal2, int stepAmount);
+    
+    /**
+     * Add temporal.
+     *
+     * @param temporal to be added temporal
+     * @param stepAmount to be added step amount
+     * @param unit temporal unit
+     * @return added temporal
+     */
+    T add(T temporal, long stepAmount, TemporalUnit unit);
+}
diff --git a/features/sharding/core/src/main/java/org/apache/shardingsphere/sharding/algorithm/sharding/datetime/temporal/TemporalHandlerFactory.java b/features/sharding/core/src/main/java/org/apache/shardingsphere/sharding/algorithm/sharding/datetime/temporal/TemporalHandlerFactory.java
new file mode 100644
index 00000000000..48c09a5be08
--- /dev/null
+++ b/features/sharding/core/src/main/java/org/apache/shardingsphere/sharding/algorithm/sharding/datetime/temporal/TemporalHandlerFactory.java
@@ -0,0 +1,62 @@
+/*
+ * 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 org.apache.shardingsphere.sharding.algorithm.sharding.datetime.temporal;
+
+import lombok.AccessLevel;
+import lombok.NoArgsConstructor;
+import org.apache.shardingsphere.sharding.algorithm.sharding.datetime.temporal.type.LocalDateTemporalHandler;
+import org.apache.shardingsphere.sharding.algorithm.sharding.datetime.temporal.type.LocalDateTimeTemporalHandler;
+import org.apache.shardingsphere.sharding.algorithm.sharding.datetime.temporal.type.LocalTimeTemporalHandler;
+import org.apache.shardingsphere.sharding.algorithm.sharding.datetime.temporal.type.MonthTemporalHandler;
+import org.apache.shardingsphere.sharding.algorithm.sharding.datetime.temporal.type.YearMonthTemporalHandler;
+import org.apache.shardingsphere.sharding.algorithm.sharding.datetime.temporal.type.YearTemporalHandler;
+
+import java.time.temporal.ChronoField;
+import java.time.temporal.TemporalAccessor;
+
+/**
+ * Temporal handler factory.
+ */
+@NoArgsConstructor(access = AccessLevel.NONE)
+public final class TemporalHandlerFactory {
+    
+    /**
+     * Create new instance of temporal handler.
+     *
+     * @param temporal temporal
+     * @return temporal handler
+     */
+    @SuppressWarnings("rawtypes")
+    public static TemporalHandler newInstance(final TemporalAccessor temporal) {
+        if (!temporal.isSupported(ChronoField.NANO_OF_DAY)) {
+            if (temporal.isSupported(ChronoField.EPOCH_DAY)) {
+                return new LocalDateTemporalHandler();
+            }
+            if (temporal.isSupported(ChronoField.YEAR) && temporal.isSupported(ChronoField.MONTH_OF_YEAR)) {
+                return new YearMonthTemporalHandler();
+            }
+            if (temporal.isSupported(ChronoField.YEAR)) {
+                return new YearTemporalHandler();
+            }
+            if (temporal.isSupported(ChronoField.MONTH_OF_YEAR)) {
+                return new MonthTemporalHandler();
+            }
+        }
+        return temporal.isSupported(ChronoField.EPOCH_DAY) ? new LocalDateTimeTemporalHandler() : new LocalTimeTemporalHandler();
+    }
+}
diff --git a/features/sharding/core/src/main/java/org/apache/shardingsphere/sharding/algorithm/sharding/datetime/temporal/type/LocalDateTemporalHandler.java b/features/sharding/core/src/main/java/org/apache/shardingsphere/sharding/algorithm/sharding/datetime/temporal/type/LocalDateTemporalHandler.java
new file mode 100644
index 00000000000..0035e27fc72
--- /dev/null
+++ b/features/sharding/core/src/main/java/org/apache/shardingsphere/sharding/algorithm/sharding/datetime/temporal/type/LocalDateTemporalHandler.java
@@ -0,0 +1,52 @@
+/*
+ * 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 org.apache.shardingsphere.sharding.algorithm.sharding.datetime.temporal.type;
+
+import org.apache.shardingsphere.sharding.algorithm.sharding.datetime.temporal.TemporalHandler;
+
+import java.time.LocalDate;
+import java.time.format.DateTimeFormatter;
+import java.time.temporal.TemporalAccessor;
+import java.time.temporal.TemporalQueries;
+import java.time.temporal.TemporalUnit;
+
+/**
+ * Local date temporal handler.
+ */
+public final class LocalDateTemporalHandler implements TemporalHandler<LocalDate> {
+    
+    @Override
+    public LocalDate parse(final CharSequence text, final DateTimeFormatter formatter) {
+        return LocalDate.parse(text, formatter);
+    }
+    
+    @Override
+    public LocalDate convertTo(final TemporalAccessor temporal) {
+        return temporal.query(TemporalQueries.localDate());
+    }
+    
+    @Override
+    public boolean isAfter(final LocalDate temporal1, final LocalDate temporal2, final int stepAmount) {
+        return temporal1.isAfter(temporal2);
+    }
+    
+    @Override
+    public LocalDate add(final LocalDate temporal, final long stepAmount, final TemporalUnit unit) {
+        return temporal.plus(stepAmount, unit);
+    }
+}
diff --git a/features/sharding/core/src/main/java/org/apache/shardingsphere/sharding/algorithm/sharding/datetime/temporal/type/LocalDateTimeTemporalHandler.java b/features/sharding/core/src/main/java/org/apache/shardingsphere/sharding/algorithm/sharding/datetime/temporal/type/LocalDateTimeTemporalHandler.java
new file mode 100644
index 00000000000..3fb9f45bd7a
--- /dev/null
+++ b/features/sharding/core/src/main/java/org/apache/shardingsphere/sharding/algorithm/sharding/datetime/temporal/type/LocalDateTimeTemporalHandler.java
@@ -0,0 +1,51 @@
+/*
+ * 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 org.apache.shardingsphere.sharding.algorithm.sharding.datetime.temporal.type;
+
+import org.apache.shardingsphere.sharding.algorithm.sharding.datetime.temporal.TemporalHandler;
+
+import java.time.LocalDateTime;
+import java.time.format.DateTimeFormatter;
+import java.time.temporal.TemporalAccessor;
+import java.time.temporal.TemporalUnit;
+
+/**
+ * Local date time temporal handler.
+ */
+public final class LocalDateTimeTemporalHandler implements TemporalHandler<LocalDateTime> {
+    
+    @Override
+    public LocalDateTime parse(final CharSequence text, final DateTimeFormatter formatter) {
+        return LocalDateTime.parse(text, formatter);
+    }
+    
+    @Override
+    public LocalDateTime convertTo(final TemporalAccessor temporal) {
+        return LocalDateTime.from(temporal);
+    }
+    
+    @Override
+    public boolean isAfter(final LocalDateTime temporal1, final LocalDateTime temporal2, final int stepAmount) {
+        return temporal1.isAfter(temporal2);
+    }
+    
+    @Override
+    public LocalDateTime add(final LocalDateTime temporal, final long stepAmount, final TemporalUnit unit) {
+        return temporal.plus(stepAmount, unit);
+    }
+}
diff --git a/features/sharding/core/src/main/java/org/apache/shardingsphere/sharding/algorithm/sharding/datetime/temporal/type/LocalTimeTemporalHandler.java b/features/sharding/core/src/main/java/org/apache/shardingsphere/sharding/algorithm/sharding/datetime/temporal/type/LocalTimeTemporalHandler.java
new file mode 100644
index 00000000000..c5671be9c17
--- /dev/null
+++ b/features/sharding/core/src/main/java/org/apache/shardingsphere/sharding/algorithm/sharding/datetime/temporal/type/LocalTimeTemporalHandler.java
@@ -0,0 +1,52 @@
+/*
+ * 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 org.apache.shardingsphere.sharding.algorithm.sharding.datetime.temporal.type;
+
+import org.apache.shardingsphere.sharding.algorithm.sharding.datetime.temporal.TemporalHandler;
+
+import java.time.LocalTime;
+import java.time.format.DateTimeFormatter;
+import java.time.temporal.TemporalAccessor;
+import java.time.temporal.TemporalQueries;
+import java.time.temporal.TemporalUnit;
+
+/**
+ * Local time temporal handler.
+ */
+public final class LocalTimeTemporalHandler implements TemporalHandler<LocalTime> {
+    
+    @Override
+    public LocalTime parse(final CharSequence text, final DateTimeFormatter formatter) {
+        return LocalTime.parse(text, formatter);
+    }
+    
+    @Override
+    public LocalTime convertTo(final TemporalAccessor temporal) {
+        return temporal.query(TemporalQueries.localTime());
+    }
+    
+    @Override
+    public boolean isAfter(final LocalTime temporal1, final LocalTime temporal2, final int stepAmount) {
+        return temporal1.isAfter(temporal2);
+    }
+    
+    @Override
+    public LocalTime add(final LocalTime temporal, final long stepAmount, final TemporalUnit unit) {
+        return temporal.plus(stepAmount, unit);
+    }
+}
diff --git a/features/sharding/core/src/main/java/org/apache/shardingsphere/sharding/algorithm/sharding/datetime/temporal/type/MonthTemporalHandler.java b/features/sharding/core/src/main/java/org/apache/shardingsphere/sharding/algorithm/sharding/datetime/temporal/type/MonthTemporalHandler.java
new file mode 100644
index 00000000000..b05e5ed524c
--- /dev/null
+++ b/features/sharding/core/src/main/java/org/apache/shardingsphere/sharding/algorithm/sharding/datetime/temporal/type/MonthTemporalHandler.java
@@ -0,0 +1,58 @@
+/*
+ * 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 org.apache.shardingsphere.sharding.algorithm.sharding.datetime.temporal.type;
+
+import org.apache.shardingsphere.sharding.algorithm.sharding.datetime.temporal.TemporalHandler;
+
+import java.time.Month;
+import java.time.format.DateTimeFormatter;
+import java.time.temporal.TemporalAccessor;
+import java.time.temporal.TemporalUnit;
+
+/**
+ * Month temporal handler.
+ */
+public final class MonthTemporalHandler implements TemporalHandler<Month> {
+    
+    /*
+     * After the sharding key is formatted as a {@link String}, if the length of the {@link String} is less than `datetime-pattern`, it usually means there is a problem with the sharding key.
+     *
+     * @param endpoint A class carrying time information with an unknown class name.
+     *
+     * @return {@link java.time.Month}
+     */
+    @Override
+    public Month parse(final CharSequence text, final DateTimeFormatter formatter) {
+        return Month.of(Integer.parseInt(text.toString()));
+    }
+    
+    @Override
+    public Month convertTo(final TemporalAccessor temporal) {
+        return Month.from(temporal);
+    }
+    
+    @Override
+    public boolean isAfter(final Month temporal1, final Month temporal2, final int stepAmount) {
+        return temporal1.getValue() > temporal2.getValue() || (temporal1.getValue() + stepAmount) > Month.DECEMBER.getValue();
+    }
+    
+    @Override
+    public Month add(final Month temporal, final long stepAmount, final TemporalUnit unit) {
+        return temporal.plus(stepAmount);
+    }
+}
diff --git a/features/sharding/core/src/main/java/org/apache/shardingsphere/sharding/algorithm/sharding/datetime/temporal/type/YearMonthTemporalHandler.java b/features/sharding/core/src/main/java/org/apache/shardingsphere/sharding/algorithm/sharding/datetime/temporal/type/YearMonthTemporalHandler.java
new file mode 100644
index 00000000000..04f750d9a5d
--- /dev/null
+++ b/features/sharding/core/src/main/java/org/apache/shardingsphere/sharding/algorithm/sharding/datetime/temporal/type/YearMonthTemporalHandler.java
@@ -0,0 +1,51 @@
+/*
+ * 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 org.apache.shardingsphere.sharding.algorithm.sharding.datetime.temporal.type;
+
+import org.apache.shardingsphere.sharding.algorithm.sharding.datetime.temporal.TemporalHandler;
+
+import java.time.YearMonth;
+import java.time.format.DateTimeFormatter;
+import java.time.temporal.TemporalAccessor;
+import java.time.temporal.TemporalUnit;
+
+/**
+ * Year month temporal handler.
+ */
+public final class YearMonthTemporalHandler implements TemporalHandler<YearMonth> {
+    
+    @Override
+    public YearMonth parse(final CharSequence text, final DateTimeFormatter formatter) {
+        return YearMonth.parse(text, formatter);
+    }
+    
+    @Override
+    public YearMonth convertTo(final TemporalAccessor temporal) {
+        return temporal.query(YearMonth::from);
+    }
+    
+    @Override
+    public boolean isAfter(final YearMonth temporal1, final YearMonth temporal2, final int stepAmount) {
+        return temporal1.isAfter(temporal2);
+    }
+    
+    @Override
+    public YearMonth add(final YearMonth temporal, final long stepAmount, final TemporalUnit unit) {
+        return temporal.plus(stepAmount, unit);
+    }
+}
diff --git a/features/sharding/core/src/main/java/org/apache/shardingsphere/sharding/algorithm/sharding/datetime/temporal/type/YearTemporalHandler.java b/features/sharding/core/src/main/java/org/apache/shardingsphere/sharding/algorithm/sharding/datetime/temporal/type/YearTemporalHandler.java
new file mode 100644
index 00000000000..b8116388db0
--- /dev/null
+++ b/features/sharding/core/src/main/java/org/apache/shardingsphere/sharding/algorithm/sharding/datetime/temporal/type/YearTemporalHandler.java
@@ -0,0 +1,51 @@
+/*
+ * 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 org.apache.shardingsphere.sharding.algorithm.sharding.datetime.temporal.type;
+
+import org.apache.shardingsphere.sharding.algorithm.sharding.datetime.temporal.TemporalHandler;
+
+import java.time.Year;
+import java.time.format.DateTimeFormatter;
+import java.time.temporal.TemporalAccessor;
+import java.time.temporal.TemporalUnit;
+
+/**
+ * Year temporal handler.
+ */
+public final class YearTemporalHandler implements TemporalHandler<Year> {
+    
+    @Override
+    public Year parse(final CharSequence text, final DateTimeFormatter formatter) {
+        return Year.parse(text, formatter);
+    }
+    
+    @Override
+    public Year convertTo(final TemporalAccessor temporal) {
+        return Year.from(temporal);
+    }
+    
+    @Override
+    public boolean isAfter(final Year temporal1, final Year temporal2, final int stepAmount) {
+        return temporal1.isAfter(temporal2);
+    }
+    
+    @Override
+    public Year add(final Year temporal, final long stepAmount, final TemporalUnit unit) {
+        return temporal.plus(stepAmount, unit);
+    }
+}
diff --git a/features/sharding/core/src/test/java/org/apache/shardingsphere/sharding/algorithm/sharding/datetime/IntervalShardingAlgorithmTest.java b/features/sharding/core/src/test/java/org/apache/shardingsphere/sharding/algorithm/sharding/datetime/IntervalShardingAlgorithmTest.java
index 64c2cd8575e..169ba0f807d 100644
--- a/features/sharding/core/src/test/java/org/apache/shardingsphere/sharding/algorithm/sharding/datetime/IntervalShardingAlgorithmTest.java
+++ b/features/sharding/core/src/test/java/org/apache/shardingsphere/sharding/algorithm/sharding/datetime/IntervalShardingAlgorithmTest.java
@@ -130,8 +130,7 @@ class IntervalShardingAlgorithmTest {
     
     @Test
     void assertRangeDoShardingByQuarter() {
-        Collection<String> actual = shardingAlgorithmByQuarter.doSharding(availableTablesForQuarterDataSources,
-                createShardingValue("2019-10-15 10:59:08", "2020-04-08 10:59:08"));
+        Collection<String> actual = shardingAlgorithmByQuarter.doSharding(availableTablesForQuarterDataSources, createShardingValue("2019-10-15 10:59:08", "2020-04-08 10:59:08"));
         assertThat(actual.size(), is(3));
     }