enumClass, Predicate super E> predicate, E defaultEnum) {
+ if (null == enumClass || null == predicate) {
return null;
}
return Arrays.stream(enumClass.getEnumConstants())
- .filter(predicate).findFirst().orElse(null);
+ .filter(predicate).findFirst().orElse(defaultEnum);
+ }
+
+ /**
+ * 通过 某字段对应值 获取 枚举,获取不到时为 {@code null}
+ *
+ * {@link LambdaUtil#getRealClass(Func1)}} 是相对耗时的
+ * 如果枚举值比较多,那么{@link EnumUtil#getBy(Func1, Object)} 方法
+ * 大部分时间都是被{@link LambdaUtil#getRealClass(Func1)}}所消耗的
+ *
+ * 如果可以在编码过程中可以提供对应的枚举类 该方法与枚举的{@code Enum.values()}方法是差不多的。
+ *
+ * @param enumClass 枚举类, 为{@code null}返回{@code null}
+ * @param condition 条件字段,为{@code null}返回{@code null}
+ * @param value 条件字段值
+ * @param 枚举类型
+ * @param 字段类型
+ * @return 对应枚举 ,获取不到时为 {@code null}
+ */
+ public static , C> E getBy(Class enumClass, Func1 condition, C value) {
+ if (null == condition) {
+ return null;
+ }
+ return getBy(enumClass, constant -> ObjUtil.equals(condition.callWithRuntimeException(constant), value));
+ }
+
+ /**
+ * 通过 某字段对应值 获取 枚举,获取不到时为 {@code defaultEnum}
+ *
+ * @param enumClass 枚举类, 为{@code null}返回{@code null}
+ * @param condition 条件字段,为{@code null}返回{@code null}
+ * @param value 条件字段值
+ * @param defaultEnum 获取不到时的默认枚举值
+ * @param 枚举类型
+ * @param 字段类型
+ * @return 对应枚举 ,获取不到时为 {@code defaultEnum}
+ */
+ public static , C> E getBy(Class enumClass, Func1 condition, C value, E defaultEnum) {
+ return ObjectUtil.defaultIfNull(getBy(enumClass, condition, value), defaultEnum);
}
/**
@@ -259,10 +310,7 @@ public class EnumUtil {
return null;
}
final Class implClass = LambdaUtil.getRealClass(condition);
- return Arrays.stream(implClass.getEnumConstants())
- .filter(constant -> ObjUtil.equals(condition.callWithRuntimeException(constant), value))
- .findAny()
- .orElse(null);
+ return getBy(implClass, condition, value);
}
/**
@@ -293,7 +341,7 @@ public class EnumUtil {
* @since 5.8.0
*/
public static , F, C> F getFieldBy(Func1 field, Function condition, C value) {
- if(null == field || null == condition){
+ if (null == field || null == condition) {
return null;
}
final Class implClass = LambdaUtil.getRealClass(field);
@@ -316,7 +364,7 @@ public class EnumUtil {
* @since 4.0.2
*/
public static > LinkedHashMap getEnumMap(final Class enumClass) {
- if(null == enumClass){
+ if (null == enumClass) {
return null;
}
final LinkedHashMap map = new LinkedHashMap<>();
@@ -335,7 +383,7 @@ public class EnumUtil {
* @return 枚举名对应指定字段值的Map
*/
public static Map getNameFieldMap(Class extends Enum>> clazz, String fieldName) {
- if(null == clazz || StrUtil.isBlank(fieldName)){
+ if (null == clazz || StrUtil.isBlank(fieldName)) {
return null;
}
final Enum>[] enums = clazz.getEnumConstants();
@@ -359,7 +407,7 @@ public class EnumUtil {
*/
public static > boolean contains(final Class enumClass, String val) {
final LinkedHashMap enumMap = getEnumMap(enumClass);
- if(CollUtil.isEmpty(enumMap)){
+ if (CollUtil.isEmpty(enumMap)) {
return false;
}
return enumMap.containsKey(val);
diff --git a/hutool-core/src/test/java/cn/hutool/core/date/DateBetweenTest.java b/hutool-core/src/test/java/cn/hutool/core/date/DateBetweenTest.java
index afcdda170..86e723b2b 100644
--- a/hutool-core/src/test/java/cn/hutool/core/date/DateBetweenTest.java
+++ b/hutool-core/src/test/java/cn/hutool/core/date/DateBetweenTest.java
@@ -1,12 +1,13 @@
package cn.hutool.core.date;
import cn.hutool.core.date.BetweenFormatter.Level;
-import static org.junit.jupiter.api.Assertions.*;
import org.junit.jupiter.api.Test;
import java.time.temporal.ChronoUnit;
import java.util.Date;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
public class DateBetweenTest {
@Test
@@ -36,6 +37,14 @@ public class DateBetweenTest {
assertEquals(18, betweenYear);
}
+ @Test
+ public void betweenYearTest3() {
+ Date start = DateUtil.parse("20170301");
+ Date end = DateUtil.parse("2024-02-29 14:56:18");
+ long betweenYear = new DateBetween(start, end).betweenYear(false);
+ assertEquals(6, betweenYear);
+ }
+
@Test
public void betweenMonthTest() {
Date start = DateUtil.parse("2017-02-01 12:23:46");
diff --git a/hutool-core/src/test/java/cn/hutool/core/date/DateUtilTest.java b/hutool-core/src/test/java/cn/hutool/core/date/DateUtilTest.java
index 3a535a7c9..d8cd91198 100755
--- a/hutool-core/src/test/java/cn/hutool/core/date/DateUtilTest.java
+++ b/hutool-core/src/test/java/cn/hutool/core/date/DateUtilTest.java
@@ -605,9 +605,9 @@ public class DateUtilTest {
}
@Test
- public void parseUTCTest() {
+ public void parseISO8601Test() {
String dateStr1 = "2018-09-13T05:34:31Z";
- DateTime dt = DateUtil.parseUTC(dateStr1);
+ DateTime dt = DateUtil.parseISO8601(dateStr1);
// parse方法支持UTC格式测试
final DateTime dt2 = DateUtil.parse(dateStr1);
@@ -622,12 +622,12 @@ public class DateUtilTest {
assertEquals("2018-09-13 13:34:31", dateStr);
dateStr1 = "2018-09-13T13:34:32+0800";
- dt = DateUtil.parseUTC(dateStr1);
+ dt = DateUtil.parseISO8601(dateStr1);
dateStr = dt.toString(TimeZone.getTimeZone("GMT+8:00"));
assertEquals("2018-09-13 13:34:32", dateStr);
dateStr1 = "2018-09-13T13:34:33+08:00";
- dt = DateUtil.parseUTC(dateStr1);
+ dt = DateUtil.parseISO8601(dateStr1);
dateStr = dt.toString(TimeZone.getTimeZone("GMT+8:00"));
assertEquals("2018-09-13 13:34:33", dateStr);
@@ -644,14 +644,14 @@ public class DateUtilTest {
assertEquals("2018-09-13 13:34:35", dateStr);
dateStr1 = "2018-09-13T13:34:36.999+0800";
- dt = DateUtil.parseUTC(dateStr1);
+ dt = DateUtil.parseISO8601(dateStr1);
final SimpleDateFormat simpleDateFormat = new SimpleDateFormat(DatePattern.NORM_DATETIME_MS_PATTERN);
simpleDateFormat.setTimeZone(TimeZone.getTimeZone("GMT+8:00"));
dateStr = dt.toString(simpleDateFormat);
assertEquals("2018-09-13 13:34:36.999", dateStr);
dateStr1 = "2018-09-13T13:34:37.999+08:00";
- dt = DateUtil.parseUTC(dateStr1);
+ dt = DateUtil.parseISO8601(dateStr1);
dateStr = dt.toString(simpleDateFormat);
assertEquals("2018-09-13 13:34:37.999", dateStr);
@@ -676,19 +676,19 @@ public class DateUtilTest {
}
@Test
- public void parseUTCTest2() {
+ public void parseUTCTest() {
// issue1503@Github
// 检查不同毫秒长度都可以正常匹配
String utcTime = "2021-03-30T12:56:51.3Z";
- DateTime parse = DateUtil.parseUTC(utcTime);
+ DateTime parse = DateUtil.parseISO8601(utcTime);
assertEquals("2021-03-30 12:56:51", parse.toString());
utcTime = "2021-03-30T12:56:51.34Z";
- parse = DateUtil.parseUTC(utcTime);
+ parse = DateUtil.parseISO8601(utcTime);
assertEquals("2021-03-30 12:56:51", parse.toString());
utcTime = "2021-03-30T12:56:51.345Z";
- parse = DateUtil.parseUTC(utcTime);
+ parse = DateUtil.parseISO8601(utcTime);
assertEquals("2021-03-30 12:56:51", parse.toString());
}
@@ -994,7 +994,7 @@ public class DateUtilTest {
@SuppressWarnings("ConstantConditions")
@Test
- public void parseISO8601Test() {
+ public void parseWithMilsTest() {
final String dt = "2020-06-03 12:32:12,333";
final DateTime parse = DateUtil.parse(dt);
assertEquals("2020-06-03 12:32:12", parse.toString());
diff --git a/hutool-core/src/test/java/cn/hutool/core/date/IssueIB8OFSTest.java b/hutool-core/src/test/java/cn/hutool/core/date/IssueIB8OFSTest.java
new file mode 100644
index 000000000..1d6921523
--- /dev/null
+++ b/hutool-core/src/test/java/cn/hutool/core/date/IssueIB8OFSTest.java
@@ -0,0 +1,25 @@
+package cn.hutool.core.date;
+
+import cn.hutool.core.lang.Console;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+
+import java.util.List;
+
+public class IssueIB8OFSTest {
+ @Test
+ void rangeTest() {
+ DateRange startRange = DateUtil.range(
+ DateUtil.parse("2017-01-01"),
+ DateUtil.parse("2017-01-31"), DateField.DAY_OF_YEAR);
+ DateRange endRange = DateUtil.range(
+ DateUtil.parse("2017-01-31"),
+ DateUtil.parse("2017-02-02"), DateField.DAY_OF_YEAR);
+
+ List dateTimes = DateUtil.rangeContains(startRange, endRange);
+ Assertions.assertEquals(1, dateTimes.size());
+
+ List dateNotTimes = DateUtil.rangeNotContains(startRange, endRange);
+ Assertions.assertEquals(2, dateNotTimes.size());
+ }
+}
diff --git a/hutool-core/src/test/java/cn/hutool/core/date/IssueIB9NPUTest.java b/hutool-core/src/test/java/cn/hutool/core/date/IssueIB9NPUTest.java
new file mode 100644
index 000000000..447f5b1aa
--- /dev/null
+++ b/hutool-core/src/test/java/cn/hutool/core/date/IssueIB9NPUTest.java
@@ -0,0 +1,12 @@
+package cn.hutool.core.date;
+
+import org.junit.jupiter.api.Test;
+
+import java.text.SimpleDateFormat;
+
+public class IssueIB9NPUTest {
+ @Test
+ void parseTest() {
+ DateUtil.parse("202409032400", new SimpleDateFormat("yyyyMMddHHmm"));
+ }
+}
diff --git a/hutool-core/src/test/java/cn/hutool/core/date/IssueIBB6I5Test.java b/hutool-core/src/test/java/cn/hutool/core/date/IssueIBB6I5Test.java
new file mode 100644
index 000000000..718f37a9f
--- /dev/null
+++ b/hutool-core/src/test/java/cn/hutool/core/date/IssueIBB6I5Test.java
@@ -0,0 +1,25 @@
+package cn.hutool.core.date;
+
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+
+import java.time.ZoneId;
+import java.util.TimeZone;
+
+public class IssueIBB6I5Test {
+ @Test
+ void parseISO8601Test() {
+ DateTime date = DateUtil.parseISO8601("2024-12-13T08:02:27Z");
+ TimeZone timeZone = TimeZone.getTimeZone(ZoneId.of("Asia/Shanghai"));
+ date.setTimeZone(timeZone);
+ Assertions.assertEquals("2024-12-13 16:02:27", date.toString());
+ }
+
+ @Test
+ void parseISO8601Test2() {
+ DateTime date = DateUtil.parseISO8601("2024-12-13T08:02:27");
+ TimeZone timeZone = TimeZone.getTimeZone(ZoneId.of("Asia/Shanghai"));
+ date.setTimeZone(timeZone);
+ Assertions.assertEquals("2024-12-13 08:02:27", date.toString());
+ }
+}
diff --git a/hutool-core/src/test/java/cn/hutool/core/util/Issue3809Test.java b/hutool-core/src/test/java/cn/hutool/core/util/Issue3809Test.java
new file mode 100644
index 000000000..ac667387b
--- /dev/null
+++ b/hutool-core/src/test/java/cn/hutool/core/util/Issue3809Test.java
@@ -0,0 +1,16 @@
+package cn.hutool.core.util;
+
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+
+public class Issue3809Test {
+ @Test
+ void roundStrTest() {
+ Assertions.assertEquals("9999999999999999.99", NumberUtil.roundStr("9999999999999999.99", 2)); //输出结果不符合方法声明返回值规则
+ Assertions.assertEquals("11111111111111119.00", NumberUtil.roundStr("11111111111111119.00", 2));
+ Assertions.assertEquals("7999999999999999.99", NumberUtil.roundStr("7999999999999999.99", 2)); //输出结果不符合方法声明返回值规则
+ Assertions.assertEquals("699999999991999.92", NumberUtil.roundStr("699999999991999.92", 2)); //输出结果不符合方法声明返回值规则
+ Assertions.assertEquals("10.92", NumberUtil.roundStr("10.92", 2));
+ Assertions.assertEquals("10.99", NumberUtil.roundStr("10.99", 2));
+ }
+}
diff --git a/hutool-core/src/test/java/cn/hutool/core/util/IssueIB95X4Test.java b/hutool-core/src/test/java/cn/hutool/core/util/IssueIB95X4Test.java
new file mode 100644
index 000000000..49b281229
--- /dev/null
+++ b/hutool-core/src/test/java/cn/hutool/core/util/IssueIB95X4Test.java
@@ -0,0 +1,16 @@
+package cn.hutool.core.util;
+
+import cn.hutool.core.lang.PatternPool;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+
+public class IssueIB95X4Test {
+
+ @Test
+ void isMacTest() {
+ Assertions.assertTrue(ReUtil.isMatch(PatternPool.MAC_ADDRESS, "ab1c.2d3e.f468"));
+ Assertions.assertTrue(ReUtil.isMatch(PatternPool.MAC_ADDRESS, "ab:1c:2d:3e:f4:68"));
+ Assertions.assertTrue(ReUtil.isMatch(PatternPool.MAC_ADDRESS, "ab-1c-2d-3e-f4-68"));
+ Assertions.assertTrue(ReUtil.isMatch(PatternPool.MAC_ADDRESS, "ab1c2d3ef468"));
+ }
+}
diff --git a/hutool-cron/pom.xml b/hutool-cron/pom.xml
index 2f36a22ad..78263c982 100755
--- a/hutool-cron/pom.xml
+++ b/hutool-cron/pom.xml
@@ -9,7 +9,7 @@
cn.hutool
hutool-parent
- 5.8.34
+ 5.8.35
hutool-cron
diff --git a/hutool-crypto/pom.xml b/hutool-crypto/pom.xml
index 4ee1a3991..557797fb6 100755
--- a/hutool-crypto/pom.xml
+++ b/hutool-crypto/pom.xml
@@ -9,7 +9,7 @@
cn.hutool
hutool-parent
- 5.8.34
+ 5.8.35
hutool-crypto
diff --git a/hutool-db/pom.xml b/hutool-db/pom.xml
index 224d04a89..ee443457a 100755
--- a/hutool-db/pom.xml
+++ b/hutool-db/pom.xml
@@ -9,7 +9,7 @@
cn.hutool
hutool-parent
- 5.8.34
+ 5.8.35
hutool-db
diff --git a/hutool-db/src/main/java/cn/hutool/db/Entity.java b/hutool-db/src/main/java/cn/hutool/db/Entity.java
index cd807c359..a66ad8060 100755
--- a/hutool-db/src/main/java/cn/hutool/db/Entity.java
+++ b/hutool-db/src/main/java/cn/hutool/db/Entity.java
@@ -8,6 +8,7 @@ import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.CharsetUtil;
import cn.hutool.core.util.ReflectUtil;
import cn.hutool.core.util.StrUtil;
+import cn.hutool.db.sql.Condition;
import cn.hutool.db.sql.SqlUtil;
import java.nio.charset.Charset;
@@ -266,6 +267,17 @@ public class Entity extends Dict {
}
// -------------------------------------------------------------------- Put and Set start
+ /**
+ * 添加条件
+ *
+ * @param condition 条件
+ * @return this
+ * @since 5.8.34
+ */
+ public Entity addCondition(final Condition condition) {
+ return set(condition.getField(), condition);
+ }
+
@Override
public Entity set(String field, Object value) {
return (Entity) super.set(field, value);
diff --git a/hutool-dfa/pom.xml b/hutool-dfa/pom.xml
index d619fd4dd..5927c802f 100755
--- a/hutool-dfa/pom.xml
+++ b/hutool-dfa/pom.xml
@@ -9,7 +9,7 @@
cn.hutool
hutool-parent
- 5.8.34
+ 5.8.35
hutool-dfa
diff --git a/hutool-extra/pom.xml b/hutool-extra/pom.xml
index 83c88d98c..564ebc22d 100755
--- a/hutool-extra/pom.xml
+++ b/hutool-extra/pom.xml
@@ -9,7 +9,7 @@
cn.hutool
hutool-parent
- 5.8.34
+ 5.8.35
hutool-extra
diff --git a/hutool-extra/src/main/java/cn/hutool/extra/ftp/Ftp.java b/hutool-extra/src/main/java/cn/hutool/extra/ftp/Ftp.java
index 9bdc9fac2..96fbd275e 100755
--- a/hutool-extra/src/main/java/cn/hutool/extra/ftp/Ftp.java
+++ b/hutool-extra/src/main/java/cn/hutool/extra/ftp/Ftp.java
@@ -708,9 +708,11 @@ public class Ftp extends AbstractFtp {
if (null != fileNameCharset) {
fileName = new String(fileName.getBytes(fileNameCharset), StandardCharsets.ISO_8859_1);
}
+
+ boolean isSuccess;
try {
client.setFileType(FTPClient.BINARY_FILE_TYPE);
- client.retrieveFile(fileName, out);
+ isSuccess = client.retrieveFile(fileName, out);
} catch (IOException e) {
throw new IORuntimeException(e);
} finally {
@@ -718,6 +720,10 @@ public class Ftp extends AbstractFtp {
cd(pwd);
}
}
+
+ if(false == isSuccess){
+ throw new FtpException("retrieveFile return false");
+ }
}
/**
diff --git a/hutool-extra/src/main/java/cn/hutool/extra/ssh/Sftp.java b/hutool-extra/src/main/java/cn/hutool/extra/ssh/Sftp.java
index 865f216d4..412509098 100755
--- a/hutool-extra/src/main/java/cn/hutool/extra/ssh/Sftp.java
+++ b/hutool-extra/src/main/java/cn/hutool/extra/ssh/Sftp.java
@@ -169,7 +169,7 @@ public class Sftp extends AbstractFtp {
*/
public void init() {
// issue#IB69U8 如果用户传入Session对象,则不能使用配置初始化,而是尝试重新连接
- if(StrUtil.isEmpty(this.ftpConfig.getHost()) && null != this.session){
+ if(null != this.session){
try {
this.session.connect((int) this.ftpConfig.getConnectionTimeout());
} catch (JSchException e) {
diff --git a/hutool-http/pom.xml b/hutool-http/pom.xml
index 403dae32a..1662ffb7f 100755
--- a/hutool-http/pom.xml
+++ b/hutool-http/pom.xml
@@ -9,7 +9,7 @@
cn.hutool
hutool-parent
- 5.8.34
+ 5.8.35
hutool-http
diff --git a/hutool-http/src/test/java/cn/hutool/http/IssueIB7REWTest.java b/hutool-http/src/test/java/cn/hutool/http/IssueIB7REWTest.java
new file mode 100644
index 000000000..58db5ce38
--- /dev/null
+++ b/hutool-http/src/test/java/cn/hutool/http/IssueIB7REWTest.java
@@ -0,0 +1,15 @@
+package cn.hutool.http;
+
+import cn.hutool.core.lang.Console;
+import org.junit.jupiter.api.Disabled;
+import org.junit.jupiter.api.Test;
+
+public class IssueIB7REWTest {
+ @Test
+ @Disabled
+ void getTest() {
+ System.setProperty("jdk.tls.namedCurves", "secp256r1,secp384r1,secp521r1");
+ final String s = HttpUtil.get("https://ebssec.boc.cn/");
+ Console.log(s);
+ }
+}
diff --git a/hutool-json/pom.xml b/hutool-json/pom.xml
index c1dee152d..281a1fc5f 100755
--- a/hutool-json/pom.xml
+++ b/hutool-json/pom.xml
@@ -9,7 +9,7 @@
cn.hutool
hutool-parent
- 5.8.34
+ 5.8.35
hutool-json
diff --git a/hutool-json/src/main/java/cn/hutool/json/JSON.java b/hutool-json/src/main/java/cn/hutool/json/JSON.java
index 4932f1e8a..9a5972cc9 100755
--- a/hutool-json/src/main/java/cn/hutool/json/JSON.java
+++ b/hutool-json/src/main/java/cn/hutool/json/JSON.java
@@ -97,6 +97,32 @@ public interface JSON extends Cloneable, Serializable, IJSONTypeConverter {
*/
T getByPath(String expression, Class resultType);
+ /**
+ * 通过表达式获取JSON中嵌套的对象
+ *
+ * - .表达式,可以获取Bean对象中的属性(字段)值或者Map中key对应的值
+ * - []表达式,可以获取集合等对象中对应index的值
+ *
+ *
+ * 表达式栗子:
+ *
+ *
+ * persion
+ * persion.name
+ * persons[3]
+ * person.friends[5].name
+ *
+ *
+ * 获取表达式对应值后转换为对应类型的值
+ *
+ * @param expression 表达式
+ * @param targetType 返回值类型
+ * @return 对象
+ * @see BeanPath#get(Object)
+ * @since 5.8.34
+ */
+ T getByPath(String expression, TypeReference targetType);
+
/**
* 格式化打印JSON,缩进为4个空格
*
diff --git a/hutool-json/src/main/java/cn/hutool/json/JSONArray.java b/hutool-json/src/main/java/cn/hutool/json/JSONArray.java
index e7371f14f..636da5da7 100755
--- a/hutool-json/src/main/java/cn/hutool/json/JSONArray.java
+++ b/hutool-json/src/main/java/cn/hutool/json/JSONArray.java
@@ -3,6 +3,7 @@ package cn.hutool.json;
import cn.hutool.core.bean.BeanPath;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.lang.Filter;
+import cn.hutool.core.lang.TypeReference;
import cn.hutool.core.lang.Validator;
import cn.hutool.core.lang.mutable.Mutable;
import cn.hutool.core.lang.mutable.MutableObj;
@@ -13,6 +14,7 @@ import cn.hutool.json.serialize.JSONWriter;
import java.io.StringWriter;
import java.io.Writer;
+import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
@@ -195,7 +197,7 @@ public class JSONArray implements JSON, JSONGetter, List