diff --git a/components/fluent-builtin/src/main/java/io/fluent/builtin/crypto/AesUtil.java b/components/fluent-builtin/src/main/java/io/fluent/builtin/crypto/AesUtil.java
new file mode 100644
index 0000000..d691cc1
--- /dev/null
+++ b/components/fluent-builtin/src/main/java/io/fluent/builtin/crypto/AesUtil.java
@@ -0,0 +1,124 @@
+package io.fluent.builtin.crypto;
+
+
+import io.fluent.builtin.exception.EncryptException;
+
+import javax.crypto.Cipher;
+import javax.crypto.spec.IvParameterSpec;
+import javax.crypto.spec.SecretKeySpec;
+import java.nio.charset.StandardCharsets;
+import java.util.Base64;
+
+/**
+ * AES-128-CBC 算法
+ * iv 默认取key
+ */
+public class AesUtil {
+
+ /**
+ * AES
+ */
+ static String ALGORITHM = "AES";
+ /**
+ * AES 算法
+ */
+ static String AES_CBC_CIPHER = "AES/CBC/PKCS5Padding";
+ /**
+ * 偏移量
+ */
+ private static final int OFFSET = 16;
+
+
+ /**
+ * 加密
+ *
+ * @param data 需要加密的内容
+ * @param key 加密密码
+ * @param iv 加密密码
+ * @return
+ */
+ public static byte[] encrypt(byte[] data, byte[] key, byte[] iv) {
+ try {
+ if (key.length < OFFSET) {
+ byte[] tmp = new byte[OFFSET];
+ System.arraycopy(key, 0, tmp, 0, key.length);
+ key = tmp;
+ }
+ if (iv.length < 16) {
+ byte[] tmp = new byte[16];
+ System.arraycopy(iv, 0, tmp, 0, iv.length);
+ iv = tmp;
+ }
+ SecretKeySpec secretKey = new SecretKeySpec(key, ALGORITHM);
+ IvParameterSpec ivParameterSpec = new IvParameterSpec(iv, 0, OFFSET);
+ Cipher cipher = Cipher.getInstance(AES_CBC_CIPHER);
+ cipher.init(Cipher.ENCRYPT_MODE, secretKey, ivParameterSpec);
+ return cipher.doFinal(data);
+ } catch (Exception e) {
+ throw new EncryptException("aes encrypt error:" + e.getMessage(), e);
+ }
+ }
+
+ /**
+ * 解密
+ *
+ * @param data 待解密内容
+ * @param key 解密密钥
+ * @return
+ */
+ public static byte[] decrypt(byte[] data, byte[] key, byte[] iv) {
+ try {
+ if (key.length < 16) {
+ byte[] tmp = new byte[16];
+ System.arraycopy(key, 0, tmp, 0, key.length);
+ key = tmp;
+ }
+ if (iv.length < 16) {
+ byte[] tmp = new byte[16];
+ System.arraycopy(iv, 0, tmp, 0, iv.length);
+ iv = tmp;
+ }
+ SecretKeySpec secretKey = new SecretKeySpec(key, ALGORITHM);
+ IvParameterSpec ivParameterSpec = new IvParameterSpec(iv, 0, OFFSET);
+ Cipher cipher = Cipher.getInstance(AES_CBC_CIPHER);
+ cipher.init(Cipher.DECRYPT_MODE, secretKey, ivParameterSpec);
+ return cipher.doFinal(data);
+ } catch (Exception e) {
+ throw new EncryptException("ase decrypt error", e);
+ }
+ }
+
+ /**
+ * 加密
+ *
+ * * 定义 aes 加密的key
+ * * 密钥 必须是16位, 自定义,
+ * * 如果不是16位, 则会出现InvalidKeyException: Illegal key size
+ * * 解决方案有两种:
+ * * 需要安装Java Cryptography Extension (JCE) Unlimited Strength Jurisdiction Policy Files(可以在Oracle下载).
+ * * .设置设置key的长度为16个字母和数字的字符窜(128 Bit/8=16字符)就不报错了。
+ *
+ * @param data 需要加密的内容
+ * @param key 加密密码
+ * @return
+ */
+ public static String encrypt(String data, String key) {
+ byte[] keyBytes = key.getBytes(StandardCharsets.UTF_8);
+ byte[] valueByte = encrypt(data.getBytes(StandardCharsets.UTF_8), keyBytes, keyBytes);
+ return Base64.getEncoder().encodeToString(valueByte);
+ }
+
+ /**
+ * 解密
+ *
+ * @param data 待解密内容 base64 字符串
+ * @param key 解密密钥
+ * @return
+ */
+ public static String decrypt(String data, String key) {
+ byte[] originalData = Base64.getDecoder().decode(data.getBytes());
+ byte[] keyBytes = key.getBytes(StandardCharsets.UTF_8);
+ byte[] valueByte = decrypt(originalData, keyBytes, keyBytes);
+ return new String(valueByte);
+ }
+}
diff --git a/components/fluent-builtin/src/main/java/io/fluent/builtin/crypto/DesUtil.java b/components/fluent-builtin/src/main/java/io/fluent/builtin/crypto/DesUtil.java
new file mode 100644
index 0000000..7b1c3ec
--- /dev/null
+++ b/components/fluent-builtin/src/main/java/io/fluent/builtin/crypto/DesUtil.java
@@ -0,0 +1,88 @@
+package io.fluent.builtin.crypto;
+
+
+import io.fluent.builtin.exception.EncryptException;
+
+import javax.crypto.Cipher;
+import javax.crypto.spec.SecretKeySpec;
+import java.nio.charset.StandardCharsets;
+import java.util.Base64;
+
+/**
+ * des算法加解密
+ * DES/ECB/PKCS5Padding
+ *
+ */
+public class DesUtil {
+
+ /**
+ * AES
+ */
+ static final String ALGORITHM = "DES";
+ /**
+ * AES 算法
+ */
+ static final String DES_ECB_CIPHER = "DES/ECB/PKCS5Padding";
+
+ /**
+ * 加密
+ *
+ * @param data 需要加密的内容
+ * @param key 加密密码
+ * @return
+ */
+ public static byte[] encrypt(byte[] data, byte[] key) {
+ try {
+ //生成KEY
+ SecretKeySpec secretKey = new SecretKeySpec(key, ALGORITHM);
+ Cipher cipher = Cipher.getInstance(DES_ECB_CIPHER);
+ cipher.init(Cipher.ENCRYPT_MODE, secretKey);
+ return cipher.doFinal(data);
+ } catch (Exception e) {
+ throw new EncryptException("encrypt error", e);
+ }
+ }
+
+ /**
+ * 解密
+ *
+ * @param data 待解密内容
+ * @param key 解密密钥
+ * @return
+ */
+ public static byte[] decrypt(byte[] data, byte[] key) {
+ try {
+ SecretKeySpec secretKey = new SecretKeySpec(key, ALGORITHM);
+ Cipher cipher = Cipher.getInstance(DES_ECB_CIPHER);
+ cipher.init(Cipher.DECRYPT_MODE, secretKey);
+ return cipher.doFinal(data);
+ } catch (Exception e) {
+ throw new EncryptException("decrypt error", e);
+ }
+ }
+
+ /**
+ * 加密
+ *
+ * @param data 需要加密的内容
+ * @param key 加密密码
+ * @return
+ */
+ public static String encrypt(String data, String key) {
+ byte[] valueByte = encrypt(data.getBytes(StandardCharsets.UTF_8), key.getBytes(StandardCharsets.UTF_8));
+ return Base64.getEncoder().encodeToString(valueByte);
+ }
+
+ /**
+ * 解密
+ *
+ * @param data 待解密内容 base64 字符串
+ * @param key 解密密钥
+ * @return
+ */
+ public static String decrypt(String data, String key) {
+ byte[] originalData = Base64.getDecoder().decode(data.getBytes());
+ byte[] valueByte = decrypt(originalData, key.getBytes(StandardCharsets.UTF_8));
+ return new String(valueByte);
+ }
+}
diff --git a/components/fluent-builtin/src/main/java/io/fluent/builtin/exception/EncryptException.java b/components/fluent-builtin/src/main/java/io/fluent/builtin/exception/EncryptException.java
new file mode 100644
index 0000000..6bcb529
--- /dev/null
+++ b/components/fluent-builtin/src/main/java/io/fluent/builtin/exception/EncryptException.java
@@ -0,0 +1,9 @@
+package io.fluent.builtin.exception;
+
+public class EncryptException extends SystemException {
+
+ public EncryptException(String message, Throwable throwable) {
+ super(message, throwable);
+ }
+
+}
diff --git a/components/fluent-builtin/src/main/java/io/fluent/builtin/exception/SystemException.java b/components/fluent-builtin/src/main/java/io/fluent/builtin/exception/SystemException.java
new file mode 100644
index 0000000..d117ae8
--- /dev/null
+++ b/components/fluent-builtin/src/main/java/io/fluent/builtin/exception/SystemException.java
@@ -0,0 +1,13 @@
+package io.fluent.builtin.exception;
+
+public class SystemException extends WrapMessageException {
+ private static final long serialVersionUID = 1L;
+
+ public SystemException(String message) {
+ super(message);
+ }
+
+ public SystemException(String message, Throwable cause) {
+ super(message, cause);
+ }
+}
diff --git a/components/fluent-builtin/src/main/java/io/fluent/builtin/exception/WrapMessageException.java b/components/fluent-builtin/src/main/java/io/fluent/builtin/exception/WrapMessageException.java
new file mode 100644
index 0000000..40ed0e3
--- /dev/null
+++ b/components/fluent-builtin/src/main/java/io/fluent/builtin/exception/WrapMessageException.java
@@ -0,0 +1,19 @@
+package io.fluent.builtin.exception;
+
+/**
+ * 只包装了 错误信息 的 {@link RuntimeException}.
+ * 用于 {@link com.sprainkle.spring.cloud.advance.common.core.exception.assertion.Assert} 中用于包装自定义异常信息
+ *
+
+ */
+public class WrapMessageException extends RuntimeException {
+
+ public WrapMessageException(String message) {
+ super(message);
+ }
+
+ public WrapMessageException(String message, Throwable cause) {
+ super(message, cause);
+ }
+
+}
diff --git a/components/fluent-builtin/src/main/java/io/fluent/builtin/meta/TargetType.java b/components/fluent-builtin/src/main/java/io/fluent/builtin/meta/TargetType.java
new file mode 100644
index 0000000..3d4ad96
--- /dev/null
+++ b/components/fluent-builtin/src/main/java/io/fluent/builtin/meta/TargetType.java
@@ -0,0 +1,32 @@
+package io.fluent.builtin.meta;
+
+import java.lang.reflect.ParameterizedType;
+import java.lang.reflect.Type;
+
+public class TargetType {
+
+ public Type getType() {
+
+ Type t = getClass().getGenericSuperclass();
+ if (!(t instanceof ParameterizedType)) {
+ throw new IllegalStateException("Incorrect use of TypeToken: " + t);
+ }
+ ParameterizedType pt = (ParameterizedType) t;
+ Type[] typeArgs = pt.getActualTypeArguments();
+ if (typeArgs.length > 0) {
+ return typeArgs[0];
+ }
+ throw new IllegalStateException("Incorrect use of TypeToken: " + t);
+ }
+
+ @SuppressWarnings("unchecked")
+ public Class getClassType() {
+
+ Type type = getType();
+ if (type instanceof ParameterizedType) {
+ return (Class) ((ParameterizedType) type).getRawType();
+ } else {
+ return (Class) type;
+ }
+ }
+}
diff --git a/components/fluent-builtin/src/main/java/io/fluent/builtin/time/DateFormatterPattern.java b/components/fluent-builtin/src/main/java/io/fluent/builtin/time/DateFormatterPattern.java
new file mode 100644
index 0000000..33fd071
--- /dev/null
+++ b/components/fluent-builtin/src/main/java/io/fluent/builtin/time/DateFormatterPattern.java
@@ -0,0 +1,156 @@
+package io.fluent.builtin.time;
+
+import lombok.AccessLevel;
+import lombok.NoArgsConstructor;
+
+import java.time.format.DateTimeFormatter;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.regex.Pattern;
+
+/**
+ * 日期格式化类,提供常用的日期格式化对象
+ *
+ */
+@NoArgsConstructor(access = AccessLevel.PRIVATE)
+public class DateFormatterPattern {
+
+
+ /**
+ * 标准日期时间正则,每个字段支持单个数字或2个数字,包括:
+ *
+ * yyyy-MM-dd HH:mm:ss.SSS
+ * yyyy-MM-dd HH:mm:ss
+ * yyyy-MM-dd HH:mm
+ * yyyy-MM-dd
+ *
+ *
+ * @since 5.3.6
+ */
+ public static final Pattern REGEX_NORM = Pattern.compile("\\d{4}-\\d{1,2}-\\d{1,2}(\\s\\d{1,2}:\\d{1,2}(:\\d{1,2})?)?(.\\d{1,3})?");
+
+ //-------------------------------------------------------------------------------------------------------------------------------- Normal
+ /**
+ * 年月格式:yyyy-MM
+ */
+ public static final String NORM_MONTH_PATTERN = "yyyy-MM";
+ /**
+ * 简单年月格式:yyyyMM
+ */
+ public static final String SIMPLE_MONTH_PATTERN = "yyyyMM";
+ /**
+ * 标准日期格式:yyyy-MM-dd
+ */
+ public static final String NORM_DATE_PATTERN = "yyyy-MM-dd";
+ /**
+ * 标准时间格式:HH:mm:ss
+ */
+ public static final String NORM_TIME_PATTERN = "HH:mm:ss";
+ /**
+ * 标准日期时间格式,精确到分:yyyy-MM-dd HH:mm
+ */
+ public static final String NORM_DATETIME_MINUTE_PATTERN = "yyyy-MM-dd HH:mm";
+ /**
+ * 标准日期时间格式,精确到秒:yyyy-MM-dd HH:mm:ss
+ */
+ public static final String NORM_DATETIME_PATTERN = "yyyy-MM-dd HH:mm:ss";
+ /**
+ * 准日期时间格式,精确到毫秒:yyyy-MM-dd HH:mm:ss.SSS
+ */
+ public static final String NORM_DATETIME_MS_PATTERN = "yyyy-MM-dd HH:mm:ss.SSS";
+ /**
+ * ISO8601日期时间格式,精确到毫秒:yyyy-MM-dd HH:mm:ss,SSS
+ */
+ public static final String ISO8601_PATTERN = "yyyy-MM-dd HH:mm:ss,SSS";
+ /**
+ * 标准日期格式:yyyy年MM月dd日
+ */
+ public static final String CHINESE_DATE_PATTERN = "yyyy年MM月dd日";
+ /**
+ * 标准日期格式:yyyy年MM月dd日 HH时mm分ss秒
+ */
+ public static final String CHINESE_DATE_TIME_PATTERN = "yyyy年MM月dd日HH时mm分ss秒";
+ /**
+ * 标准日期格式:yyyyMMdd
+ */
+ public static final String PURE_DATE_PATTERN = "yyyyMMdd";
+ /**
+ * 标准日期格式:HHmmss
+ */
+ public static final String PURE_TIME_PATTERN = "HHmmss";
+ /**
+ * HTTP头中日期时间格式:EEE, dd MMM yyyy HH:mm:ss z
+ */
+ public static final String HTTP_DATETIME_PATTERN = "EEE, dd MMM yyyy HH:mm:ss z";
+ /**
+ * JDK中日期时间格式:EEE MMM dd HH:mm:ss zzz yyyy
+ */
+ public static final String JDK_DATETIME_PATTERN = "EEE MMM dd HH:mm:ss zzz yyyy";
+ /**
+ * UTC时间:yyyy-MM-dd'T'HH:mm:ss
+ */
+ public static final String UTC_SIMPLE_PATTERN = "yyyy-MM-dd'T'HH:mm:ss";
+ /**
+ * UTC时间:yyyy-MM-dd'T'HH:mm:ss.SSS
+ */
+ public static final String UTC_SIMPLE_MS_PATTERN = "yyyy-MM-dd'T'HH:mm:ss.SSS";
+ /**
+ * UTC时间:yyyy-MM-dd'T'HH:mm:ss'Z'
+ */
+ public static final String UTC_PATTERN = "yyyy-MM-dd'T'HH:mm:ss'Z'";
+ /**
+ * UTC时间:yyyy-MM-dd'T'HH:mm:ssZ
+ */
+ public static final String UTC_WITH_ZONE_OFFSET_PATTERN = "yyyy-MM-dd'T'HH:mm:ssZ";
+ /**
+ * UTC时间:yyyy-MM-dd'T'HH:mm:ssXXX
+ */
+ public static final String UTC_WITH_XXX_OFFSET_PATTERN = "yyyy-MM-dd'T'HH:mm:ssXXX";
+ /**
+ * UTC时间:yyyy-MM-dd'T'HH:mm:ss.SSS'Z'
+ */
+ public static final String UTC_MS_PATTERN = "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'";
+
+ //-------------------------------------------------------------------------------------------------------------------------------- Pure
+ /**
+ * UTC时间:yyyy-MM-dd'T'HH:mm:ssZ
+ */
+ public static final String UTC_MS_WITH_ZONE_OFFSET_PATTERN = "yyyy-MM-dd'T'HH:mm:ss.SSSZ";
+ /**
+ * UTC时间:yyyy-MM-dd'T'HH:mm:ss.SSSXXX
+ */
+ public static final String UTC_MS_WITH_XXX_OFFSET_PATTERN = "yyyy-MM-dd'T'HH:mm:ss.SSSXXX";
+ private final static Map DATE_FORMATTER_PATTERN_MAP = new ConcurrentHashMap<>(64);
+ public static final DateTimeFormatter NORM_MONTH_FORMATTER = createFormatter(NORM_MONTH_PATTERN);
+
+
+ //-------------------------------------------------------------------------------------------------------------------------------- Others
+ public static final DateTimeFormatter SIMPLE_MONTH_FORMATTER = createFormatter(SIMPLE_MONTH_PATTERN);
+ public static final DateTimeFormatter NORM_DATE_FORMATTER = createFormatter(NORM_DATE_PATTERN);
+ public static final DateTimeFormatter NORM_TIME_FORMATTER = createFormatter(NORM_TIME_PATTERN);
+ public static final DateTimeFormatter NORM_DATETIME_MINUTE_FORMATTER = createFormatter(NORM_DATETIME_MINUTE_PATTERN);
+ public static final DateTimeFormatter NORM_DATETIME_FORMATTER = createFormatter(NORM_DATETIME_PATTERN);
+ public static final DateTimeFormatter NORM_DATETIME_MS_FORMATTER = createFormatter(NORM_DATETIME_MS_PATTERN);
+ public static final DateTimeFormatter ISO8601_FORMATTER = createFormatter(ISO8601_PATTERN);
+ public static final DateTimeFormatter CHINESE_DATE_FORMATTER = createFormatter(ISO8601_PATTERN);
+ public static final DateTimeFormatter CHINESE_DATE_TIME_FORMATTER = createFormatter(CHINESE_DATE_TIME_PATTERN);
+ public static final DateTimeFormatter PURE_DATE_FORMATTER = createFormatter(PURE_DATE_PATTERN);
+ public static final DateTimeFormatter PURE_TIME_FORMATTER = createFormatter(PURE_TIME_PATTERN);
+
+ /**
+ * 创建并为 DateTimeFormatter 赋予默认时区和位置信息,默认值为系统默认值。
+ * Params: pattern – 日期格式
+ * Returns: DateTimeFormatter
+ *
+ * @param pattern
+ * @return
+ */
+ private static DateTimeFormatter createFormatter(String pattern) {
+ return getFormatter(pattern);
+ }
+
+ public static DateTimeFormatter getFormatter(String pattern) {
+ return DATE_FORMATTER_PATTERN_MAP.computeIfAbsent(pattern, key -> DateTimeFormatter.ofPattern(pattern));
+
+ }
+}
diff --git a/components/fluent-builtin/src/main/java/io/fluent/builtin/time/DateParseUtil.java b/components/fluent-builtin/src/main/java/io/fluent/builtin/time/DateParseUtil.java
new file mode 100644
index 0000000..bb21613
--- /dev/null
+++ b/components/fluent-builtin/src/main/java/io/fluent/builtin/time/DateParseUtil.java
@@ -0,0 +1,135 @@
+package io.fluent.builtin.time;
+
+
+import io.fluent.builtin.StringUtils;
+
+import java.time.LocalDateTime;
+import java.time.OffsetTime;
+import java.time.ZoneOffset;
+import java.time.format.DateTimeFormatter;
+
+public class DateParseUtil {
+
+ public static final ZoneOffset DEFAULT_ZONE_OFFSET = OffsetTime.now().getOffset();
+
+ /**
+ * 解析 yyyy-MM-dd HH:mm:ss
+ *
+ * @param dateStr
+ * @return
+ */
+ public static LocalDateTime parse(String dateStr) {
+ return LocalDateTime.parse(dateStr, DateFormatterPattern.NORM_DATETIME_FORMATTER);
+ }
+
+ /**
+ * 解析 yyyy-MM-dd HH:mm:ss 格式成秒
+ *
+ * @param dateStr
+ * @return
+ */
+ public static Long toEpochSecond(String dateStr, DateTimeFormatter dateTimeFormatter, String offset) {
+
+ ZoneOffset zoneOffset = StringUtils.isEmpty(offset) ? DEFAULT_ZONE_OFFSET : ZoneOffset.of(offset);
+ dateTimeFormatter = dateTimeFormatter == null ? DateFormatterPattern.NORM_DATETIME_FORMATTER : dateTimeFormatter;
+ return LocalDateTime.parse(dateStr, dateTimeFormatter).toEpochSecond(zoneOffset);
+ }
+
+ /**
+ * 解析 yyyy-MM-dd HH:mm:ss 格式成秒
+ *
+ * @param dateStr
+ * @return
+ */
+ public static Long toEpochSecond(String dateStr, String offset) {
+
+
+ ZoneOffset zoneOffset = StringUtils.isEmpty(offset) ? DEFAULT_ZONE_OFFSET : ZoneOffset.of(offset);
+ return LocalDateTime.parse(dateStr, DateFormatterPattern.NORM_DATETIME_FORMATTER).toEpochSecond(zoneOffset);
+ }
+
+ /**
+ * 解析 yyyy-MM-dd HH:mm:ss 格式成秒
+ *
+ * @param dateStr
+ * @return
+ */
+ public static Long toEpochSecond(String dateStr) {
+
+ return LocalDateTime.parse(dateStr, DateFormatterPattern.NORM_DATETIME_FORMATTER).toEpochSecond(DEFAULT_ZONE_OFFSET);
+ }
+
+
+ /**
+ * 解析 yyyy-MM-dd HH:mm:ss 格式成毫秒
+ *
+ * @param dateStr 时间
+ * @return
+ */
+ public static Long toEpochMilli(String dateStr, DateTimeFormatter dateTimeFormatter, String offset) {
+
+ ZoneOffset zoneOffset = StringUtils.isEmpty(offset) ? DEFAULT_ZONE_OFFSET : ZoneOffset.of(offset);
+ dateTimeFormatter = dateTimeFormatter == null ? DateFormatterPattern.NORM_DATETIME_FORMATTER : dateTimeFormatter;
+ return LocalDateTime.parse(dateStr, dateTimeFormatter).toInstant(zoneOffset).toEpochMilli();
+ }
+
+ /**
+ * 解析 yyyy-MM-dd HH:mm:ss 格式成秒
+ *
+ * @param dateStr
+ * @return
+ */
+ public static Long toEpochMilli(String dateStr, String offset) {
+
+
+ ZoneOffset zoneOffset = StringUtils.isEmpty(offset) ? DEFAULT_ZONE_OFFSET : ZoneOffset.of(offset);
+ return LocalDateTime.parse(dateStr, DateFormatterPattern.NORM_DATETIME_FORMATTER).toInstant(zoneOffset).toEpochMilli();
+ }
+
+ /**
+ * 解析 yyyy-MM-dd HH:mm:ss 格式成秒
+ *
+ * @param dateStr
+ * @return
+ */
+ public static Long toEpochMilli(String dateStr) {
+
+ return LocalDateTime.parse(dateStr, DateFormatterPattern.NORM_DATETIME_FORMATTER).toInstant(DEFAULT_ZONE_OFFSET).toEpochMilli();
+ }
+
+ /**
+ * LocalDateTime 解释成秒
+ *
+ * @param localDateTime 本地日期
+ * @param offset 时区
+ * @return
+ */
+ public static Long toEpochSecond(LocalDateTime localDateTime, String offset) {
+
+ ZoneOffset zoneOffset = StringUtils.isEmpty(offset) ? DEFAULT_ZONE_OFFSET : ZoneOffset.of(offset);
+ return localDateTime.toEpochSecond(zoneOffset);
+ }
+
+ public static Long toEpochSecond(LocalDateTime localDateTime) {
+
+ return localDateTime.toEpochSecond(DEFAULT_ZONE_OFFSET);
+ }
+
+ /**
+ * LocalDateTime 解释毫秒
+ *
+ * @param localDateTime 本地日期
+ * @param offset 时区
+ * @return
+ */
+ public static Long toEpochMilli(LocalDateTime localDateTime, String offset) {
+
+ ZoneOffset zoneOffset = StringUtils.isEmpty(offset) ? DEFAULT_ZONE_OFFSET : ZoneOffset.of(offset);
+ return localDateTime.toInstant(zoneOffset).toEpochMilli();
+ }
+
+ public static Long toEpochMilli(LocalDateTime localDateTime) {
+
+ return localDateTime.toInstant(DEFAULT_ZONE_OFFSET).toEpochMilli();
+ }
+}
diff --git a/components/fluent-builtin/src/main/java/io/fluent/builtin/time/TimeDifferUtil.java b/components/fluent-builtin/src/main/java/io/fluent/builtin/time/TimeDifferUtil.java
new file mode 100644
index 0000000..19290e6
--- /dev/null
+++ b/components/fluent-builtin/src/main/java/io/fluent/builtin/time/TimeDifferUtil.java
@@ -0,0 +1,81 @@
+package io.fluent.builtin.time;
+
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+import java.time.ZoneOffset;
+
+public class TimeDifferUtil {
+
+ /**
+ * 相差几天
+ *
+ * @param beginDate beginTime
+ * @param endDate endDate
+ * @return 相差几天
+ */
+ public static long day(LocalDate beginDate, LocalDate endDate) {
+
+ return endDate.toEpochDay() - beginDate.toEpochDay();
+ }
+
+ /**
+ * 相差几年
+ *
+ * @param beginDate beginTime
+ * @param endDate endDate
+ * @return 相差几天
+ */
+ public static double year(LocalDate beginDate, LocalDate endDate) {
+
+ return (endDate.toEpochDay() - beginDate.toEpochDay()) / 365.0;
+ }
+
+ /**
+ * 相差几天
+ *
+ * @param beginTime beginTime
+ * @param endTime endTime
+ * @return 相差几天
+ */
+ public static double day(LocalDateTime beginTime, LocalDateTime endTime) {
+
+
+ long beginSecond = beginTime.toEpochSecond(ZoneOffset.UTC);
+ long endSecond = endTime.toEpochSecond(ZoneOffset.UTC);
+ return (endSecond - beginSecond) / 60.0 / 60.0 / 24.0;
+ }
+
+
+ /**
+ * 相差几小时
+ */
+ public static double hour(LocalDateTime beginTime, LocalDateTime endTime) {
+
+
+ long beginSecond = beginTime.toEpochSecond(ZoneOffset.UTC);
+ long endSecond = endTime.toEpochSecond(ZoneOffset.UTC);
+ return (endSecond - beginSecond) / 60.0 / 60.0;
+ }
+
+ /**
+ * 相差几分钟
+ */
+ public static double minute(LocalDateTime beginTime, LocalDateTime endTime) {
+
+ long beginSecond = beginTime.toEpochSecond(ZoneOffset.UTC);
+ long endSecond = endTime.toEpochSecond(ZoneOffset.UTC);
+ return (endSecond - beginSecond) / 60.0;
+ }
+
+ /**
+ * 相差几秒
+ */
+ public static double second(LocalDateTime beginTime, LocalDateTime endTime) {
+
+ long beginSecond = beginTime.toEpochSecond(ZoneOffset.UTC);
+ long endSecond = endTime.toEpochSecond(ZoneOffset.UTC);
+ return (endSecond - beginSecond);
+ }
+
+
+}
diff --git a/components/fluent-loader/pom.xml b/components/fluent-loader/pom.xml
new file mode 100644
index 0000000..4f25fa6
--- /dev/null
+++ b/components/fluent-loader/pom.xml
@@ -0,0 +1,42 @@
+
+
+ 4.0.0
+
+ io.fluent
+ components
+ 1.0-SNAPSHOT
+
+
+ fluent-loader
+
+
+ UTF-8
+ 7.0.0
+
+
+
+ com.google.inject
+ guice
+ ${guice.version}
+
+
+ com.google.inject.extensions
+ guice-assistedinject
+ ${guice.version}
+
+
+
+ com.google.inject.extensions
+ guice-servlet
+ ${guice.version}
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/components/fluent-loader/src/main/java/io/fluent/loader/dep/DependencyAware.java b/components/fluent-loader/src/main/java/io/fluent/loader/dep/DependencyAware.java
new file mode 100644
index 0000000..2b19c90
--- /dev/null
+++ b/components/fluent-loader/src/main/java/io/fluent/loader/dep/DependencyAware.java
@@ -0,0 +1,21 @@
+package io.fluent.loader.dep;
+
+import java.util.Set;
+
+public interface DependencyAware {
+
+ /**
+ * Get key of the dependent object.
+ * @return
+ */
+ K getId();
+
+ /**
+ * Get set of keys of other dependency objects this dependency object directly depends on.
+ * @return
+ * Should not be null. In case of no dependencies, please return an empty collection
+ * instead of a null value.
+ */
+ Set getDependencies();
+
+}
diff --git a/components/fluent-loader/src/main/java/io/fluent/loader/package-info.java b/components/fluent-loader/src/main/java/io/fluent/loader/package-info.java
new file mode 100644
index 0000000..cd2878e
--- /dev/null
+++ b/components/fluent-loader/src/main/java/io/fluent/loader/package-info.java
@@ -0,0 +1 @@
+package io.fluent.loader;
\ No newline at end of file
diff --git a/components/fluent-spring/src/main/java/io/fluent/spring/config/SpringConfig.java b/components/fluent-spring/src/main/java/io/fluent/spring/config/SpringConfig.java
index a501263..ddcc2fc 100644
--- a/components/fluent-spring/src/main/java/io/fluent/spring/config/SpringConfig.java
+++ b/components/fluent-spring/src/main/java/io/fluent/spring/config/SpringConfig.java
@@ -5,7 +5,7 @@
public class SpringConfig {
- @Bean("fluentSpringUtils")
+ @Bean("springUtils")
public SpringUtils springUtils() {
return new SpringUtils();
}
diff --git a/components/fluent-spring/src/main/java/io/fluent/spring/util/SpringUtils.java b/components/fluent-spring/src/main/java/io/fluent/spring/util/SpringUtils.java
index 5ceb838..b53eded 100644
--- a/components/fluent-spring/src/main/java/io/fluent/spring/util/SpringUtils.java
+++ b/components/fluent-spring/src/main/java/io/fluent/spring/util/SpringUtils.java
@@ -19,7 +19,6 @@
/**
* spring工具类 方便在非spring管理环境中获取bean
*
- * @author andanyang
*/
public final class SpringUtils implements BeanFactoryPostProcessor, ApplicationContextAware {
diff --git a/components/fluent-spring/src/main/resources/META-INF/spring.factories b/components/fluent-spring/src/main/resources/META-INF/spring.factories
new file mode 100644
index 0000000..bff0efa
--- /dev/null
+++ b/components/fluent-spring/src/main/resources/META-INF/spring.factories
@@ -0,0 +1,2 @@
+org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
+ com.admin4j.spring.config.SpringConfig
diff --git a/components/pom.xml b/components/pom.xml
index 1a0bcb5..c09c7c5 100644
--- a/components/pom.xml
+++ b/components/pom.xml
@@ -26,6 +26,7 @@
fluent-datafactory
fluent-testlibs
fluent-spring
+ fluent-loader
diff --git a/references.yaml b/references.yaml
index 6d5750d..f987426 100644
--- a/references.yaml
+++ b/references.yaml
@@ -1,6 +1,5 @@
stacks:
- https://www.stackradar.co/
-
agent:
- https://www.agentcrew.co/
@@ -34,7 +33,7 @@ devops:
- https://gitee.com/ketr/jecloud
database-tools:
- - https://github.com/azimuttapp/azimutt.git
+ - https://github.com/azimuttapp/azimutt.git
qa-tools:
- https://gitee.com/cat2bug/cat2bug-platform.git
qa-ai-tools:
@@ -50,6 +49,7 @@ api-mgt:
- https://github.com/Kong/insomnia.git
- https://github.com/xyyxhcj/vpi.git
low-code:
+ - https://gitee.com/yabushan/low-code-data-center.git
- https://gitee.com/zj1983/zz.git
- https://gitee.com/y_project/RuoYi-Vue.git
- https://gitee.com/newcorenet/elcube-backend.git