diff --git a/CHANGELOG.md b/CHANGELOG.md index b3ae47dc0..1ac8071bd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,7 +3,21 @@ ------------------------------------------------------------------------------------------------------------- -# 5.4.5 (2020-10-16) +# 5.4.6 (2020-10-21) + +### 新特性 +* 【http 】 HttpRequest增加basicProxyAuth方法(issue#I1YQGM@Gitee) +* 【core 】 NumberUtil.toStr修改逻辑,去掉BigDecimal的科学计数表示(pr#196@Gitee) + +### Bug修复 +* 【core 】 修复ChineseDate没有忽略时分秒导致计算错误问题(issue#I1YW12@Gitee) +* 【core 】 修复FileUtil中,copyFile方法断言判断参数传递错误(issue#I1Z2NY@Gitee) +* 【core 】 修复BeanDesc读取父类属性覆盖子类属性导致的问题(pr#1175@Github) +* 【aop 】 修复SimpleAspect一个重载导致的问题,去掉重载的after方法(issue#I1YUG9@Gitee) + +------------------------------------------------------------------------------------------------------------- + +# 5.4.5 (2020-10-18) ### 新特性 * 【core 】 ConsoleTable代码优化(pr#190@Gitee) @@ -20,6 +34,9 @@ * 【core 】 优化针对list的split方法(pr#194@Gitee) * 【poi 】 ExcelWriter增加setRowStyle方法 * 【core 】 Assert增加函数接口(pr#1166@Github) +* 【core 】 新增AtomicIntegerArray、AtomicLongArray转换 +* 【extra 】 PinyinUtil新增Bopomofo4j支持 +* 【core 】 新增TemporalUtil工具类,新增时间相关方法 ### Bug修复 * 【core 】 解决农历判断节日未判断大小月导致的问题(issue#I1XHSF@Gitee) @@ -28,6 +45,7 @@ * 【core 】 修复CaseInsensitiveMap的remove等方法并没有忽略大小写的问题(pr#1163@Gitee) * 【poi 】 修复合并单元格值读取错误的问题 * 【poi 】 修复NamedSql解析形如col::numeric出错问题(issue#I1YHBX@Gitee) +* 【core 】 修复计算相差天数导致的问题 ------------------------------------------------------------------------------------------------------------- diff --git a/README-EN.md b/README-EN.md index 109d59373..941d9f06c 100644 --- a/README-EN.md +++ b/README-EN.md @@ -120,19 +120,19 @@ Each module can be introduced individually, or all modules can be introduced by cn.hutool hutool-all - 5.4.5 + 5.4.6 ``` ### Gradle ``` -compile 'cn.hutool:hutool-all:5.4.5' +compile 'cn.hutool:hutool-all:5.4.6' ``` ## Download -- [Maven1](https://repo1.maven.org/maven2/cn/hutool/hutool-all/5.4.5/) -- [Maven2](http://repo2.maven.org/maven2/cn/hutool/hutool-all/5.4.5/) +- [Maven1](https://repo1.maven.org/maven2/cn/hutool/hutool-all/5.4.6/) +- [Maven2](http://repo2.maven.org/maven2/cn/hutool/hutool-all/5.4.6/) > note: > Hutool 5.x supports JDK8+ and is not tested on Android platforms, and cannot guarantee that all tool classes or tool methods are available. diff --git a/README.md b/README.md index ffb4b58c4..8dc6689b6 100644 --- a/README.md +++ b/README.md @@ -119,21 +119,21 @@ Hutool的存在就是为了减少代码搜索成本,避免网络上参差不 cn.hutool hutool-all - 5.4.5 + 5.4.6 ``` ### Gradle ``` -compile 'cn.hutool:hutool-all:5.4.5' +compile 'cn.hutool:hutool-all:5.4.6' ``` ### 非Maven项目 点击以下任一链接,下载`hutool-all-X.X.X.jar`即可: -- [Maven中央库1](https://repo1.maven.org/maven2/cn/hutool/hutool-all/5.4.5/) -- [Maven中央库2](http://repo2.maven.org/maven2/cn/hutool/hutool-all/5.4.5/) +- [Maven中央库1](https://repo1.maven.org/maven2/cn/hutool/hutool-all/5.4.6/) +- [Maven中央库2](http://repo2.maven.org/maven2/cn/hutool/hutool-all/5.4.6/) > 注意 > Hutool 5.x支持JDK8+,对Android平台没有测试,不能保证所有工具类或工具方法可用。 diff --git a/bin/version.txt b/bin/version.txt index 8ce222e90..bb0915fd5 100755 --- a/bin/version.txt +++ b/bin/version.txt @@ -1 +1 @@ -5.4.5 +5.4.6 diff --git a/docs/js/version.js b/docs/js/version.js index ca23d3c78..86e998e04 100644 --- a/docs/js/version.js +++ b/docs/js/version.js @@ -1 +1 @@ -var version = '5.4.5' \ No newline at end of file +var version = '5.4.6' \ No newline at end of file diff --git a/hutool-all/pom.xml b/hutool-all/pom.xml index 9c635dedf..1e4cafd2f 100644 --- a/hutool-all/pom.xml +++ b/hutool-all/pom.xml @@ -9,7 +9,7 @@ cn.hutool hutool-parent - 5.4.5-SNAPSHOT + 5.4.6-SNAPSHOT hutool-all diff --git a/hutool-aop/pom.xml b/hutool-aop/pom.xml index ba86c1b4a..dccff3aab 100644 --- a/hutool-aop/pom.xml +++ b/hutool-aop/pom.xml @@ -9,7 +9,7 @@ cn.hutool hutool-parent - 5.4.5-SNAPSHOT + 5.4.6-SNAPSHOT hutool-aop diff --git a/hutool-aop/src/main/java/cn/hutool/aop/aspects/SimpleAspect.java b/hutool-aop/src/main/java/cn/hutool/aop/aspects/SimpleAspect.java index 99f959da2..6c0d6a0d1 100644 --- a/hutool-aop/src/main/java/cn/hutool/aop/aspects/SimpleAspect.java +++ b/hutool-aop/src/main/java/cn/hutool/aop/aspects/SimpleAspect.java @@ -18,24 +18,6 @@ public class SimpleAspect implements Aspect, Serializable { return true; } - - /** - * 目标方法执行后的操作 - * 如果 target.method 抛出异常且 - * - * @param target 目标对象 - * @param method 目标方法 - * @param args 参数 - * @return 是否允许返回值(接下来的操作) - * @see Aspect#afterException 返回true,则不会执行此操作 - * 如果 - * @see Aspect#afterException 返回false,则无论target.method是否抛出异常,均会执行此操作 - */ - public boolean after(Object target, Method method, Object[] args) { - //继承此类后实现此方法 - return after(target, method, args, null); - } - @Override public boolean after(Object target, Method method, Object[] args, Object returnVal) { //继承此类后实现此方法 diff --git a/hutool-bloomFilter/pom.xml b/hutool-bloomFilter/pom.xml index dd544604e..9c7da9d21 100644 --- a/hutool-bloomFilter/pom.xml +++ b/hutool-bloomFilter/pom.xml @@ -7,7 +7,7 @@ cn.hutool hutool-parent - 5.4.5-SNAPSHOT + 5.4.6-SNAPSHOT hutool-bloomFilter diff --git a/hutool-bom/pom.xml b/hutool-bom/pom.xml index 4b0d9b363..3724e75c7 100644 --- a/hutool-bom/pom.xml +++ b/hutool-bom/pom.xml @@ -7,7 +7,7 @@ cn.hutool hutool-parent - 5.4.5-SNAPSHOT + 5.4.6-SNAPSHOT hutool-bom diff --git a/hutool-cache/pom.xml b/hutool-cache/pom.xml index ab7b31fd8..32b6f3d7d 100644 --- a/hutool-cache/pom.xml +++ b/hutool-cache/pom.xml @@ -7,7 +7,7 @@ cn.hutool hutool-parent - 5.4.5-SNAPSHOT + 5.4.6-SNAPSHOT hutool-cache diff --git a/hutool-captcha/pom.xml b/hutool-captcha/pom.xml index b4dd92449..99859b461 100644 --- a/hutool-captcha/pom.xml +++ b/hutool-captcha/pom.xml @@ -7,7 +7,7 @@ cn.hutool hutool-parent - 5.4.5-SNAPSHOT + 5.4.6-SNAPSHOT hutool-captcha diff --git a/hutool-core/pom.xml b/hutool-core/pom.xml index 42bebd745..61b9fd1a5 100644 --- a/hutool-core/pom.xml +++ b/hutool-core/pom.xml @@ -9,7 +9,7 @@ cn.hutool hutool-parent - 5.4.5-SNAPSHOT + 5.4.6-SNAPSHOT hutool-core diff --git a/hutool-core/src/main/java/cn/hutool/core/bean/BeanDesc.java b/hutool-core/src/main/java/cn/hutool/core/bean/BeanDesc.java index bdc032736..6fce559db 100644 --- a/hutool-core/src/main/java/cn/hutool/core/bean/BeanDesc.java +++ b/hutool-core/src/main/java/cn/hutool/core/bean/BeanDesc.java @@ -146,7 +146,8 @@ public class BeanDesc implements Serializable { if (false == ModifierUtil.isStatic(field)) { //只针对非static属性 prop = createProp(field, methods); - this.propMap.put(prop.getFieldName(), prop); + // 只有不存在时才放入,防止父类属性覆盖子类属性 + this.propMap.putIfAbsent(prop.getFieldName(), prop); } } return this; diff --git a/hutool-core/src/main/java/cn/hutool/core/convert/ConverterRegistry.java b/hutool-core/src/main/java/cn/hutool/core/convert/ConverterRegistry.java index 3fa034c86..fe1c55143 100644 --- a/hutool-core/src/main/java/cn/hutool/core/convert/ConverterRegistry.java +++ b/hutool-core/src/main/java/cn/hutool/core/convert/ConverterRegistry.java @@ -3,6 +3,8 @@ package cn.hutool.core.convert; import cn.hutool.core.bean.BeanUtil; import cn.hutool.core.convert.impl.ArrayConverter; import cn.hutool.core.convert.impl.AtomicBooleanConverter; +import cn.hutool.core.convert.impl.AtomicIntegerArrayConverter; +import cn.hutool.core.convert.impl.AtomicLongArrayConverter; import cn.hutool.core.convert.impl.AtomicReferenceConverter; import cn.hutool.core.convert.impl.BeanConverter; import cn.hutool.core.convert.impl.BooleanConverter; @@ -69,7 +71,9 @@ import java.util.UUID; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicInteger; +import java.util.concurrent.atomic.AtomicIntegerArray; import java.util.concurrent.atomic.AtomicLong; +import java.util.concurrent.atomic.AtomicLongArray; import java.util.concurrent.atomic.AtomicReference; /** @@ -423,6 +427,10 @@ public class ConverterRegistry implements Serializable { defaultConverterMap.put(SoftReference.class, new ReferenceConverter(SoftReference.class));// since 3.0.8 defaultConverterMap.put(AtomicReference.class, new AtomicReferenceConverter());// since 3.0.8 + //AtomicXXXArray,since 5.4.5 + defaultConverterMap.put(AtomicIntegerArray.class, new AtomicIntegerArrayConverter()); + defaultConverterMap.put(AtomicLongArray.class, new AtomicLongArrayConverter()); + // 其它类型 defaultConverterMap.put(Class.class, new ClassConverter()); defaultConverterMap.put(TimeZone.class, new TimeZoneConverter()); diff --git a/hutool-core/src/main/java/cn/hutool/core/convert/impl/AtomicIntegerArrayConverter.java b/hutool-core/src/main/java/cn/hutool/core/convert/impl/AtomicIntegerArrayConverter.java new file mode 100644 index 000000000..81b9b6c7e --- /dev/null +++ b/hutool-core/src/main/java/cn/hutool/core/convert/impl/AtomicIntegerArrayConverter.java @@ -0,0 +1,22 @@ +package cn.hutool.core.convert.impl; + +import cn.hutool.core.convert.AbstractConverter; +import cn.hutool.core.convert.Convert; + +import java.util.concurrent.atomic.AtomicIntegerArray; + +/** + * {@link AtomicIntegerArray}转换器 + * + * @author Looly + * @since 5.4.5 + */ +public class AtomicIntegerArrayConverter extends AbstractConverter { + private static final long serialVersionUID = 1L; + + @Override + protected AtomicIntegerArray convertInternal(Object value) { + return new AtomicIntegerArray(Convert.convert(int[].class, value)); + } + +} diff --git a/hutool-core/src/main/java/cn/hutool/core/convert/impl/AtomicLongArrayConverter.java b/hutool-core/src/main/java/cn/hutool/core/convert/impl/AtomicLongArrayConverter.java new file mode 100644 index 000000000..1b0d170fc --- /dev/null +++ b/hutool-core/src/main/java/cn/hutool/core/convert/impl/AtomicLongArrayConverter.java @@ -0,0 +1,22 @@ +package cn.hutool.core.convert.impl; + +import cn.hutool.core.convert.AbstractConverter; +import cn.hutool.core.convert.Convert; + +import java.util.concurrent.atomic.AtomicLongArray; + +/** + * {@link AtomicLongArray}转换器 + * + * @author Looly + * @since 5.4.5 + */ +public class AtomicLongArrayConverter extends AbstractConverter { + private static final long serialVersionUID = 1L; + + @Override + protected AtomicLongArray convertInternal(Object value) { + return new AtomicLongArray(Convert.convert(long[].class, value)); + } + +} diff --git a/hutool-core/src/main/java/cn/hutool/core/convert/impl/NumberConverter.java b/hutool-core/src/main/java/cn/hutool/core/convert/impl/NumberConverter.java index 3054e76a8..1f366f4ad 100644 --- a/hutool-core/src/main/java/cn/hutool/core/convert/impl/NumberConverter.java +++ b/hutool-core/src/main/java/cn/hutool/core/convert/impl/NumberConverter.java @@ -13,6 +13,8 @@ import java.util.Calendar; import java.util.Date; import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicLong; +import java.util.concurrent.atomic.DoubleAdder; +import java.util.concurrent.atomic.LongAdder; /** * 数字转换器
@@ -64,7 +66,6 @@ public class NumberConverter extends AbstractConverter { } final String valueStr = convertToStr(value); return StrUtil.isBlank(valueStr) ? null : Byte.valueOf(valueStr); - } else if (Short.class == targetType) { if (value instanceof Number) { return ((Number) value).shortValue(); @@ -73,7 +74,6 @@ public class NumberConverter extends AbstractConverter { } final String valueStr = convertToStr(value); return StrUtil.isBlank(valueStr) ? null : Short.valueOf(valueStr); - } else if (Integer.class == targetType) { if (value instanceof Number) { return ((Number) value).intValue(); @@ -88,7 +88,6 @@ public class NumberConverter extends AbstractConverter { } final String valueStr = convertToStr(value); return StrUtil.isBlank(valueStr) ? null : NumberUtil.parseInt(valueStr); - } else if (AtomicInteger.class == targetType) { final Number number = convertInternal(value, Integer.class); if (null != number) { @@ -96,7 +95,6 @@ public class NumberConverter extends AbstractConverter { intValue.set(number.intValue()); return intValue; } - return null; } else if (Long.class == targetType) { if (value instanceof Number) { return ((Number) value).longValue(); @@ -111,7 +109,6 @@ public class NumberConverter extends AbstractConverter { } final String valueStr = convertToStr(value); return StrUtil.isBlank(valueStr) ? null : NumberUtil.parseLong(valueStr); - } else if (AtomicLong.class == targetType) { final Number number = convertInternal(value, Long.class); if (null != number) { @@ -119,7 +116,14 @@ public class NumberConverter extends AbstractConverter { longValue.set(number.longValue()); return longValue; } - return null; + }else if (LongAdder.class == targetType) { + //jdk8 新增 + final Number number = convertInternal(value, Long.class); + if (null != number) { + final LongAdder longValue = new LongAdder(); + longValue.add(number.longValue()); + return longValue; + } } else if (Float.class == targetType) { if (value instanceof Number) { return ((Number) value).floatValue(); @@ -137,13 +141,18 @@ public class NumberConverter extends AbstractConverter { } final String valueStr = convertToStr(value); return StrUtil.isBlank(valueStr) ? null : Double.valueOf(valueStr); - + }else if (DoubleAdder.class == targetType) { + //jdk8 新增 + final Number number = convertInternal(value, Long.class); + if (null != number) { + final DoubleAdder doubleAdder = new DoubleAdder(); + doubleAdder.add(number.doubleValue()); + return doubleAdder; + } } else if (BigDecimal.class == targetType) { return toBigDecimal(value); - } else if (BigInteger.class == targetType) { return toBigInteger(value); - } else if (Number.class == targetType) { if (value instanceof Number) { return (Number) value; @@ -166,22 +175,14 @@ public class NumberConverter extends AbstractConverter { * @return 结果 */ private BigDecimal toBigDecimal(Object value) { - if (value instanceof Long) { - return new BigDecimal((Long) value); - } else if (value instanceof Integer) { - return new BigDecimal((Integer) value); - } else if (value instanceof BigInteger) { - return new BigDecimal((BigInteger) value); + if (value instanceof Number) { + return NumberUtil.toBigDecimal((Number) value); } else if (value instanceof Boolean) { return new BigDecimal((boolean) value ? 1 : 0); } //对于Double类型,先要转换为String,避免精度问题 - final String valueStr = convertToStr(value); - if (StrUtil.isBlank(valueStr)) { - return null; - } - return new BigDecimal(valueStr); + return NumberUtil.toBigDecimal(convertToStr(value)); } /** @@ -198,11 +199,8 @@ public class NumberConverter extends AbstractConverter { } else if (value instanceof Boolean) { return BigInteger.valueOf((boolean) value ? 1 : 0); } - final String valueStr = convertToStr(value); - if (StrUtil.isBlank(valueStr)) { - return null; - } - return new BigInteger(valueStr); + + return NumberUtil.toBigInteger(convertToStr(value)); } @Override diff --git a/hutool-core/src/main/java/cn/hutool/core/convert/impl/StringConverter.java b/hutool-core/src/main/java/cn/hutool/core/convert/impl/StringConverter.java index f1a49e749..91f2ac830 100644 --- a/hutool-core/src/main/java/cn/hutool/core/convert/impl/StringConverter.java +++ b/hutool-core/src/main/java/cn/hutool/core/convert/impl/StringConverter.java @@ -1,18 +1,77 @@ package cn.hutool.core.convert.impl; import cn.hutool.core.convert.AbstractConverter; +import cn.hutool.core.convert.ConvertException; +import cn.hutool.core.io.IoUtil; +import cn.hutool.core.util.CharsetUtil; +import cn.hutool.core.util.XmlUtil; + +import java.io.InputStream; +import java.io.Reader; +import java.sql.Blob; +import java.sql.Clob; +import java.sql.SQLException; +import java.util.TimeZone; /** - * 字符串转换器 - * @author Looly + * 字符串转换器,提供各种对象转换为字符串的逻辑封装 * + * @author Looly */ -public class StringConverter extends AbstractConverter{ +public class StringConverter extends AbstractConverter { private static final long serialVersionUID = 1L; @Override protected String convertInternal(Object value) { + if (value instanceof TimeZone) { + return ((TimeZone) value).getID(); + } else if (value instanceof org.w3c.dom.Node) { + return XmlUtil.toStr((org.w3c.dom.Node) value); + } else if (value instanceof Clob) { + return clobToStr((Clob) value); + } else if (value instanceof Blob) { + return blobToStr((Blob) value); + } + + // 其它情况 return convertToStr(value); } + /** + * Clob字段值转字符串 + * + * @param clob {@link Clob} + * @return 字符串 + * @since 5.4.5 + */ + private static String clobToStr(Clob clob) { + Reader reader = null; + try { + reader = clob.getCharacterStream(); + return IoUtil.read(reader); + } catch (SQLException e) { + throw new ConvertException(e); + } finally { + IoUtil.close(reader); + } + } + + /** + * Blob字段值转字符串 + * + * @param blob {@link Blob} + * @return 字符串 + * @since 5.4.5 + */ + private static String blobToStr(Blob blob) { + InputStream in = null; + try { + in = blob.getBinaryStream(); + return IoUtil.read(in, CharsetUtil.CHARSET_UTF_8); + } catch (SQLException e) { + throw new ConvertException(e); + } finally { + IoUtil.close(in); + } + } } diff --git a/hutool-core/src/main/java/cn/hutool/core/date/ChineseDate.java b/hutool-core/src/main/java/cn/hutool/core/date/ChineseDate.java index 368cd302d..e6166d318 100644 --- a/hutool-core/src/main/java/cn/hutool/core/date/ChineseDate.java +++ b/hutool-core/src/main/java/cn/hutool/core/date/ChineseDate.java @@ -21,7 +21,9 @@ public class ChineseDate { /** * 1900-01-31 */ - private static final long BASE_DATE = -2206425943000L; +// private static final long BASE_DATE = -2206425943000L; + private static final long BASE_DAY = -25538; + //农历年 private final int year; //农历月 @@ -46,13 +48,12 @@ public class ChineseDate { */ public ChineseDate(Date date) { // 求出和1900年1月31日相差的天数 - int offset = (int) ((date.getTime() - BASE_DATE) / DateUnit.DAY.getMillis()); + int offset = (int) ((DateUtil.beginOfDay(date).getTime() / DateUnit.DAY.getMillis()) - BASE_DAY); // 计算农历年份 // 用offset减去每农历年的天数,计算当天是农历第几天,offset是当年的第几天 int daysOfYear; int iYear = LunarInfo.BASE_YEAR; - final int maxYear = LunarInfo.getMaxYear(); - for (; iYear <= maxYear; iYear++) { + for (; iYear <= LunarInfo.MAX_YEAR; iYear++) { daysOfYear = LunarInfo.yearDays(iYear); if (offset < daysOfYear) { break; @@ -299,7 +300,7 @@ public class ChineseDate { if (D >= firstNode) { gzM = GanZhi.cyclicalm((Y - LunarInfo.BASE_YEAR) * 12 + M + 12); } - int dayCyclical = (int) ((DateUtil.parseDate(Y + "-" + M + "-" + "1").getTime() - BASE_DATE + 2592000000L) / DateUnit.DAY.getMillis()) + 10; + int dayCyclical = (int) ((DateUtil.parseDate(Y + "-" + M + "-" + "1").getTime() / DateUnit.DAY.getMillis() - BASE_DAY + 30)) + 10; String gzD = GanZhi.cyclicalm(dayCyclical + D - 1); return gzyear + "年" + gzM + "月" + gzD + "日"; } diff --git a/hutool-core/src/main/java/cn/hutool/core/date/DateBetween.java b/hutool-core/src/main/java/cn/hutool/core/date/DateBetween.java index a190f5131..7a28fb572 100644 --- a/hutool-core/src/main/java/cn/hutool/core/date/DateBetween.java +++ b/hutool-core/src/main/java/cn/hutool/core/date/DateBetween.java @@ -26,7 +26,7 @@ public class DateBetween implements Serializable{ * * @param begin 起始时间 * @param end 结束时间 - * @return {@link DateBetween} + * @return DateBetween * @since 3.2.3 */ public static DateBetween create(Date begin, Date end) { @@ -40,7 +40,7 @@ public class DateBetween implements Serializable{ * @param begin 起始时间 * @param end 结束时间 * @param isAbs 日期间隔是否只保留绝对值正数 - * @return {@link DateBetween} + * @return DateBetween * @since 3.2.3 */ public static DateBetween create(Date begin, Date end, boolean isAbs) { diff --git a/hutool-core/src/main/java/cn/hutool/core/date/DateUnit.java b/hutool-core/src/main/java/cn/hutool/core/date/DateUnit.java index 2f2a58544..019678a96 100644 --- a/hutool-core/src/main/java/cn/hutool/core/date/DateUnit.java +++ b/hutool-core/src/main/java/cn/hutool/core/date/DateUnit.java @@ -1,33 +1,108 @@ package cn.hutool.core.date; +import java.time.temporal.ChronoUnit; + /** * 日期时间单位,每个单位都是以毫秒为基数 - * @author Looly * + * @author Looly */ public enum DateUnit { - /** 一毫秒 */ - MS(1), - /** 一秒的毫秒数 */ - SECOND(1000), - /**一分钟的毫秒数 */ + /** + * 一毫秒 + */ + MS(1), + /** + * 一秒的毫秒数 + */ + SECOND(1000), + /** + * 一分钟的毫秒数 + */ MINUTE(SECOND.getMillis() * 60), - /**一小时的毫秒数 */ + /** + * 一小时的毫秒数 + */ HOUR(MINUTE.getMillis() * 60), - /**一天的毫秒数 */ + /** + * 一天的毫秒数 + */ DAY(HOUR.getMillis() * 24), - /**一周的毫秒数 */ + /** + * 一周的毫秒数 + */ WEEK(DAY.getMillis() * 7); - + private final long millis; - DateUnit(long millis){ + + DateUnit(long millis) { this.millis = millis; } - + /** * @return 单位对应的毫秒数 */ - public long getMillis(){ + public long getMillis() { return this.millis; } + + /** + * 单位兼容转换,将DateUnit转换为对应的{@link ChronoUnit} + * + * @return {@link ChronoUnit} + * @since 5.4.5 + */ + public ChronoUnit toChronoUnit() { + return DateUnit.toChronoUnit(this); + } + + /** + * 单位兼容转换,将{@link ChronoUnit}转换为对应的DateUnit + * + * @param unit {@link ChronoUnit} + * @return DateUnit,null表示不支持此单位 + * @since 5.4.5 + */ + public static DateUnit of(ChronoUnit unit) { + switch (unit) { + case MICROS: + return DateUnit.MS; + case SECONDS: + return DateUnit.SECOND; + case MINUTES: + return DateUnit.MINUTE; + case HOURS: + return DateUnit.HOUR; + case DAYS: + return DateUnit.DAY; + case WEEKS: + return DateUnit.WEEK; + } + return null; + } + + /** + * 单位兼容转换,将DateUnit转换为对应的{@link ChronoUnit} + * + * @param unit DateUnit + * @return {@link ChronoUnit} + * @since 5.4.5 + */ + public static ChronoUnit toChronoUnit(DateUnit unit) { + switch (unit) { + case MS: + return ChronoUnit.MICROS; + case SECOND: + return ChronoUnit.SECONDS; + case MINUTE: + return ChronoUnit.MINUTES; + case HOUR: + return ChronoUnit.HOURS; + case DAY: + return ChronoUnit.DAYS; + case WEEK: + return ChronoUnit.WEEKS; + } + return null; + } } diff --git a/hutool-core/src/main/java/cn/hutool/core/date/LocalDateTimeUtil.java b/hutool-core/src/main/java/cn/hutool/core/date/LocalDateTimeUtil.java index a1745440f..ba08a2cc2 100644 --- a/hutool-core/src/main/java/cn/hutool/core/date/LocalDateTimeUtil.java +++ b/hutool-core/src/main/java/cn/hutool/core/date/LocalDateTimeUtil.java @@ -9,11 +9,14 @@ import java.time.Instant; import java.time.LocalDate; import java.time.LocalDateTime; import java.time.LocalTime; +import java.time.Period; import java.time.ZoneId; import java.time.ZonedDateTime; import java.time.format.DateTimeFormatter; import java.time.format.DateTimeFormatterBuilder; import java.time.temporal.ChronoField; +import java.time.temporal.ChronoUnit; +import java.time.temporal.Temporal; import java.time.temporal.TemporalAccessor; import java.time.temporal.TemporalUnit; import java.util.Date; @@ -412,14 +415,43 @@ public class LocalDateTimeUtil { *

* 返回结果为{@link Duration}对象,通过调用toXXX方法返回相差单位 * - * @param startTime 开始时间 - * @param endTime 结束时间 + * @param startTimeInclude 开始时间(包含) + * @param endTimeExclude 结束时间(不包含) * @return 时间差 {@link Duration}对象 + * @see TemporalUtil#between(Temporal, Temporal) */ - public static Duration between(LocalDateTime startTime, LocalDateTime endTime) { - return Duration.between(startTime, endTime); + public static Duration between(LocalDateTime startTimeInclude, LocalDateTime endTimeExclude) { + return TemporalUtil.between(startTimeInclude, endTimeExclude); } + /** + * 获取两个日期的差,如果结束时间早于开始时间,获取结果为负。 + *

+ * 返回结果为时间差的long值 + * + * @param startTimeInclude 开始时间(包括) + * @param endTimeExclude 结束时间(不包括) + * @param unit 时间差单位 + * @return 时间差 + * @since 5.4.5 + */ + public static long between(LocalDateTime startTimeInclude, LocalDateTime endTimeExclude, ChronoUnit unit) { + return TemporalUtil.between(startTimeInclude, endTimeExclude, unit); + } + + /** + * 获取两个日期的表象时间差,如果结束时间早于开始时间,获取结果为负。 + *

+ * 比如2011年2月1日,和2021年8月11日,日相差了10天,月相差6月 + * + * @param startTimeInclude 开始时间(包括) + * @param endTimeExclude 结束时间(不包括) + * @return 时间差 + * @since 5.4.5 + */ + public static Period betweenPeriod(LocalDate startTimeInclude, LocalDate endTimeExclude) { + return Period.between(startTimeInclude, endTimeExclude); + } /** * 修改为一天的开始时间,例如:2020-02-02 00:00:00,000 diff --git a/hutool-core/src/main/java/cn/hutool/core/date/TemporalAccessorUtil.java b/hutool-core/src/main/java/cn/hutool/core/date/TemporalAccessorUtil.java index d666301cb..3ecb8a5af 100644 --- a/hutool-core/src/main/java/cn/hutool/core/date/TemporalAccessorUtil.java +++ b/hutool-core/src/main/java/cn/hutool/core/date/TemporalAccessorUtil.java @@ -20,7 +20,7 @@ import java.time.temporal.TemporalField; * @author looly * @since 5.3.9 */ -public class TemporalAccessorUtil { +public class TemporalAccessorUtil extends TemporalUtil{ /** * 安全获取时间的某个属性,属性不存在返回0 diff --git a/hutool-core/src/main/java/cn/hutool/core/date/TemporalUtil.java b/hutool-core/src/main/java/cn/hutool/core/date/TemporalUtil.java new file mode 100644 index 000000000..cd62f4e39 --- /dev/null +++ b/hutool-core/src/main/java/cn/hutool/core/date/TemporalUtil.java @@ -0,0 +1,41 @@ +package cn.hutool.core.date; + +import java.time.Duration; +import java.time.temporal.ChronoUnit; +import java.time.temporal.Temporal; + +/** + * {@link Temporal} 工具类封装 + * + * @author looly + * @since 5.4.5 + */ +public class TemporalUtil { + + /** + * 获取两个日期的差,如果结束时间早于开始时间,获取结果为负。 + *

+ * 返回结果为{@link Duration}对象,通过调用toXXX方法返回相差单位 + * + * @param startTimeInclude 开始时间(包含) + * @param endTimeExclude 结束时间(不包含) + * @return 时间差 {@link Duration}对象 + */ + public static Duration between(Temporal startTimeInclude, Temporal endTimeExclude) { + return Duration.between(startTimeInclude, endTimeExclude); + } + + /** + * 获取两个日期的差,如果结束时间早于开始时间,获取结果为负。 + *

+ * 返回结果为时间差的long值 + * + * @param startTimeInclude 开始时间(包括) + * @param endTimeExclude 结束时间(不包括) + * @param unit 时间差单位 + * @return 时间差 + */ + public static long between(Temporal startTimeInclude, Temporal endTimeExclude, ChronoUnit unit) { + return unit.between(startTimeInclude, endTimeExclude); + } +} diff --git a/hutool-core/src/main/java/cn/hutool/core/date/chinese/LunarInfo.java b/hutool-core/src/main/java/cn/hutool/core/date/chinese/LunarInfo.java index a088d0c05..12863a4b6 100644 --- a/hutool-core/src/main/java/cn/hutool/core/date/chinese/LunarInfo.java +++ b/hutool-core/src/main/java/cn/hutool/core/date/chinese/LunarInfo.java @@ -40,13 +40,18 @@ public class LunarInfo { 0x0e968, 0x0d520, 0x0daa0, 0x16aa6, 0x056d0, 0x04ae0, 0x0a9d4, 0x0a2d0, 0x0d150, 0x0f252,//2090-2099 }; + // 支持的最大年限 + public static final int MAX_YEAR = BASE_YEAR + LUNAR_CODE.length - 1; + /** * 获取支持的最大年(包括) * * @return 最大年(包括) + * @deprecated 使用 {@link #MAX_YEAR} */ + @Deprecated public static int getMaxYear() { - return BASE_YEAR + LUNAR_CODE.length - 1; + return MAX_YEAR; } /** diff --git a/hutool-core/src/main/java/cn/hutool/core/io/FileUtil.java b/hutool-core/src/main/java/cn/hutool/core/io/FileUtil.java index 6b3db398a..f7a76de1d 100644 --- a/hutool-core/src/main/java/cn/hutool/core/io/FileUtil.java +++ b/hutool-core/src/main/java/cn/hutool/core/io/FileUtil.java @@ -862,7 +862,7 @@ public class FileUtil extends PathUtil { */ public static File copyFile(String src, String dest, StandardCopyOption... options) throws IORuntimeException { Assert.notBlank(src, "Source File path is blank !"); - Assert.notNull(src, "Destination File path is null !"); + Assert.notBlank(dest, "Destination File path is blank !"); return copyFile(Paths.get(src), Paths.get(dest), options).toFile(); } diff --git a/hutool-core/src/main/java/cn/hutool/core/lang/Assert.java b/hutool-core/src/main/java/cn/hutool/core/lang/Assert.java index c3137e67a..69557d274 100644 --- a/hutool-core/src/main/java/cn/hutool/core/lang/Assert.java +++ b/hutool-core/src/main/java/cn/hutool/core/lang/Assert.java @@ -68,7 +68,7 @@ public class Assert { * 断言是否为假,如果为 {@code true} 抛出指定类型异常
* 并使用指定的函数获取错误信息返回 *

-	 *  Assert.isFalse(i > 0, ()->{
+	 *  Assert.isFalse(i > 0, ()->{
 	 *      // to query relation message
 	 *      return new IllegalArgumentException("relation message to return");
 	 *  });
@@ -120,7 +120,7 @@ public class Assert {
 	 * 断言对象是否为{@code null} ,如果不为{@code null} 抛出指定类型异常
 	 * 并使用指定的函数获取错误信息返回
 	 * 
-	 * Assert.isNull(value, ()->{
+	 * Assert.isNull(value, ()->{
 	 *      // to query relation message
 	 *      return new IllegalArgumentException("relation message to return");
 	 *  });
@@ -174,7 +174,7 @@ public class Assert {
 	 * 断言对象是否不为{@code null} ,如果为{@code null} 抛出指定类型异常
 	 * 并使用指定的函数获取错误信息返回
 	 * 
-	 * Assert.notNull(clazz, ()->{
+	 * Assert.notNull(clazz, ()->{
 	 *      // to query relation message
 	 *      return new IllegalArgumentException("relation message to return");
 	 *  });
@@ -234,7 +234,7 @@ public class Assert {
 	/**
 	 * 检查给定字符串是否为空,为空抛出自定义异常,并使用指定的函数获取错误信息返回。
 	 * 
-	 * Assert.notEmpty(name, ()->{
+	 * Assert.notEmpty(name, ()->{
 	 *      // to query relation message
 	 *      return new IllegalArgumentException("relation message to return");
 	 *  });
@@ -296,7 +296,7 @@ public class Assert {
 	 * 检查给定字符串是否为空白(null、空串或只包含空白符),为空抛出自定义异常。
 	 * 并使用指定的函数获取错误信息返回
 	 * 
-	 * Assert.notBlank(name, ()->{
+	 * Assert.notBlank(name, ()->{
 	 *      // to query relation message
 	 *      return new IllegalArgumentException("relation message to return");
 	 *  });
@@ -357,7 +357,7 @@ public class Assert {
 	 * 断言给定字符串是否不被另一个字符串包含(即是否为子串)
 	 * 并使用指定的函数获取错误信息返回
 	 * 
-	 * Assert.notContain(name, "rod", ()->{
+	 * Assert.notContain(name, "rod", ()->{
 	 *      // to query relation message
 	 *      return new IllegalArgumentException("relation message to return ");
 	 *  });
@@ -419,7 +419,7 @@ public class Assert {
 	 * 并使用指定的函数获取错误信息返回
 	 *
 	 * 
-	 * Assert.notEmpty(array, ()->{
+	 * Assert.notEmpty(array, ()->{
 	 *      // to query relation message
 	 *      return new IllegalArgumentException("relation message to return");
 	 *  });
@@ -479,7 +479,7 @@ public class Assert {
 	 * 断言给定数组是否不包含{@code null}元素,如果数组为空或 {@code null}将被认为不包含
 	 * 并使用指定的函数获取错误信息返回
 	 * 
-	 * Assert.noNullElements(array, ()->{
+	 * Assert.noNullElements(array, ()->{
 	 *      // to query relation message
 	 *      return new IllegalArgumentException("relation message to return ");
 	 *  });
@@ -538,7 +538,7 @@ public class Assert {
 	 * 断言给定集合非空
 	 * 并使用指定的函数获取错误信息返回
 	 * 
-	 * Assert.notEmpty(collection, ()->{
+	 * Assert.notEmpty(collection, ()->{
 	 *      // to query relation message
 	 *      return new IllegalArgumentException("relation message to return");
 	 *  });
@@ -601,7 +601,7 @@ public class Assert {
 	 * 断言给定Map非空
 	 * 并使用指定的函数获取错误信息返回
 	 * 
-	 * Assert.notEmpty(map, ()->{
+	 * Assert.notEmpty(map, ()->{
 	 *      // to query relation message
 	 *      return new IllegalArgumentException("relation message to return");
 	 *  });
@@ -744,7 +744,7 @@ public class Assert {
 	 * 检查boolean表达式,当检查结果为false时抛出 {@code IllegalStateException}。
 	 * 并使用指定的函数获取错误信息返回
 	 * 
-	 * Assert.state(id == null, ()->{
+	 * Assert.state(id == null, ()->{
 	 *      // to query relation message
 	 *      return "relation message to return ";
 	 *  });
diff --git a/hutool-core/src/main/java/cn/hutool/core/util/NumberUtil.java b/hutool-core/src/main/java/cn/hutool/core/util/NumberUtil.java
index 737f7347d..120d32f39 100644
--- a/hutool-core/src/main/java/cn/hutool/core/util/NumberUtil.java
+++ b/hutool-core/src/main/java/cn/hutool/core/util/NumberUtil.java
@@ -1967,20 +1967,20 @@ public class NumberUtil {
 
 	/**
 	 * 数字转字符串
- * 调用{@link Number#toString()},并去除尾小数点儿后多余的0 + * 调用{@link Number#toString()}或 {@link BigDecimal#toPlainString()},并去除尾小数点儿后多余的0 * * @param number A Number * @return A String. */ public static String toStr(Number number) { - if (null == number) { - throw new NullPointerException("Number is null !"); - } - - if (false == ObjectUtil.isValidIfNumber(number)) { - throw new IllegalArgumentException("Number is non-finite!"); + Assert.notNull(number, "Number is null !"); + + // BigDecimal单独处理,使用非科学计数法 + if(number instanceof BigDecimal){ + return toStr((BigDecimal)number); } + Assert.isTrue(isValidNumber(number), "Number is non-finite!"); // 去掉小数点儿后多余的0 String string = number.toString(); if (string.indexOf('.') > 0 && string.indexOf('e') < 0 && string.indexOf('E') < 0) { @@ -1994,6 +1994,19 @@ public class NumberUtil { return string; } + /** + * {@link BigDecimal}数字转字符串
+ * 调用{@link BigDecimal#toPlainString()},并去除尾小数点儿后多余的0 + * + * @param bigDecimal A {@link BigDecimal} + * @return A String. + * @since 5.4.6 + */ + public static String toStr(BigDecimal bigDecimal) { + Assert.notNull(bigDecimal, "BigDecimal is null !"); + return bigDecimal.stripTrailingZeros().toPlainString(); + } + /** * 数字转{@link BigDecimal} * @@ -2005,6 +2018,17 @@ public class NumberUtil { if (null == number) { return BigDecimal.ZERO; } + + if(number instanceof BigDecimal){ + return (BigDecimal) number; + } else if (number instanceof Long) { + return new BigDecimal((Long) number); + } else if (number instanceof Integer) { + return new BigDecimal((Integer) number); + } else if (number instanceof BigInteger) { + return new BigDecimal((BigInteger) number); + } + return toBigDecimal(number.toString()); } @@ -2019,6 +2043,38 @@ public class NumberUtil { return (null == number) ? BigDecimal.ZERO : new BigDecimal(number); } + /** + * 数字转{@link BigInteger} + * + * @param number 数字 + * @return {@link BigInteger} + * @since 5.4.5 + */ + public static BigInteger toBigInteger(Number number) { + if (null == number) { + return BigInteger.ZERO; + } + + if(number instanceof BigInteger){ + return (BigInteger) number; + } else if (number instanceof Long) { + return BigInteger.valueOf((Long) number); + } + + return toBigInteger(number.longValue()); + } + + /** + * 数字转{@link BigInteger} + * + * @param number 数字 + * @return {@link BigInteger} + * @since 5.4.5 + */ + public static BigInteger toBigInteger(String number) { + return (null == number) ? BigInteger.ZERO : new BigInteger(number); + } + /** * 是否空白符
* 空白符包括空格、制表符、全角空格和不间断空格
diff --git a/hutool-core/src/main/java/cn/hutool/core/util/ReflectUtil.java b/hutool-core/src/main/java/cn/hutool/core/util/ReflectUtil.java index 222eb936e..faa4000ca 100644 --- a/hutool-core/src/main/java/cn/hutool/core/util/ReflectUtil.java +++ b/hutool-core/src/main/java/cn/hutool/core/util/ReflectUtil.java @@ -139,7 +139,7 @@ public class ReflectUtil { } /** - * 查找指定类中的所有字段(包括非public字段),也包括父类和Object类的字段, 字段不存在则返回null + * 查找指定类中的指定name的字段(包括非public字段),也包括父类和Object类的字段, 字段不存在则返回null * * @param beanClass 被查找字段的类,不能为null * @param name 字段名 @@ -148,26 +148,20 @@ public class ReflectUtil { */ public static Field getField(Class beanClass, String name) throws SecurityException { final Field[] fields = getFields(beanClass); - if (ArrayUtil.isNotEmpty(fields)) { - for (Field field : fields) { - if ((name.equals(getFieldName(field)))) { - return field; - } - } - } - return null; + return ArrayUtil.firstMatch((field)->name.equals(getFieldName(field)), fields); } /** - * 获取指定类中字段名和字段对应的Map,包括其父类中的字段 + * 获取指定类中字段名和字段对应的有序Map,包括其父类中的字段
+ * 如果子类与父类中存在同名字段,则这两个字段同时存在,子类字段在前,父类字段在后。 * * @param beanClass 类 - * @return 字段名和字段对应的Map + * @return 字段名和字段对应的Map,有序 * @since 5.0.7 */ public static Map getFieldMap(Class beanClass) { final Field[] fields = getFields(beanClass); - final HashMap map = MapUtil.newHashMap(fields.length); + final HashMap map = MapUtil.newHashMap(fields.length, true); for (Field field : fields) { map.put(field.getName(), field); } @@ -175,7 +169,8 @@ public class ReflectUtil { } /** - * 获得一个类中所有字段列表,包括其父类中的字段 + * 获得一个类中所有字段列表,包括其父类中的字段
+ * 如果子类与父类中存在同名字段,则这两个字段同时存在,子类字段在前,父类字段在后。 * * @param beanClass 类 * @return 字段列表 @@ -192,14 +187,15 @@ public class ReflectUtil { } /** - * 获得一个类中所有字段列表,直接反射获取,无缓存 + * 获得一个类中所有字段列表,直接反射获取,无缓存
+ * 如果子类与父类中存在同名字段,则这两个字段同时存在,子类字段在前,父类字段在后。 * * @param beanClass 类 - * @param withSuperClassFieds 是否包括父类的字段列表 + * @param withSuperClassFields 是否包括父类的字段列表 * @return 字段列表 * @throws SecurityException 安全检查异常 */ - public static Field[] getFieldsDirectly(Class beanClass, boolean withSuperClassFieds) throws SecurityException { + public static Field[] getFieldsDirectly(Class beanClass, boolean withSuperClassFields) throws SecurityException { Assert.notNull(beanClass); Field[] allFields = null; @@ -212,7 +208,7 @@ public class ReflectUtil { } else { allFields = ArrayUtil.append(allFields, declaredFields); } - searchType = withSuperClassFieds ? searchType.getSuperclass() : null; + searchType = withSuperClassFields ? searchType.getSuperclass() : null; } return allFields; diff --git a/hutool-core/src/main/java/cn/hutool/core/util/XmlUtil.java b/hutool-core/src/main/java/cn/hutool/core/util/XmlUtil.java index e7162eb4f..eb0e34ea8 100644 --- a/hutool-core/src/main/java/cn/hutool/core/util/XmlUtil.java +++ b/hutool-core/src/main/java/cn/hutool/core/util/XmlUtil.java @@ -345,6 +345,19 @@ public class XmlUtil { // -------------------------------------------------------------------------------------- Write + /** + * 将XML文档转换为String
+ * 字符编码使用XML文档中的编码,获取不到则使用UTF-8
+ * 默认非格式化输出,若想格式化请使用{@link #format(Document)} + * + * @param doc XML文档 + * @return XML字符串 + * @since 5.4.5 + */ + public static String toStr(Node doc) { + return toStr(doc, false); + } + /** * 将XML文档转换为String
* 字符编码使用XML文档中的编码,获取不到则使用UTF-8
@@ -354,7 +367,20 @@ public class XmlUtil { * @return XML字符串 */ public static String toStr(Document doc) { - return toStr(doc, false); + return toStr((Node)doc); + } + + /** + * 将XML文档转换为String
+ * 字符编码使用XML文档中的编码,获取不到则使用UTF-8 + * + * @param doc XML文档 + * @param isPretty 是否格式化输出 + * @return XML字符串 + * @since 5.4.5 + */ + public static String toStr(Node doc, boolean isPretty) { + return toStr(doc, CharsetUtil.UTF_8, isPretty); } /** @@ -367,7 +393,21 @@ public class XmlUtil { * @since 3.0.9 */ public static String toStr(Document doc, boolean isPretty) { - return toStr(doc, CharsetUtil.UTF_8, isPretty); + return toStr((Node)doc, isPretty); + } + + /** + * 将XML文档转换为String
+ * 字符编码使用XML文档中的编码,获取不到则使用UTF-8 + * + * @param doc XML文档 + * @param charset 编码 + * @param isPretty 是否格式化输出 + * @return XML字符串 + * @since 5.4.5 + */ + public static String toStr(Node doc, String charset, boolean isPretty) { + return toStr(doc, charset, isPretty, false); } /** @@ -381,7 +421,7 @@ public class XmlUtil { * @since 3.0.9 */ public static String toStr(Document doc, String charset, boolean isPretty) { - return toStr(doc, charset, isPretty, false); + return toStr((Node)doc, charset, isPretty); } /** @@ -395,7 +435,7 @@ public class XmlUtil { * @return XML字符串 * @since 5.1.2 */ - public static String toStr(Document doc, String charset, boolean isPretty, boolean omitXmlDeclaration) { + public static String toStr(Node doc, String charset, boolean isPretty, boolean omitXmlDeclaration) { final StringWriter writer = StrUtil.getWriter(); try { write(doc, writer, charset, isPretty ? INDENT_DEFAULT : 0, omitXmlDeclaration); diff --git a/hutool-core/src/test/java/cn/hutool/core/bean/BeanUtilTest.java b/hutool-core/src/test/java/cn/hutool/core/bean/BeanUtilTest.java index 16284002e..a74683f05 100644 --- a/hutool-core/src/test/java/cn/hutool/core/bean/BeanUtilTest.java +++ b/hutool-core/src/test/java/cn/hutool/core/bean/BeanUtilTest.java @@ -364,12 +364,26 @@ public class BeanUtilTest { @Getter @Setter - public static class Person { + public static class SubPersonWithOverlayTransientField extends PersonWithTransientField { + // 覆盖父类中 transient 属性 private String name; + } + + @Getter + @Setter + public static class Person { + private String name; private int age; private String openid; } + @Getter + @Setter + public static class PersonWithTransientField { + private transient String name; + private int age; + private String openid; + } public static class Person2 { public Person2(String name, int age, String openid) { @@ -383,6 +397,23 @@ public class BeanUtilTest { public String openid; } + /** + * #1173 + */ + @Test + public void beanToBeanOverlayFieldTest() { + SubPersonWithOverlayTransientField source = new SubPersonWithOverlayTransientField(); + source.setName("zhangsan"); + source.setAge(20); + source.setOpenid("1"); + SubPersonWithOverlayTransientField dest = new SubPersonWithOverlayTransientField(); + BeanUtil.copyProperties(source, dest); + + Assert.assertEquals(source.getName(), dest.getName()); + Assert.assertEquals(source.getAge(), dest.getAge()); + Assert.assertEquals(source.getOpenid(), dest.getOpenid()); + } + @Test public void beanToBeanTest() { // 修复对象无getter方法导致报错的问题 @@ -434,6 +465,8 @@ public class BeanUtilTest { @Data public static class HllFoodEntity implements Serializable { + private static final long serialVersionUID = 1L; + private String bookId; @Alias("code") private String code2; diff --git a/hutool-core/src/test/java/cn/hutool/core/convert/ConvertTest.java b/hutool-core/src/test/java/cn/hutool/core/convert/ConvertTest.java index 52d063af0..43d5bd5f6 100644 --- a/hutool-core/src/test/java/cn/hutool/core/convert/ConvertTest.java +++ b/hutool-core/src/test/java/cn/hutool/core/convert/ConvertTest.java @@ -9,6 +9,8 @@ import java.io.Serializable; import java.util.ArrayList; import java.util.Arrays; import java.util.List; +import java.util.concurrent.atomic.AtomicIntegerArray; +import java.util.concurrent.atomic.AtomicLongArray; /** * 类型转换工具单元测试 @@ -222,6 +224,20 @@ public class ConvertTest { Assert.assertEquals("5.1.1", product.getVersion()); } + @Test + public void toAtomicIntegerArrayTest(){ + String str = "1,2"; + final AtomicIntegerArray atomicIntegerArray = Convert.convert(AtomicIntegerArray.class, str); + Assert.assertEquals("[1, 2]", atomicIntegerArray.toString()); + } + + @Test + public void toAtomicLongArrayTest(){ + String str = "1,2"; + final AtomicLongArray atomicLongArray = Convert.convert(AtomicLongArray.class, str); + Assert.assertEquals("[1, 2]", atomicLongArray.toString()); + } + @Data @AllArgsConstructor public static class Product implements Serializable { diff --git a/hutool-core/src/test/java/cn/hutool/core/convert/StringConvertTest.java b/hutool-core/src/test/java/cn/hutool/core/convert/StringConvertTest.java new file mode 100644 index 000000000..aeed15190 --- /dev/null +++ b/hutool-core/src/test/java/cn/hutool/core/convert/StringConvertTest.java @@ -0,0 +1,15 @@ +package cn.hutool.core.convert; + +import org.junit.Assert; +import org.junit.Test; + +import java.util.TimeZone; + +public class StringConvertTest { + + @Test + public void timezoneToStrTest(){ + final String s = Convert.toStr(TimeZone.getTimeZone("Asia/Shanghai")); + Assert.assertEquals("Asia/Shanghai", s); + } +} diff --git a/hutool-core/src/test/java/cn/hutool/core/date/ChineseDateTest.java b/hutool-core/src/test/java/cn/hutool/core/date/ChineseDateTest.java index 877064d84..1792fd4ff 100644 --- a/hutool-core/src/test/java/cn/hutool/core/date/ChineseDateTest.java +++ b/hutool-core/src/test/java/cn/hutool/core/date/ChineseDateTest.java @@ -85,4 +85,20 @@ public class ChineseDateTest { ChineseDate chineseDate = new ChineseDate(DateUtil.parseDate("2023-01-20")); Assert.assertTrue(StrUtil.isEmpty(chineseDate.getFestivals())); } + + @Test + public void dateTest(){ + // 修复这两个日期不正确的问题 + // 问题出在计算与1900-01-31相差天数的问题上了,相差天数非整天 + ChineseDate date = new ChineseDate(DateUtil.parseDate("1991-09-14")); + Assert.assertEquals("辛未羊年 八月初七", date.toString()); + date = new ChineseDate(DateUtil.parseDate("1991-09-15")); + Assert.assertEquals("辛未羊年 八月初八", date.toString()); + } + + @Test + public void dateTest2(){ + ChineseDate date = new ChineseDate(DateUtil.parse("2020-10-19 11:12:23")); + Assert.assertEquals("庚子鼠年 九月初三", date.toString()); + } } diff --git a/hutool-core/src/test/java/cn/hutool/core/net/UrlBuilderTest.java b/hutool-core/src/test/java/cn/hutool/core/net/UrlBuilderTest.java index fc861f3fe..fe1b95f47 100644 --- a/hutool-core/src/test/java/cn/hutool/core/net/UrlBuilderTest.java +++ b/hutool-core/src/test/java/cn/hutool/core/net/UrlBuilderTest.java @@ -204,4 +204,10 @@ public class UrlBuilderTest { final UrlBuilder urlBuilder = UrlBuilder.ofHttp("http://a.com/aaa bbb.html", CharsetUtil.CHARSET_UTF_8); Assert.assertEquals("http://a.com/aaa%20bbb.html", urlBuilder.toString()); } + + @Test + public void dotEncodeTest(){ + final UrlBuilder urlBuilder = UrlBuilder.ofHttp("http://xtbgyy.digitalgd.com.cn/ebus/../../..", CharsetUtil.CHARSET_UTF_8); + Assert.assertEquals("http://xtbgyy.digitalgd.com.cn/ebus/../../..", urlBuilder.toString()); + } } diff --git a/hutool-core/src/test/java/cn/hutool/core/util/NumberUtilTest.java b/hutool-core/src/test/java/cn/hutool/core/util/NumberUtilTest.java index 8891b4986..10584a2a8 100644 --- a/hutool-core/src/test/java/cn/hutool/core/util/NumberUtilTest.java +++ b/hutool-core/src/test/java/cn/hutool/core/util/NumberUtilTest.java @@ -279,4 +279,12 @@ public class NumberUtilTest { final Set set = Convert.convert(Set.class, ints); Assert.assertEquals(5, set.size()); } + + @Test + public void toStrTest(){ + Assert.assertEquals("1", NumberUtil.toStr(new BigDecimal("1.0000000000"))); + Assert.assertEquals("0", NumberUtil.toStr(NumberUtil.sub(new BigDecimal("9600.00000"), new BigDecimal("9600.00000")))); + Assert.assertEquals("0", NumberUtil.toStr(NumberUtil.sub(new BigDecimal("9600.0000000000"), new BigDecimal("9600.000000")))); + Assert.assertEquals("0", NumberUtil.toStr(new BigDecimal("9600.00000").subtract(new BigDecimal("9600.000000000")))); + } } diff --git a/hutool-cron/pom.xml b/hutool-cron/pom.xml index f4f0368c7..967030a24 100644 --- a/hutool-cron/pom.xml +++ b/hutool-cron/pom.xml @@ -7,7 +7,7 @@ cn.hutool hutool-parent - 5.4.5-SNAPSHOT + 5.4.6-SNAPSHOT hutool-cron diff --git a/hutool-crypto/pom.xml b/hutool-crypto/pom.xml index 25acea0a2..f88bc3bd6 100644 --- a/hutool-crypto/pom.xml +++ b/hutool-crypto/pom.xml @@ -9,7 +9,7 @@ cn.hutool hutool-parent - 5.4.5-SNAPSHOT + 5.4.6-SNAPSHOT hutool-crypto diff --git a/hutool-db/pom.xml b/hutool-db/pom.xml index 99518169b..3781e1697 100644 --- a/hutool-db/pom.xml +++ b/hutool-db/pom.xml @@ -9,7 +9,7 @@ cn.hutool hutool-parent - 5.4.5-SNAPSHOT + 5.4.6-SNAPSHOT hutool-db diff --git a/hutool-dfa/pom.xml b/hutool-dfa/pom.xml index 1d2a09ab2..6cf12759b 100644 --- a/hutool-dfa/pom.xml +++ b/hutool-dfa/pom.xml @@ -7,7 +7,7 @@ cn.hutool hutool-parent - 5.4.5-SNAPSHOT + 5.4.6-SNAPSHOT hutool-dfa diff --git a/hutool-extra/bopomofo4j-temp/bopomofo4j-c6e41074-5302-42b6-9bdf-8742cb416a62.jar b/hutool-extra/bopomofo4j-temp/bopomofo4j-c6e41074-5302-42b6-9bdf-8742cb416a62.jar new file mode 100644 index 000000000..6ae573b55 Binary files /dev/null and b/hutool-extra/bopomofo4j-temp/bopomofo4j-c6e41074-5302-42b6-9bdf-8742cb416a62.jar differ diff --git a/hutool-extra/pom.xml b/hutool-extra/pom.xml index f91f5ac87..d07297970 100644 --- a/hutool-extra/pom.xml +++ b/hutool-extra/pom.xml @@ -9,7 +9,7 @@ cn.hutool hutool-parent - 5.4.5-SNAPSHOT + 5.4.6-SNAPSHOT hutool-extra @@ -233,6 +233,12 @@ 1.1.8 true + + com.rnkrsoft.bopomofo4j + bopomofo4j + 1.0.0 + true + cglib cglib diff --git a/hutool-extra/src/main/java/cn/hutool/extra/pinyin/engine/bopomofo4j/Bopomofo4jEngine.java b/hutool-extra/src/main/java/cn/hutool/extra/pinyin/engine/bopomofo4j/Bopomofo4jEngine.java new file mode 100644 index 000000000..09409cab8 --- /dev/null +++ b/hutool-extra/src/main/java/cn/hutool/extra/pinyin/engine/bopomofo4j/Bopomofo4jEngine.java @@ -0,0 +1,43 @@ +package cn.hutool.extra.pinyin.engine.bopomofo4j; + +import cn.hutool.core.util.StrUtil; +import cn.hutool.extra.pinyin.PinyinEngine; +import com.rnkrsoft.bopomofo4j.Bopomofo4j; +import com.rnkrsoft.bopomofo4j.ToneType; + +/** + * 封装了Bopomofo4j的引擎。 + * + *

+ * Bopomofo4j封装,项目:https://gitee.com/rnkrsoft/Bopomofo4j。 + *

+ * + *

+ * 引入: + *

+ * <dependency>
+ *     <groupId>com.rnkrsoft.bopomofo4j</groupId>
+ *     <artifactId>bopomofo4j</artifactId>
+ *     <version>1.0.0</version>
+ * </dependency>
+ * 
+ * + * @author looly + * @since 5.4.5 + */ +public class Bopomofo4jEngine implements PinyinEngine { + + public Bopomofo4jEngine(){ + Bopomofo4j.local(); + } + + @Override + public String getPinyin(char c) { + return Bopomofo4j.pinyin(String.valueOf(c), ToneType.WITHOUT_TONE, false, false, StrUtil.EMPTY); + } + + @Override + public String getPinyin(String str, String separator) { + return Bopomofo4j.pinyin(str, ToneType.WITHOUT_TONE, false, false, separator); + } +} diff --git a/hutool-extra/src/main/java/cn/hutool/extra/pinyin/engine/bopomofo4j/package-info.java b/hutool-extra/src/main/java/cn/hutool/extra/pinyin/engine/bopomofo4j/package-info.java new file mode 100644 index 000000000..8e56f1b49 --- /dev/null +++ b/hutool-extra/src/main/java/cn/hutool/extra/pinyin/engine/bopomofo4j/package-info.java @@ -0,0 +1,20 @@ +/** + * 封装了Bopomofo4j的引擎。 + * + *

+ * Bopomofo4j封装,项目:https://gitee.com/rnkrsoft/Bopomofo4j。 + *

+ * + *

+ * 引入: + *

+ * <dependency>
+ *     <groupId>com.rnkrsoft.bopomofo4j</groupId>
+ *     <artifactId>bopomofo4j</artifactId>
+ *     <version>1.0.0</version>
+ * </dependency>
+ * 
+ * + * @author looly + */ +package cn.hutool.extra.pinyin.engine.bopomofo4j; \ No newline at end of file diff --git a/hutool-extra/src/main/resources/META-INF/services/cn.hutool.extra.pinyin.PinyinEngine b/hutool-extra/src/main/resources/META-INF/services/cn.hutool.extra.pinyin.PinyinEngine index 5526a0a33..c91f32dd3 100644 --- a/hutool-extra/src/main/resources/META-INF/services/cn.hutool.extra.pinyin.PinyinEngine +++ b/hutool-extra/src/main/resources/META-INF/services/cn.hutool.extra.pinyin.PinyinEngine @@ -1,3 +1,4 @@ cn.hutool.extra.pinyin.engine.tinypinyin.TinyPinyinEngine cn.hutool.extra.pinyin.engine.jpinyin.JPinyinEngine -cn.hutool.extra.pinyin.engine.pinyin4j.Pinyin4jEngine \ No newline at end of file +cn.hutool.extra.pinyin.engine.pinyin4j.Pinyin4jEngine +cn.hutool.extra.pinyin.engine.bopomofo4j.Bopomofo4jEngine \ No newline at end of file diff --git a/hutool-extra/src/test/java/cn/hutool/extra/pinyin/PinyinUtilTest.java b/hutool-extra/src/test/java/cn/hutool/extra/pinyin/PinyinUtilTest.java index 751fa53ee..a39c8c1db 100644 --- a/hutool-extra/src/test/java/cn/hutool/extra/pinyin/PinyinUtilTest.java +++ b/hutool-extra/src/test/java/cn/hutool/extra/pinyin/PinyinUtilTest.java @@ -1,5 +1,6 @@ package cn.hutool.extra.pinyin; +import cn.hutool.extra.pinyin.engine.bopomofo4j.Bopomofo4jEngine; import cn.hutool.extra.pinyin.engine.pinyin4j.Pinyin4jEngine; import org.junit.Assert; import org.junit.Test; @@ -19,6 +20,13 @@ public class PinyinUtilTest { Assert.assertEquals("ni hao h", pinyin); } + @Test + public void getPinyinByBopomofo4jTest() { + final Bopomofo4jEngine engine = new Bopomofo4jEngine(); + final String pinyin = engine.getPinyin("你好h", " "); + Assert.assertEquals("ni haoh", pinyin); + } + @Test public void getPinyinUpperCaseTest(){ final String pinyin = PinyinUtil.getPinyin("你好怡", " "); @@ -37,4 +45,11 @@ public class PinyinUtilTest { final String result = engine.getFirstLetter("林海", ""); Assert.assertEquals("lh", result); } + + @Test + public void getFirstLetterByBopomofo4jTest(){ + final Bopomofo4jEngine engine = new Bopomofo4jEngine(); + final String result = engine.getFirstLetter("林海", ""); + Assert.assertEquals("lh", result); + } } diff --git a/hutool-http/pom.xml b/hutool-http/pom.xml index a7b33873e..ad3171410 100644 --- a/hutool-http/pom.xml +++ b/hutool-http/pom.xml @@ -9,7 +9,7 @@ cn.hutool hutool-parent - 5.4.5-SNAPSHOT + 5.4.6-SNAPSHOT hutool-http diff --git a/hutool-http/src/main/java/cn/hutool/http/Header.java b/hutool-http/src/main/java/cn/hutool/http/Header.java index 1c90606c5..86dc86245 100644 --- a/hutool-http/src/main/java/cn/hutool/http/Header.java +++ b/hutool-http/src/main/java/cn/hutool/http/Header.java @@ -9,9 +9,19 @@ public enum Header { //------------------------------------------------------------- 通用头域 /** - * 提供验证头 + * 提供验证头,例如: + *
+	 * Authorization: Basic YWxhZGRpbjpvcGVuc2VzYW1l
+	 * 
*/ AUTHORIZATION("Authorization"), + /** + * 提供给代理服务器的用于身份验证的凭证,例如: + *
+	 * Proxy-Authorization: Basic YWxhZGRpbjpvcGVuc2VzYW1l
+	 * 
+ */ + PROXY_AUTHORIZATION("Proxy-Authorization"), /** * 提供日期和时间标志,说明报文是什么时间创建的 */ diff --git a/hutool-http/src/main/java/cn/hutool/http/HttpConnection.java b/hutool-http/src/main/java/cn/hutool/http/HttpConnection.java index 7dd41123e..bf1d7dcf2 100644 --- a/hutool-http/src/main/java/cn/hutool/http/HttpConnection.java +++ b/hutool-http/src/main/java/cn/hutool/http/HttpConnection.java @@ -531,7 +531,7 @@ public class HttpConnection { final URLConnection conn = openConnection(); if (false == conn instanceof HttpURLConnection) { // 防止其它协议造成的转换异常 - throw new HttpException("'{}' is not a http connection, make sure URL is format for http.", conn.getClass().getName()); + throw new HttpException("'{}' of URL [{}] is not a http connection, make sure URL is format for http.", conn.getClass().getName(), this.url); } return (HttpURLConnection) conn; diff --git a/hutool-http/src/main/java/cn/hutool/http/HttpRequest.java b/hutool-http/src/main/java/cn/hutool/http/HttpRequest.java index b0cae62d8..daba627c1 100644 --- a/hutool-http/src/main/java/cn/hutool/http/HttpRequest.java +++ b/hutool-http/src/main/java/cn/hutool/http/HttpRequest.java @@ -1,6 +1,5 @@ package cn.hutool.http; -import cn.hutool.core.codec.Base64; import cn.hutool.core.collection.CollUtil; import cn.hutool.core.convert.Convert; import cn.hutool.core.io.IORuntimeException; @@ -981,16 +980,32 @@ public class HttpRequest extends HttpBase { } /** - * 简单验证 + * 简单验证,生成的头信息类似于: + *
+	 * Authorization: Basic YWxhZGRpbjpvcGVuc2VzYW1l
+	 * 
* * @param username 用户名 * @param password 密码 - * @return HttpRequest + * @return this */ public HttpRequest basicAuth(String username, String password) { - final String data = username.concat(":").concat(password); - final String base64 = Base64.encode(data, charset); - return auth("Basic " + base64); + return auth(HttpUtil.buildBasicAuth(username, password, charset)); + } + + /** + * 简单代理验证,生成的头信息类似于: + *
+	 * Proxy-Authorization: Basic YWxhZGRpbjpvcGVuc2VzYW1l
+	 * 
+ * + * @param username 用户名 + * @param password 密码 + * @return this + * @since 5.4.6 + */ + public HttpRequest basicProxyAuth(String username, String password) { + return proxyAuth(HttpUtil.buildBasicAuth(username, password, charset)); } /** @@ -1005,6 +1020,18 @@ public class HttpRequest extends HttpBase { return this; } + /** + * 验证,简单插入Authorization头 + * + * @param content 验证内容 + * @return HttpRequest + * @since 5.4.6 + */ + public HttpRequest proxyAuth(String content) { + header(Header.PROXY_AUTHORIZATION, content, true); + return this; + } + @Override public String toString() { StringBuilder sb = StrUtil.builder(); diff --git a/hutool-http/src/main/java/cn/hutool/http/HttpUtil.java b/hutool-http/src/main/java/cn/hutool/http/HttpUtil.java index db816cd27..1c37c31cd 100644 --- a/hutool-http/src/main/java/cn/hutool/http/HttpUtil.java +++ b/hutool-http/src/main/java/cn/hutool/http/HttpUtil.java @@ -1,5 +1,6 @@ package cn.hutool.http; +import cn.hutool.core.codec.Base64; import cn.hutool.core.convert.Convert; import cn.hutool.core.io.FastByteArrayOutputStream; import cn.hutool.core.io.FileUtil; @@ -870,4 +871,21 @@ public class HttpUtil { public static SimpleServer createServer(int port) { return new SimpleServer(port); } + + /** + * 构建简单的账号秘密验证信息,构建后类似于: + *
+	 *     Basic YWxhZGRpbjpvcGVuc2VzYW1l
+	 * 
+ * + * @param username 账号 + * @param password 密码 + * @param charset 编码(如果账号或密码中有非ASCII字符适用) + * @return 密码验证信息 + * @since 5.4.6 + */ + public static String buildBasicAuth(String username, String password, Charset charset){ + final String data = username.concat(":").concat(password); + return "Basic " + Base64.encode(data, charset); + } } diff --git a/hutool-http/src/test/java/cn/hutool/http/test/HttpRequestTest.java b/hutool-http/src/test/java/cn/hutool/http/test/HttpRequestTest.java index aa1d9d93f..bf00b18ff 100644 --- a/hutool-http/src/test/java/cn/hutool/http/test/HttpRequestTest.java +++ b/hutool-http/src/test/java/cn/hutool/http/test/HttpRequestTest.java @@ -143,4 +143,5 @@ public class HttpRequestTest { HttpResponse execute = get.execute(); Console.log(execute.body()); } + } diff --git a/hutool-json/pom.xml b/hutool-json/pom.xml index b84f23bec..1fd98acf1 100644 --- a/hutool-json/pom.xml +++ b/hutool-json/pom.xml @@ -9,7 +9,7 @@ cn.hutool hutool-parent - 5.4.5-SNAPSHOT + 5.4.6-SNAPSHOT hutool-json diff --git a/hutool-json/src/main/java/cn/hutool/json/InternalJSONUtil.java b/hutool-json/src/main/java/cn/hutool/json/InternalJSONUtil.java index c47ac3df6..98e9c3264 100644 --- a/hutool-json/src/main/java/cn/hutool/json/InternalJSONUtil.java +++ b/hutool-json/src/main/java/cn/hutool/json/InternalJSONUtil.java @@ -2,6 +2,7 @@ package cn.hutool.json; import cn.hutool.core.convert.Convert; import cn.hutool.core.date.DateUtil; +import cn.hutool.core.date.TemporalAccessorUtil; import cn.hutool.core.util.CharUtil; import cn.hutool.core.util.NumberUtil; import cn.hutool.core.util.ObjectUtil; @@ -239,6 +240,9 @@ final class InternalJSONUtil { */ private static String formatDate(Object dateObj, String format) { if (StrUtil.isNotBlank(format)) { + if(dateObj instanceof TemporalAccessor){ + return TemporalAccessorUtil.format((TemporalAccessor) dateObj, format); + } //用户定义了日期格式 return JSONUtil.quote(DateUtil.format(Convert.toDate(dateObj), format)); } diff --git a/hutool-json/src/main/java/cn/hutool/json/JSONObject.java b/hutool-json/src/main/java/cn/hutool/json/JSONObject.java index 0f0117c8a..3c6c15363 100644 --- a/hutool-json/src/main/java/cn/hutool/json/JSONObject.java +++ b/hutool-json/src/main/java/cn/hutool/json/JSONObject.java @@ -351,6 +351,18 @@ public class JSONObject implements JSON, JSONGetter, Map @Override @Deprecated public JSONObject put(String key, Object value) throws JSONException { + return set(key, value); + } + + /** + * 设置键值对到JSONObject中,在忽略null模式下,如果值为null,将此键移除 + * + * @param key 键 + * @param value 值对象. 可以是以下类型: Boolean, Double, Integer, JSONArray, JSONObject, Long, String, or the JSONNull.NULL. + * @return this. + * @throws JSONException 值是无穷数字抛出此异常 + */ + public JSONObject set(String key, Object value) throws JSONException { if (null == key) { return this; } @@ -366,19 +378,6 @@ public class JSONObject implements JSON, JSONGetter, Map return this; } - /** - * 设置键值对到JSONObject中,在忽略null模式下,如果值为null,将此键移除 - * - * @param key 键 - * @param value 值对象. 可以是以下类型: Boolean, Double, Integer, JSONArray, JSONObject, Long, String, or the JSONNull.NULL. - * @return this. - * @throws JSONException 值是无穷数字抛出此异常 - */ - public JSONObject set(String key, Object value) throws JSONException { - put(key, value); - return this; - } - /** * 一次性Put 键值对,如果key已经存在抛出异常,如果键值中有null值,忽略 * @@ -392,7 +391,7 @@ public class JSONObject implements JSON, JSONGetter, Map if (rawHashMap.containsKey(key)) { throw new JSONException("Duplicate key \"{}\"", key); } - this.put(key, value); + this.set(key, value); } return this; } @@ -407,7 +406,7 @@ public class JSONObject implements JSON, JSONGetter, Map */ public JSONObject putOpt(String key, Object value) throws JSONException { if (key != null && value != null) { - this.put(key, value); + this.set(key, value); } return this; } @@ -415,7 +414,7 @@ public class JSONObject implements JSON, JSONGetter, Map @Override public void putAll(Map m) { for (Entry entry : m.entrySet()) { - this.put(entry.getKey(), entry.getValue()); + this.set(entry.getKey(), entry.getValue()); } } @@ -432,7 +431,7 @@ public class JSONObject implements JSON, JSONGetter, Map InternalJSONUtil.testValidity(value); Object object = this.getObj(key); if (object == null) { - this.put(key, value instanceof JSONArray ? new JSONArray(this.config).set(value) : value); + this.set(key, value instanceof JSONArray ? new JSONArray(this.config).set(value) : value); } else if (object instanceof JSONArray) { ((JSONArray) object).set(value); } else { @@ -472,19 +471,19 @@ public class JSONObject implements JSON, JSONGetter, Map public JSONObject increment(String key) throws JSONException { Object value = this.getObj(key); if (value == null) { - this.put(key, 1); + this.set(key, 1); } else if (value instanceof BigInteger) { - this.put(key, ((BigInteger) value).add(BigInteger.ONE)); + this.set(key, ((BigInteger) value).add(BigInteger.ONE)); } else if (value instanceof BigDecimal) { - this.put(key, ((BigDecimal) value).add(BigDecimal.ONE)); + this.set(key, ((BigDecimal) value).add(BigDecimal.ONE)); } else if (value instanceof Integer) { - this.put(key, (Integer) value + 1); + this.set(key, (Integer) value + 1); } else if (value instanceof Long) { - this.put(key, (Long) value + 1); + this.set(key, (Long) value + 1); } else if (value instanceof Double) { - this.put(key, (Double) value + 1); + this.set(key, (Double) value + 1); } else if (value instanceof Float) { - this.put(key, (Float) value + 1); + this.set(key, (Float) value + 1); } else { throw new JSONException("Unable to increment [" + JSONUtil.quote(key) + "]."); } @@ -652,8 +651,11 @@ public class JSONObject implements JSON, JSONGetter, Map } else if (source instanceof Map) { // Map for (final Entry e : ((Map) source).entrySet()) { - this.put(Convert.toStr(e.getKey()), e.getValue()); + this.set(Convert.toStr(e.getKey()), e.getValue()); } + }else if (source instanceof Map.Entry) { + final Map.Entry entry = (Map.Entry) source; + this.set(Convert.toStr(entry.getKey()), entry.getValue()); } else if (source instanceof CharSequence) { // 可能为JSON字符串 init((CharSequence) source); diff --git a/hutool-json/src/test/java/cn/hutool/json/JSONObjectTest.java b/hutool-json/src/test/java/cn/hutool/json/JSONObjectTest.java index cc5583dad..9f7e8422a 100644 --- a/hutool-json/src/test/java/cn/hutool/json/JSONObjectTest.java +++ b/hutool-json/src/test/java/cn/hutool/json/JSONObjectTest.java @@ -9,6 +9,7 @@ import cn.hutool.core.date.DateUtil; import cn.hutool.core.io.FileUtil; import cn.hutool.core.io.resource.ResourceUtil; import cn.hutool.core.lang.Console; +import cn.hutool.core.map.MapUtil; import cn.hutool.core.util.StrUtil; import cn.hutool.json.test.bean.JSONBean; import cn.hutool.json.test.bean.ResultDto; @@ -27,9 +28,13 @@ import org.junit.Ignore; import org.junit.Test; import java.math.BigDecimal; +import java.sql.Timestamp; import java.util.Date; +import java.util.HashMap; import java.util.List; +import java.util.Map; import java.util.Objects; +import java.util.Set; /** * JSONObject单元测试 @@ -425,6 +430,14 @@ public class JSONObjectTest { Assert.assertEquals("{\"date\":[\"2020-06-05 11:16:11\"],\"bbb\":[\"222\"],\"aaa\":[\"123\"]}", json.toString()); } + @Test + public void getTimestampTest(){ + String timeStr = "1970-01-01 00:00:00"; + final JSONObject jsonObject = JSONUtil.createObj().set("time", timeStr); + final Timestamp time = jsonObject.get("time", Timestamp.class); + Assert.assertEquals("1970-01-01 00:00:00.0", time.toString()); + } + public enum TestEnum { TYPE_A, TYPE_B } @@ -497,4 +510,14 @@ public class JSONObjectTest { return this.fieldToIgnore; } } + + @Test + public void setEntryTest(){ + final HashMap of = MapUtil.of("test", "testValue"); + final Set> entries = of.entrySet(); + final Map.Entry next = entries.iterator().next(); + + final JSONObject jsonObject = JSONUtil.parseObj(next); + Console.log(jsonObject); + } } diff --git a/hutool-log/pom.xml b/hutool-log/pom.xml index 3d15e4203..f0aa4f5e3 100644 --- a/hutool-log/pom.xml +++ b/hutool-log/pom.xml @@ -9,7 +9,7 @@ cn.hutool hutool-parent - 5.4.5-SNAPSHOT + 5.4.6-SNAPSHOT hutool-log diff --git a/hutool-poi/pom.xml b/hutool-poi/pom.xml index 47dcd4ea4..9b70a7668 100644 --- a/hutool-poi/pom.xml +++ b/hutool-poi/pom.xml @@ -8,7 +8,7 @@ cn.hutool hutool-parent - 5.4.5-SNAPSHOT + 5.4.6-SNAPSHOT hutool-poi diff --git a/hutool-script/pom.xml b/hutool-script/pom.xml index 995789f43..378cb3448 100644 --- a/hutool-script/pom.xml +++ b/hutool-script/pom.xml @@ -8,7 +8,7 @@ cn.hutool hutool-parent - 5.4.5-SNAPSHOT + 5.4.6-SNAPSHOT hutool-script diff --git a/hutool-setting/pom.xml b/hutool-setting/pom.xml index 00e487784..ffc86415c 100644 --- a/hutool-setting/pom.xml +++ b/hutool-setting/pom.xml @@ -9,7 +9,7 @@ cn.hutool hutool-parent - 5.4.5-SNAPSHOT + 5.4.6-SNAPSHOT hutool-setting diff --git a/hutool-socket/pom.xml b/hutool-socket/pom.xml index 459441938..bd43ba346 100644 --- a/hutool-socket/pom.xml +++ b/hutool-socket/pom.xml @@ -9,7 +9,7 @@ cn.hutool hutool-parent - 5.4.5-SNAPSHOT + 5.4.6-SNAPSHOT hutool-socket diff --git a/hutool-system/pom.xml b/hutool-system/pom.xml index 8110b4903..b78a89ffe 100644 --- a/hutool-system/pom.xml +++ b/hutool-system/pom.xml @@ -9,7 +9,7 @@ cn.hutool hutool-parent - 5.4.5-SNAPSHOT + 5.4.6-SNAPSHOT hutool-system diff --git a/pom.xml b/pom.xml index 6bebf3683..44246d40a 100644 --- a/pom.xml +++ b/pom.xml @@ -8,7 +8,7 @@ cn.hutool hutool-parent - 5.4.5-SNAPSHOT + 5.4.6-SNAPSHOT hutool Hutool是一个小而全的Java工具类库,通过静态方法封装,降低相关API的学习成本,提高工作效率,使Java拥有函数式语言般的优雅,让Java语言也可以“甜甜的”。 https://github.com/looly/hutool