- * 1. 将+和%20转换为空格 ; + * 1. 将+和%20转换为空格(" "); * 2. 将"%xy"转换为文本形式,xy是两位16进制的数值; * 3. 跳过不符合规范的%形式,直接输出 *diff --git a/hutool-core/src/main/java/cn/hutool/core/net/URLEncodeUtil.java b/hutool-core/src/main/java/cn/hutool/core/net/URLEncodeUtil.java index 94d462bd7..cc01cd212 100644 --- a/hutool-core/src/main/java/cn/hutool/core/net/URLEncodeUtil.java +++ b/hutool-core/src/main/java/cn/hutool/core/net/URLEncodeUtil.java @@ -7,7 +7,8 @@ import cn.hutool.core.util.StrUtil; import java.nio.charset.Charset; /** - * URL编码工具 + * URL编码工具
+ * 坐标转换相关参考: https://tool.lu/coordinate/
+ * 参考:https://github.com/JourWon/coordinate-transform
+ *
+ * @author hongzhe.qin(qin462328037at163.com), looly
+ * @since 5.7.16
+ */
+public class CoordinateUtil {
+
+ /**
+ * 坐标转换参数:(火星坐标系与百度坐标系转换的中间量)
+ */
+ public static final double X_PI = 3.14159265358979324 * 3000.0 / 180.0;
+
+ /**
+ * 坐标转换参数:π
+ */
+ public static final double PI = 3.1415926535897932384626D;
+
+ /**
+ * 地球半径(Krasovsky 1940)
+ */
+ public static final double RADIUS = 6378245.0D;
+
+ /**
+ * 修正参数(偏率ee)
+ */
+ public static final double CORRECTION_PARAM = 0.00669342162296594323D;
+
+ /**
+ * 判断坐标是否在国外
+ * 火星坐标系 (GCJ-02)只对国内有效,国外无需转换
+ *
+ * @param lng 经度
+ * @param lat 纬度
+ * @return 坐标是否在国外
+ */
+ public static boolean outOfChina(double lng, double lat) {
+ return (lng < 72.004 || lng > 137.8347) || (lat < 0.8293 || lat > 55.8271);
+ }
+
+ //----------------------------------------------------------------------------------- WGS84
+ /**
+ * WGS84 转换为 火星坐标系 (GCJ-02)
+ *
+ * @param lng 经度值
+ * @param lat 维度值
+ * @return 火星坐标 (GCJ-02)
+ */
+ public static Coordinate wgs84ToGcj02(double lng, double lat) {
+ return new Coordinate(lng, lat).offset(offset(lng, lat, true));
+ }
+
+ /**
+ * WGS84 坐标转为 百度坐标系 (BD-09) 坐标
+ *
+ * @param lng 经度值
+ * @param lat 维度值
+ * @return bd09 坐标
+ */
+ public static Coordinate wgs84ToBd09(double lng, double lat) {
+ final Coordinate gcj02 = wgs84ToGcj02(lng, lat);
+ return gcj02ToBd09(gcj02.lng, gcj02.lat);
+ }
+
+ //----------------------------------------------------------------------------------- GCJ-02
+ /**
+ * 火星坐标系 (GCJ-02) 转换为 WGS84
+ *
+ * @param lng 经度坐标
+ * @param lat 维度坐标
+ * @return WGS84 坐标
+ */
+ public static Coordinate gcj02ToWgs84(double lng, double lat) {
+ return new Coordinate(lng, lat).offset(offset(lng, lat, false));
+ }
+
+ /**
+ * 火星坐标系 (GCJ-02) 与百度坐标系 (BD-09) 的转换
+ *
+ * @param lng 经度值
+ * @param lat 纬度值
+ * @return BD-09 坐标
+ */
+ public static Coordinate gcj02ToBd09(double lng, double lat) {
+ double z = Math.sqrt(lng * lng + lat * lat) + 0.00002 * Math.sin(lat * X_PI);
+ double theta = Math.atan2(lat, lng) + 0.000003 * Math.cos(lng * X_PI);
+ double bd_lng = z * Math.cos(theta) + 0.0065;
+ double bd_lat = z * Math.sin(theta) + 0.006;
+ return new Coordinate(bd_lng, bd_lat);
+ }
+
+ //----------------------------------------------------------------------------------- BD-09
+ /**
+ * 百度坐标系 (BD-09) 与 火星坐标系 (GCJ-02)的转换
+ * 即 百度 转 谷歌、高德
+ *
+ * @param lng 经度值
+ * @param lat 纬度值
+ * @return GCJ-02 坐标
+ */
+ public static Coordinate bd09ToGcj02(double lng, double lat) {
+ double x = lng - 0.0065;
+ double y = lat - 0.006;
+ double z = Math.sqrt(x * x + y * y) - 0.00002 * Math.sin(y * X_PI);
+ double theta = Math.atan2(y, x) - 0.000003 * Math.cos(x * X_PI);
+ double gg_lng = z * Math.cos(theta);
+ double gg_lat = z * Math.sin(theta);
+ return new Coordinate(gg_lng, gg_lat);
+ }
+
+ /**
+ * 百度坐标系 (BD-09) 与 WGS84 的转换
+ *
+ * @param lng 经度值
+ * @param lat 纬度值
+ * @return WGS84坐标
+ */
+ public static Coordinate bd09toWgs84(double lng, double lat) {
+ final Coordinate gcj02 = bd09ToGcj02(lng, lat);
+ return gcj02ToWgs84(gcj02.lng, gcj02.lat);
+ }
+
+ //----------------------------------------------------------------------------------- Private methods begin
+
+ /**
+ * 转换坐标公共核心
+ *
+ * @param lng 经度坐标
+ * @param lat 维度坐标
+ * @return 返回结果
+ */
+ private static double transCore(double lng, double lat) {
+ double ret = (20.0 * Math.sin(6.0 * lng * PI) + 20.0 * Math.sin(2.0 * lng * PI)) * 2.0 / 3.0;
+ ret += (20.0 * Math.sin(lat * PI) + 40.0 * Math.sin(lat / 3.0 * PI)) * 2.0 / 3.0;
+ return ret;
+ }
+
+ /**
+ * WGS84 与 火星坐标系 (GCJ-02)转换的偏移算法(非精确)
+ *
+ * @param lng 经度值
+ * @param lat 纬度值
+ * @param isPlus 是否正向偏移:WGS84转GCJ-02使用正向,否则使用反向
+ * @return 偏移坐标
+ */
+ private static Coordinate offset(double lng, double lat, boolean isPlus) {
+ double dlng = transLng(lng - 105.0, lat - 35.0);
+ double dlat = transLat(lng - 105.0, lat - 35.0);
+
+ double magic = Math.sin(lat / 180.0 * PI);
+ magic = 1 - CORRECTION_PARAM * magic * magic;
+ double sqrtMagic = Math.sqrt(magic);
+
+ dlng = (dlng * 180.0) / (RADIUS / sqrtMagic * Math.cos(lat / 180.0 * PI) * PI);
+ dlat = (dlat * 180.0) / ((RADIUS * (1 - CORRECTION_PARAM)) / (magic * sqrtMagic) * PI);
+
+ if(false == isPlus){
+ dlng = - dlng;
+ dlat = - dlat;
+ }
+
+ return new Coordinate(dlng, dlat);
+ }
+
+ /**
+ * 计算经度坐标
+ *
+ * @param lng 经度坐标
+ * @param lat 维度坐标
+ * @return ret 计算完成后的
+ */
+ private static double transLng(double lng, double lat) {
+ double ret = 300.0 + lng + 2.0 * lat + 0.1 * lng * lng + 0.1 * lng * lat + 0.1 * Math.sqrt(Math.abs(lng));
+ ret += transCore(lng, lat);
+ ret += (150.0 * Math.sin(lng / 12.0 * PI) + 300.0 * Math.sin(lng / 30.0 * PI)) * 2.0 / 3.0;
+ return ret;
+ }
+
+ /**
+ * 计算纬度坐标
+ *
+ * @param lng 经度
+ * @param lat 维度
+ * @return ret 计算完成后的
+ */
+ private static double transLat(double lng, double lat) {
+ double ret = -100.0 + 2.0 * lng + 3.0 * lat + 0.2 * lat * lat + 0.1 * lng * lat + 0.2 * Math.sqrt(Math.abs(lng));
+ ret += transCore(lng, lat);
+ ret += (160.0 * Math.sin(lat / 12.0 * PI) + 320 * Math.sin(lat * PI / 30.0)) * 2.0 / 3.0;
+ return ret;
+ }
+ //----------------------------------------------------------------------------------- Private methods end
+
+ /**
+ * 坐标经纬度
+ *
+ * @author looly
+ */
+ public static class Coordinate implements Serializable {
+ private static final long serialVersionUID = 1L;
+
+ /**
+ * 经度
+ */
+ private double lng;
+ /**
+ * 纬度
+ */
+ private double lat;
+
+ /**
+ * 构造
+ *
+ * @param lng 经度
+ * @param lat 纬度
+ */
+ public Coordinate(double lng, double lat) {
+ this.lng = lng;
+ this.lat = lat;
+ }
+
+ /**
+ * 获取经度
+ *
+ * @return 经度
+ */
+ public double getLng() {
+ return lng;
+ }
+
+ /**
+ * 设置经度
+ *
+ * @param lng 经度
+ * @return this
+ */
+ public Coordinate setLng(double lng) {
+ this.lng = lng;
+ return this;
+ }
+
+ /**
+ * 获取纬度
+ *
+ * @return 纬度
+ */
+ public double getLat() {
+ return lat;
+ }
+
+ /**
+ * 设置纬度
+ *
+ * @param lat 纬度
+ * @return this
+ */
+ public Coordinate setLat(double lat) {
+ this.lat = lat;
+ return this;
+ }
+
+ /**
+ * 当前坐标偏移指定坐标
+ *
+ * @param offset 偏移量
+ * @return this
+ */
+ public Coordinate offset(Coordinate offset){
+ this.lng += offset.lng;
+ this.lat += offset.lng;
+ return this;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (o == null || getClass() != o.getClass()) {
+ return false;
+ }
+ Coordinate that = (Coordinate) o;
+ return Double.compare(that.lng, lng) == 0 && Double.compare(that.lat, lat) == 0;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(lng, lat);
+ }
+
+ @Override
+ public String toString() {
+ return "Coordinate{" +
+ "lng=" + lng +
+ ", lat=" + lat +
+ '}';
+ }
+ }
+}
diff --git a/hutool-core/src/main/java/cn/hutool/core/util/URLUtil.java b/hutool-core/src/main/java/cn/hutool/core/util/URLUtil.java
index 045fc72b8..5745bce89 100644
--- a/hutool-core/src/main/java/cn/hutool/core/util/URLUtil.java
+++ b/hutool-core/src/main/java/cn/hutool/core/util/URLUtil.java
@@ -319,7 +319,8 @@ public class URLUtil extends URLEncodeUtil {
/**
* 解码application/x-www-form-urlencoded字符
- * 将%开头的16进制表示的内容解码。
+ * 将%开头的16进制表示的内容解码。
+ * 规则见:https://url.spec.whatwg.org/#urlencoded-parsing
*
* @param content 被解码内容
* @param charset 编码,null表示不解码
diff --git a/hutool-core/src/main/java/cn/hutool/core/util/ZipUtil.java b/hutool-core/src/main/java/cn/hutool/core/util/ZipUtil.java
index 37e77b5d5..ddce403fb 100644
--- a/hutool-core/src/main/java/cn/hutool/core/util/ZipUtil.java
+++ b/hutool-core/src/main/java/cn/hutool/core/util/ZipUtil.java
@@ -268,7 +268,7 @@ public class ZipUtil {
/**
* 对文件或文件目录进行压缩
*
- * @param zipOutputStream 生成的Zip到的目标流,不关闭此流
+ * @param zipOutputStream 生成的Zip到的目标流,自动关闭此流
* @param withSrcDir 是否包含被打包目录,只针对压缩目录有效。若为false,则只压缩目录下的文件或目录,为true则将本目录也压缩
* @param filter 文件过滤器,通过实现此接口,自定义要过滤的文件(过滤掉哪些文件或文件夹不加入压缩)
* @param srcFiles 要压缩的源文件或目录。如果压缩一个文件,则为该文件的全路径;如果压缩一个目录,则为该目录的顶层目录路径
@@ -412,7 +412,7 @@ public class ZipUtil {
/**
* 将文件流压缩到目标流中
*
- * @param zipOutputStream 目标流,压缩完成不关闭
+ * @param zipOutputStream 目标流,压缩完成自动关闭
* @param paths 流数据在压缩文件中的路径或文件名
* @param ins 要压缩的源,添加完成后自动关闭流
* @throws IORuntimeException IO异常
diff --git a/hutool-core/src/test/java/cn/hutool/core/convert/NumberChineseFormatterTest.java b/hutool-core/src/test/java/cn/hutool/core/convert/NumberChineseFormatterTest.java
index 8f0d88828..f9bec8251 100644
--- a/hutool-core/src/test/java/cn/hutool/core/convert/NumberChineseFormatterTest.java
+++ b/hutool-core/src/test/java/cn/hutool/core/convert/NumberChineseFormatterTest.java
@@ -278,4 +278,38 @@ public class NumberChineseFormatterTest {
// 非法字符
NumberChineseFormatter.chineseToNumber("一百你三");
}
+
+ @Test
+ public void singleMoneyTest(){
+ String format = NumberChineseFormatter.format(0.01, false, true);
+ Assert.assertEquals("一分", format);
+ format = NumberChineseFormatter.format(0.10, false, true);
+ Assert.assertEquals("一角", format);
+ format = NumberChineseFormatter.format(0.12, false, true);
+ Assert.assertEquals("一角二分", format);
+
+ format = NumberChineseFormatter.format(1.00, false, true);
+ Assert.assertEquals("一元整", format);
+ format = NumberChineseFormatter.format(1.10, false, true);
+ Assert.assertEquals("一元一角", format);
+ format = NumberChineseFormatter.format(1.02, false, true);
+ Assert.assertEquals("一元零二分", format);
+ }
+
+ @Test
+ public void singleNumberTest(){
+ String format = NumberChineseFormatter.format(0.01, false, false);
+ Assert.assertEquals("零点零一", format);
+ format = NumberChineseFormatter.format(0.10, false, false);
+ Assert.assertEquals("零点一", format);
+ format = NumberChineseFormatter.format(0.12, false, false);
+ Assert.assertEquals("零点一二", format);
+
+ format = NumberChineseFormatter.format(1.00, false, false);
+ Assert.assertEquals("一", format);
+ format = NumberChineseFormatter.format(1.10, false, false);
+ Assert.assertEquals("一点一", format);
+ format = NumberChineseFormatter.format(1.02, false, false);
+ Assert.assertEquals("一点零二", format);
+ }
}
diff --git a/hutool-core/src/test/java/cn/hutool/core/io/FileUtilTest.java b/hutool-core/src/test/java/cn/hutool/core/io/FileUtilTest.java
index 4b513abeb..2d04528ba 100644
--- a/hutool-core/src/test/java/cn/hutool/core/io/FileUtilTest.java
+++ b/hutool-core/src/test/java/cn/hutool/core/io/FileUtilTest.java
@@ -298,6 +298,12 @@ public class FileUtilTest {
}
}
+ @Test
+ @Ignore
+ public void loopFilesTest2() {
+ FileUtil.loopFiles("").forEach(Console::log);
+ }
+
@Test
@Ignore
public void loopFilesWithDepthTest() {
diff --git a/hutool-core/src/test/java/cn/hutool/core/lang/OptTest.java b/hutool-core/src/test/java/cn/hutool/core/lang/OptTest.java
index 07ea9eccb..7af6a4f04 100644
--- a/hutool-core/src/test/java/cn/hutool/core/lang/OptTest.java
+++ b/hutool-core/src/test/java/cn/hutool/core/lang/OptTest.java
@@ -11,8 +11,6 @@ import org.junit.Test;
import java.util.ArrayList;
import java.util.List;
import java.util.NoSuchElementException;
-import java.util.function.Consumer;
-import java.util.stream.Stream;
/**
* {@link Opt}的单元测试
@@ -72,7 +70,7 @@ public class OptTest {
User user = new User();
// 相当于上面peek的动态参数调用,更加灵活,你可以像操作数组一样去动态设置中间的步骤,也可以使用这种方式去编写你的代码
// 可以一行搞定
- Opt.ofNullable("hutool").peeks(user::setUsername, user::setNickname, System.out::println);
+ Opt.ofNullable("hutool").peeks(user::setUsername, user::setNickname);
// 也可以在适当的地方换行使得代码的可读性提高
Opt.of(user).peeks(
u -> Assert.assertEquals("hutool", u.getNickname()),
@@ -83,15 +81,11 @@ public class OptTest {
// 注意,传入的lambda中,对包裹内的元素执行赋值操作并不会影响到原来的元素,这是java语言的特性。。。
// 这也是为什么我们需要getter和setter而不直接给bean中的属性赋值中的其中一个原因
- String name = Opt.ofNullable("hutool").peeks(username -> username = "123", username -> username = "456", n -> Assert.assertEquals("hutool", n)).get();
+ String name = Opt.ofNullable("hutool").peeks(
+ username -> username = "123", username -> username = "456",
+ n -> Assert.assertEquals("hutool", n)).get();
Assert.assertEquals("hutool", name);
- // 在控制台打印n次hutool
- int n = 10;
- @SuppressWarnings("unchecked")
- Consumer
+ * 测试参考:https://github.com/wandergis/coordtransform
+ *
+ * @author hongzhe.qin, looly
+ */
+public class CoordinateUtilTest {
+
+ @Test
+ public void gcj02ToBd09Test() {
+ final CoordinateUtil.Coordinate gcj02 = CoordinateUtil.gcj02ToBd09(116.404, 39.915);
+ Assert.assertEquals(116.41036949371029D, gcj02.getLng(), 15);
+ Assert.assertEquals(39.92133699351021D, gcj02.getLat(), 15);
+ }
+
+ @Test
+ public void bd09toGcj02Test(){
+ final CoordinateUtil.Coordinate gcj02 = CoordinateUtil.bd09ToGcj02(116.404, 39.915);
+ Assert.assertEquals(116.39762729119315D, gcj02.getLng(), 15);
+ Assert.assertEquals(39.90865673957631D, gcj02.getLat(), 15);
+ }
+
+ @Test
+ public void gcj02ToWgs84(){
+ final CoordinateUtil.Coordinate gcj02 = CoordinateUtil.wgs84ToGcj02(116.404, 39.915);
+ Assert.assertEquals(116.39775550083061D, gcj02.getLng(), 15);
+ Assert.assertEquals(39.91359571849836D, gcj02.getLat(), 15);
+ }
+
+ @Test
+ public void wgs84ToGcj02Test(){
+ final CoordinateUtil.Coordinate gcj02 = CoordinateUtil.wgs84ToGcj02(116.404, 39.915);
+ Assert.assertEquals(116.41024449916938D, gcj02.getLng(), 15);
+ Assert.assertEquals(39.91640428150164D, gcj02.getLat(), 15);
+ }
+
+ @Test
+ public void wgs84toBd09(){
+
+ }
+
+}
diff --git a/hutool-core/src/test/java/cn/hutool/core/util/ZipUtilTest.java b/hutool-core/src/test/java/cn/hutool/core/util/ZipUtilTest.java
index a98972e67..309baddf7 100644
--- a/hutool-core/src/test/java/cn/hutool/core/util/ZipUtilTest.java
+++ b/hutool-core/src/test/java/cn/hutool/core/util/ZipUtilTest.java
@@ -11,6 +11,7 @@ import org.junit.Test;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
+import java.io.InputStream;
import java.io.OutputStream;
import java.nio.charset.Charset;
import java.util.ArrayList;
@@ -169,15 +170,20 @@ public class ZipUtilTest {
String file3 = "d:/test/asn1.key";
String zip = "d:/test/test2.zip";
- try (OutputStream out = new FileOutputStream(zip)){
- //实际应用中, out 为 HttpServletResponse.getOutputStream
- ZipUtil.zip(out, Charset.defaultCharset(), false, null,
- new File(file1),
- new File(file2),
- new File(file3)
- );
- } catch (IOException e) {
- throw new IORuntimeException(e);
- }
+ //实际应用中, out 为 HttpServletResponse.getOutputStream
+ ZipUtil.zip(FileUtil.getOutputStream(zip), Charset.defaultCharset(), false, null,
+ new File(file1),
+ new File(file2),
+ new File(file3)
+ );
+ }
+
+ @Test
+ @Ignore
+ public void zipToStreamTest(){
+ String zip = "d:/test/testToStream.zip";
+ OutputStream out = FileUtil.getOutputStream(zip);
+ ZipUtil.zip(out, new String[]{"sm1_alias.txt"},
+ new InputStream[]{FileUtil.getInputStream("d:/test/sm4_1.txt")});
}
}
diff --git a/hutool-cron/src/main/java/cn/hutool/cron/pattern/CronPattern.java b/hutool-cron/src/main/java/cn/hutool/cron/pattern/CronPattern.java
index 6002bf471..b026cdd3c 100644
--- a/hutool-cron/src/main/java/cn/hutool/cron/pattern/CronPattern.java
+++ b/hutool-cron/src/main/java/cn/hutool/cron/pattern/CronPattern.java
@@ -44,7 +44,7 @@ import java.util.TimeZone;
* 注意:
*
*
- * 当isMatchSecond为
*
@@ -124,7 +124,7 @@ public class CronPattern {
*
* @param millis 时间毫秒数
* @param isMatchSecond 是否匹配秒
- * @return 如果匹配返回 true
时才会匹配秒部分
+ * 当isMatchSecond为{@code true}时才会匹配秒部分
* 默认都是关闭的
* true
, 否则返回 false
+ * @return 如果匹配返回 {@code true}, 否则返回 {@code false}
*/
public boolean match(long millis, boolean isMatchSecond) {
return match(TimeZone.getDefault(), millis, isMatchSecond);
@@ -136,7 +136,7 @@ public class CronPattern {
* @param timezone 时区 {@link TimeZone}
* @param millis 时间毫秒数
* @param isMatchSecond 是否匹配秒
- * @return 如果匹配返回 true
, 否则返回 false
+ * @return 如果匹配返回 {@code true}, 否则返回 {@code false}
*/
public boolean match(TimeZone timezone, long millis, boolean isMatchSecond) {
final GregorianCalendar calendar = new GregorianCalendar(timezone);
@@ -149,7 +149,7 @@ public class CronPattern {
*
* @param calendar 时间
* @param isMatchSecond 是否匹配秒
- * @return 如果匹配返回 true
, 否则返回 false
+ * @return 如果匹配返回 {@code true}, 否则返回 {@code false}
*/
public boolean match(GregorianCalendar calendar, boolean isMatchSecond) {
final int second = calendar.get(Calendar.SECOND);
diff --git a/hutool-cron/src/test/java/cn/hutool/cron/pattern/CronPatternTest.java b/hutool-cron/src/test/java/cn/hutool/cron/pattern/CronPatternTest.java
index 6efdb28e6..bd77a8e2b 100644
--- a/hutool-cron/src/test/java/cn/hutool/cron/pattern/CronPatternTest.java
+++ b/hutool-cron/src/test/java/cn/hutool/cron/pattern/CronPatternTest.java
@@ -1,13 +1,14 @@
package cn.hutool.cron.pattern;
import cn.hutool.core.date.DateUtil;
+import cn.hutool.core.thread.ThreadUtil;
import cn.hutool.cron.CronException;
import org.junit.Assert;
import org.junit.Test;
/**
* 定时任务单元测试类
- *
+ *
* @author Looly
*
*/
@@ -18,10 +19,11 @@ public class CronPatternTest {
CronPattern pattern;
// 任何时间匹配
pattern = new CronPattern("* * * * * *");
+ ThreadUtil.sleep(600);
Assert.assertTrue(pattern.match(DateUtil.current(), true));
Assert.assertTrue(pattern.match(DateUtil.current(), false));
}
-
+
@Test
public void matchAllTest2() {
// 在5位表达式中,秒部分并不是任意匹配,而是一个固定值
@@ -88,14 +90,14 @@ public class CronPatternTest {
assertMatch(pattern, "2017-02-09 00:00:39");
}
-
+
@SuppressWarnings("ConstantConditions")
@Test
public void CronPatternTest2() {
CronPattern pattern = new CronPattern("0/30 * * * *");
Assert.assertTrue(pattern.match(DateUtil.parse("2018-10-09 12:00:00").getTime(), false));
Assert.assertTrue(pattern.match(DateUtil.parse("2018-10-09 12:30:00").getTime(), false));
-
+
pattern = new CronPattern("32 * * * *");
Assert.assertTrue(pattern.match(DateUtil.parse("2018-10-09 12:32:00").getTime(), false));
}
@@ -144,12 +146,12 @@ public class CronPatternTest {
@Test(expected = CronException.class)
public void rangeYearTest() {
// year的范围是1970~2099年,超出报错
- CronPattern pattern = new CronPattern("0/1 * * * 1/1 ? 2020-2120");
+ new CronPattern("0/1 * * * 1/1 ? 2020-2120");
}
/**
* 表达式是否匹配日期
- *
+ *
* @param pattern 表达式
* @param date 日期,标准日期时间字符串
*/
diff --git a/hutool-crypto/src/main/java/cn/hutool/crypto/SmUtil.java b/hutool-crypto/src/main/java/cn/hutool/crypto/SmUtil.java
index e78df4dc0..6aada8c7f 100644
--- a/hutool-crypto/src/main/java/cn/hutool/crypto/SmUtil.java
+++ b/hutool-crypto/src/main/java/cn/hutool/crypto/SmUtil.java
@@ -54,7 +54,7 @@ public class SmUtil {
public static final ECDomainParameters SM2_DOMAIN_PARAMS = BCUtil.toDomainParams(GMNamedCurves.getByName(SM2_CURVE_NAME));
/**
* SM2国密算法公钥参数的Oid标识
- */
+ */
public static final ASN1ObjectIdentifier ID_SM2_PUBLIC_KEY_PARAM = new ASN1ObjectIdentifier("1.2.156.10197.1.301");
/**
@@ -133,6 +133,17 @@ public class SmUtil {
return new SM3();
}
+ /**
+ * SM3加密,可以传入盐
+ *
+ * @param salt 加密盐
+ * @return {@link SM3}
+ * @since 5.7.16
+ */
+ public static SM3 sm3WithSalt(byte[] salt) {
+ return new SM3(salt);
+ }
+
/**
* SM3加密,生成16进制SM3字符串
*
diff --git a/hutool-extra/src/main/java/cn/hutool/extra/mail/MailAccount.java b/hutool-extra/src/main/java/cn/hutool/extra/mail/MailAccount.java
index 6cff1777d..f2d3aef9a 100644
--- a/hutool-extra/src/main/java/cn/hutool/extra/mail/MailAccount.java
+++ b/hutool-extra/src/main/java/cn/hutool/extra/mail/MailAccount.java
@@ -608,8 +608,9 @@ public class MailAccount implements Serializable {
this.host = StrUtil.format("smtp.{}", StrUtil.subSuf(fromAddress, fromAddress.indexOf('@') + 1));
}
if (StrUtil.isBlank(user)) {
- // 如果用户名为空,默认为发件人邮箱前缀
- this.user = StrUtil.subPre(fromAddress, fromAddress.indexOf('@'));
+ // 如果用户名为空,默认为发件人(issue#I4FYVY@Gitee)
+ //this.user = StrUtil.subPre(fromAddress, fromAddress.indexOf('@'));
+ this.user = fromAddress;
}
if (null == this.auth) {
// 如果密码非空白,则使用认证模式
diff --git a/hutool-extra/src/test/resources/config/mail.setting b/hutool-extra/src/test/resources/config/mail.setting
index f9a9cf720..2fd907007 100644
--- a/hutool-extra/src/test/resources/config/mail.setting
+++ b/hutool-extra/src/test/resources/config/mail.setting
@@ -11,7 +11,7 @@ port = 465
# 发件人(必须正确,否则发送失败)
from = 小磊