Explorar o código

优化时间转换

zhou-hao %!s(int64=5) %!d(string=hai) anos
pai
achega
8a98971be4

+ 3 - 1
jetlinks-components/common-component/src/main/java/org/jetlinks/community/ValueObject.java

@@ -55,7 +55,9 @@ public interface ValueObject {
     }
 
     default Optional<Date> getDate(String name) {
-        return get(name, Date.class);
+        return get(name)
+            .map(String::valueOf)
+            .map(TimeUtils::parseDate);
     }
 
     default Date getDate(String name, Date defaultValue) {

+ 171 - 0
jetlinks-components/common-component/src/main/java/org/jetlinks/community/utils/DateMathParser.java

@@ -0,0 +1,171 @@
+/*
+ * Licensed to Elasticsearch under one or more contributor
+ * license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright
+ * ownership. Elasticsearch 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.jetlinks.community.utils;
+
+
+import lombok.SneakyThrows;
+import org.hswebframework.utils.time.DateFormatter;
+import org.springframework.util.StringUtils;
+
+import java.time.*;
+import java.time.temporal.TemporalAdjusters;
+import java.util.function.LongSupplier;
+
+
+public class DateMathParser {
+
+
+    @SneakyThrows
+    public static long parse(String text, LongSupplier now) {
+        long time;
+        String mathString;
+        if (text.startsWith("now()")) {
+            time = now.getAsLong();
+            mathString = text.substring("now()".length());
+        } else if (text.startsWith("now")) {
+            time = now.getAsLong();
+            mathString = text.substring("now".length());
+        } else {
+            int index = text.indexOf("||");
+            if (index == -1) {
+                return parseDateTime(text);
+            }
+            time = parseDateTime(text.substring(0, index));
+            mathString = text.substring(index + 2);
+        }
+
+        return parseMath(mathString, time);
+    }
+
+    private static long parseMath(final String mathString, final long time) {
+        ZonedDateTime dateTime = ZonedDateTime.ofInstant(Instant.ofEpochMilli(time), ZoneId.systemDefault());
+        for (int i = 0; i < mathString.length(); ) {
+            char c = mathString.charAt(i++);
+            final boolean round;
+            final int sign;
+            if (c == '/') {
+                round = true;
+                sign = 1;
+            } else {
+                round = false;
+                if (c == '+') {
+                    sign = 1;
+                } else if (c == '-') {
+                    sign = -1;
+                } else {
+                    throw new IllegalArgumentException("不支持的表达式:" + mathString);
+                }
+            }
+
+            if (i >= mathString.length()) {
+                throw new IllegalArgumentException("不支持的表达式:" + mathString);
+            }
+
+            final int num;
+            if (!Character.isDigit(mathString.charAt(i))) {
+                num = 1;
+            } else {
+                int numFrom = i;
+                while (i < mathString.length() && Character.isDigit(mathString.charAt(i))) {
+                    i++;
+                }
+                if (i >= mathString.length()) {
+                    throw new IllegalArgumentException("不支持的表达式:" + mathString);
+                }
+                num = Integer.parseInt(mathString.substring(numFrom, i));
+            }
+            if (round) {
+                if (num != 1) {
+                    throw new IllegalArgumentException("不支持的表达式:" + mathString);
+                }
+            }
+            char unit = mathString.charAt(i++);
+            switch (unit) {
+                case 'y':
+                    if (round) {
+                        dateTime = dateTime.withDayOfYear(1).with(LocalTime.MIN);
+                    } else {
+                        dateTime = dateTime.plusYears(sign * num);
+                    }
+
+                    break;
+                case 'M':
+                    if (round) {
+                        dateTime = dateTime.withDayOfMonth(1).with(LocalTime.MIN);
+                    } else {
+                        dateTime = dateTime.plusMonths(sign * num);
+                    }
+
+                    break;
+                case 'w':
+                    if (round) {
+                        dateTime = dateTime.with(TemporalAdjusters.previousOrSame(DayOfWeek.MONDAY)).with(LocalTime.MIN);
+                    } else {
+                        dateTime = dateTime.plusWeeks(sign * num);
+                    }
+
+                    break;
+                case 'd':
+                    if (round) {
+                        dateTime = dateTime.with(LocalTime.MIN);
+                    } else {
+                        dateTime = dateTime.plusDays(sign * num);
+                    }
+
+                    break;
+                case 'h':
+                case 'H':
+                    if (round) {
+                        dateTime = dateTime.withMinute(0).withSecond(0).withNano(0);
+                    } else {
+                        dateTime = dateTime.plusHours(sign * num);
+                    }
+
+                    break;
+                case 'm':
+                    if (round) {
+                        dateTime = dateTime.withSecond(0).withNano(0);
+                    } else {
+                        dateTime = dateTime.plusMinutes(sign * num);
+                    }
+
+                    break;
+                case 's':
+                    if (round) {
+                        dateTime = dateTime.withNano(0);
+                    } else {
+                        dateTime = dateTime.plusSeconds(sign * num);
+                    }
+
+                    break;
+                default:
+                    throw new IllegalArgumentException("不支持的表达式:" + mathString);
+            }
+        }
+        return dateTime.toInstant().toEpochMilli();
+    }
+
+    private static long parseDateTime(String value) {
+        if (StringUtils.isEmpty(value)) {
+            throw new IllegalArgumentException("cannot parse empty date");
+        }
+        return DateFormatter.fromString(value).getTime();
+    }
+}

+ 17 - 0
jetlinks-components/common-component/src/main/java/org/jetlinks/community/utils/TimeUtils.java

@@ -2,6 +2,7 @@ package org.jetlinks.community.utils;
 
 import java.math.BigDecimal;
 import java.time.Duration;
+import java.util.Date;
 
 public class TimeUtils {
 
@@ -50,4 +51,20 @@ public class TimeUtils {
         return duration;
     }
 
+    /**
+     * 将字符串格式化为时间,支持简单的数学运算
+     *
+     * <pre>
+     *     now+1d
+     *
+     *
+     * </pre>
+     *
+     * @param expr 时间表达式
+     * @return 时间
+     */
+    public static Date parseDate(String expr) {
+        return new Date(DateMathParser.parse(expr, System::currentTimeMillis));
+    }
+
 }