mirror of
https://gitee.com/chinabugotech/hutool.git
synced 2025-05-09 23:51:34 +08:00
Merge remote-tracking branch 'upstream/v5-dev' into v5-dev
This commit is contained in:
commit
0c8e278bfb
20
CHANGELOG.md
20
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 】 修复计算相差天数导致的问题
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------
|
||||
|
||||
|
@ -120,19 +120,19 @@ Each module can be introduced individually, or all modules can be introduced by
|
||||
<dependency>
|
||||
<groupId>cn.hutool</groupId>
|
||||
<artifactId>hutool-all</artifactId>
|
||||
<version>5.4.5</version>
|
||||
<version>5.4.6</version>
|
||||
</dependency>
|
||||
```
|
||||
|
||||
### 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.
|
||||
|
@ -119,21 +119,21 @@ Hutool的存在就是为了减少代码搜索成本,避免网络上参差不
|
||||
<dependency>
|
||||
<groupId>cn.hutool</groupId>
|
||||
<artifactId>hutool-all</artifactId>
|
||||
<version>5.4.5</version>
|
||||
<version>5.4.6</version>
|
||||
</dependency>
|
||||
```
|
||||
|
||||
### 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平台没有测试,不能保证所有工具类或工具方法可用。
|
||||
|
@ -1 +1 @@
|
||||
5.4.5
|
||||
5.4.6
|
||||
|
@ -1 +1 @@
|
||||
var version = '5.4.5'
|
||||
var version = '5.4.6'
|
@ -9,7 +9,7 @@
|
||||
<parent>
|
||||
<groupId>cn.hutool</groupId>
|
||||
<artifactId>hutool-parent</artifactId>
|
||||
<version>5.4.5-SNAPSHOT</version>
|
||||
<version>5.4.6-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>hutool-all</artifactId>
|
||||
|
@ -9,7 +9,7 @@
|
||||
<parent>
|
||||
<groupId>cn.hutool</groupId>
|
||||
<artifactId>hutool-parent</artifactId>
|
||||
<version>5.4.5-SNAPSHOT</version>
|
||||
<version>5.4.6-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>hutool-aop</artifactId>
|
||||
|
@ -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) {
|
||||
//继承此类后实现此方法
|
||||
|
@ -7,7 +7,7 @@
|
||||
<parent>
|
||||
<groupId>cn.hutool</groupId>
|
||||
<artifactId>hutool-parent</artifactId>
|
||||
<version>5.4.5-SNAPSHOT</version>
|
||||
<version>5.4.6-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>hutool-bloomFilter</artifactId>
|
||||
|
@ -7,7 +7,7 @@
|
||||
<parent>
|
||||
<groupId>cn.hutool</groupId>
|
||||
<artifactId>hutool-parent</artifactId>
|
||||
<version>5.4.5-SNAPSHOT</version>
|
||||
<version>5.4.6-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>hutool-bom</artifactId>
|
||||
|
@ -7,7 +7,7 @@
|
||||
<parent>
|
||||
<groupId>cn.hutool</groupId>
|
||||
<artifactId>hutool-parent</artifactId>
|
||||
<version>5.4.5-SNAPSHOT</version>
|
||||
<version>5.4.6-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>hutool-cache</artifactId>
|
||||
|
@ -7,7 +7,7 @@
|
||||
<parent>
|
||||
<groupId>cn.hutool</groupId>
|
||||
<artifactId>hutool-parent</artifactId>
|
||||
<version>5.4.5-SNAPSHOT</version>
|
||||
<version>5.4.6-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>hutool-captcha</artifactId>
|
||||
|
@ -9,7 +9,7 @@
|
||||
<parent>
|
||||
<groupId>cn.hutool</groupId>
|
||||
<artifactId>hutool-parent</artifactId>
|
||||
<version>5.4.5-SNAPSHOT</version>
|
||||
<version>5.4.6-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>hutool-core</artifactId>
|
||||
|
@ -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;
|
||||
|
@ -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());
|
||||
|
@ -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<AtomicIntegerArray> {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@Override
|
||||
protected AtomicIntegerArray convertInternal(Object value) {
|
||||
return new AtomicIntegerArray(Convert.convert(int[].class, value));
|
||||
}
|
||||
|
||||
}
|
@ -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<AtomicLongArray> {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@Override
|
||||
protected AtomicLongArray convertInternal(Object value) {
|
||||
return new AtomicLongArray(Convert.convert(long[].class, value));
|
||||
}
|
||||
|
||||
}
|
@ -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;
|
||||
|
||||
/**
|
||||
* 数字转换器<br>
|
||||
@ -64,7 +66,6 @@ public class NumberConverter extends AbstractConverter<Number> {
|
||||
}
|
||||
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<Number> {
|
||||
}
|
||||
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<Number> {
|
||||
}
|
||||
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<Number> {
|
||||
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<Number> {
|
||||
}
|
||||
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<Number> {
|
||||
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<Number> {
|
||||
}
|
||||
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<Number> {
|
||||
* @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<Number> {
|
||||
} 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
|
||||
|
@ -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<String>{
|
||||
public class StringConverter extends AbstractConverter<String> {
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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 + "日";
|
||||
}
|
||||
|
@ -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) {
|
||||
|
@ -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),
|
||||
/**一分钟的毫秒数 */
|
||||
/**
|
||||
* 一分钟的毫秒数
|
||||
*/
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
@ -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 {
|
||||
* <p>
|
||||
* 返回结果为{@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);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取两个日期的差,如果结束时间早于开始时间,获取结果为负。
|
||||
* <p>
|
||||
* 返回结果为时间差的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);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取两个日期的表象时间差,如果结束时间早于开始时间,获取结果为负。
|
||||
* <p>
|
||||
* 比如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
|
||||
|
@ -20,7 +20,7 @@ import java.time.temporal.TemporalField;
|
||||
* @author looly
|
||||
* @since 5.3.9
|
||||
*/
|
||||
public class TemporalAccessorUtil {
|
||||
public class TemporalAccessorUtil extends TemporalUtil{
|
||||
|
||||
/**
|
||||
* 安全获取时间的某个属性,属性不存在返回0
|
||||
|
@ -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 {
|
||||
|
||||
/**
|
||||
* 获取两个日期的差,如果结束时间早于开始时间,获取结果为负。
|
||||
* <p>
|
||||
* 返回结果为{@link Duration}对象,通过调用toXXX方法返回相差单位
|
||||
*
|
||||
* @param startTimeInclude 开始时间(包含)
|
||||
* @param endTimeExclude 结束时间(不包含)
|
||||
* @return 时间差 {@link Duration}对象
|
||||
*/
|
||||
public static Duration between(Temporal startTimeInclude, Temporal endTimeExclude) {
|
||||
return Duration.between(startTimeInclude, endTimeExclude);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取两个日期的差,如果结束时间早于开始时间,获取结果为负。
|
||||
* <p>
|
||||
* 返回结果为时间差的long值
|
||||
*
|
||||
* @param startTimeInclude 开始时间(包括)
|
||||
* @param endTimeExclude 结束时间(不包括)
|
||||
* @param unit 时间差单位
|
||||
* @return 时间差
|
||||
*/
|
||||
public static long between(Temporal startTimeInclude, Temporal endTimeExclude, ChronoUnit unit) {
|
||||
return unit.between(startTimeInclude, endTimeExclude);
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -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();
|
||||
}
|
||||
|
||||
|
@ -68,7 +68,7 @@ public class Assert {
|
||||
* 断言是否为假,如果为 {@code true} 抛出指定类型异常<br>
|
||||
* 并使用指定的函数获取错误信息返回
|
||||
* <pre class="code">
|
||||
* 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} 抛出指定类型异常
|
||||
* 并使用指定的函数获取错误信息返回
|
||||
* <pre class="code">
|
||||
* 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} 抛出指定类型异常
|
||||
* 并使用指定的函数获取错误信息返回
|
||||
* <pre class="code">
|
||||
* Assert.notNull(clazz, ()->{
|
||||
* Assert.notNull(clazz, ()->{
|
||||
* // to query relation message
|
||||
* return new IllegalArgumentException("relation message to return");
|
||||
* });
|
||||
@ -234,7 +234,7 @@ public class Assert {
|
||||
/**
|
||||
* 检查给定字符串是否为空,为空抛出自定义异常,并使用指定的函数获取错误信息返回。
|
||||
* <pre class="code">
|
||||
* 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、空串或只包含空白符),为空抛出自定义异常。
|
||||
* 并使用指定的函数获取错误信息返回
|
||||
* <pre class="code">
|
||||
* Assert.notBlank(name, ()->{
|
||||
* Assert.notBlank(name, ()->{
|
||||
* // to query relation message
|
||||
* return new IllegalArgumentException("relation message to return");
|
||||
* });
|
||||
@ -357,7 +357,7 @@ public class Assert {
|
||||
* 断言给定字符串是否不被另一个字符串包含(即是否为子串)
|
||||
* 并使用指定的函数获取错误信息返回
|
||||
* <pre class="code">
|
||||
* 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 {
|
||||
* 并使用指定的函数获取错误信息返回
|
||||
*
|
||||
* <pre class="code">
|
||||
* 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}将被认为不包含
|
||||
* 并使用指定的函数获取错误信息返回
|
||||
* <pre class="code">
|
||||
* Assert.noNullElements(array, ()->{
|
||||
* Assert.noNullElements(array, ()->{
|
||||
* // to query relation message
|
||||
* return new IllegalArgumentException("relation message to return ");
|
||||
* });
|
||||
@ -538,7 +538,7 @@ public class Assert {
|
||||
* 断言给定集合非空
|
||||
* 并使用指定的函数获取错误信息返回
|
||||
* <pre class="code">
|
||||
* 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非空
|
||||
* 并使用指定的函数获取错误信息返回
|
||||
* <pre class="code">
|
||||
* 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}。
|
||||
* 并使用指定的函数获取错误信息返回
|
||||
* <pre class="code">
|
||||
* Assert.state(id == null, ()->{
|
||||
* Assert.state(id == null, ()->{
|
||||
* // to query relation message
|
||||
* return "relation message to return ";
|
||||
* });
|
||||
|
@ -1967,20 +1967,20 @@ public class NumberUtil {
|
||||
|
||||
/**
|
||||
* 数字转字符串<br>
|
||||
* 调用{@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}数字转字符串<br>
|
||||
* 调用{@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);
|
||||
}
|
||||
|
||||
/**
|
||||
* 是否空白符<br>
|
||||
* 空白符包括空格、制表符、全角空格和不间断空格<br>
|
||||
|
@ -139,7 +139,7 @@ public class ReflectUtil {
|
||||
}
|
||||
|
||||
/**
|
||||
* 查找指定类中的所有字段(包括非public字段),也包括父类和Object类的字段, 字段不存在则返回<code>null</code>
|
||||
* 查找指定类中的指定name的字段(包括非public字段),也包括父类和Object类的字段, 字段不存在则返回<code>null</code>
|
||||
*
|
||||
* @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,包括其父类中的字段<br>
|
||||
* 如果子类与父类中存在同名字段,则这两个字段同时存在,子类字段在前,父类字段在后。
|
||||
*
|
||||
* @param beanClass 类
|
||||
* @return 字段名和字段对应的Map
|
||||
* @return 字段名和字段对应的Map,有序
|
||||
* @since 5.0.7
|
||||
*/
|
||||
public static Map<String, Field> getFieldMap(Class<?> beanClass) {
|
||||
final Field[] fields = getFields(beanClass);
|
||||
final HashMap<String, Field> map = MapUtil.newHashMap(fields.length);
|
||||
final HashMap<String, Field> map = MapUtil.newHashMap(fields.length, true);
|
||||
for (Field field : fields) {
|
||||
map.put(field.getName(), field);
|
||||
}
|
||||
@ -175,7 +169,8 @@ public class ReflectUtil {
|
||||
}
|
||||
|
||||
/**
|
||||
* 获得一个类中所有字段列表,包括其父类中的字段
|
||||
* 获得一个类中所有字段列表,包括其父类中的字段<br>
|
||||
* 如果子类与父类中存在同名字段,则这两个字段同时存在,子类字段在前,父类字段在后。
|
||||
*
|
||||
* @param beanClass 类
|
||||
* @return 字段列表
|
||||
@ -192,14 +187,15 @@ public class ReflectUtil {
|
||||
}
|
||||
|
||||
/**
|
||||
* 获得一个类中所有字段列表,直接反射获取,无缓存
|
||||
* 获得一个类中所有字段列表,直接反射获取,无缓存<br>
|
||||
* 如果子类与父类中存在同名字段,则这两个字段同时存在,子类字段在前,父类字段在后。
|
||||
*
|
||||
* @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;
|
||||
|
@ -345,6 +345,19 @@ public class XmlUtil {
|
||||
|
||||
// -------------------------------------------------------------------------------------- Write
|
||||
|
||||
/**
|
||||
* 将XML文档转换为String<br>
|
||||
* 字符编码使用XML文档中的编码,获取不到则使用UTF-8<br>
|
||||
* 默认非格式化输出,若想格式化请使用{@link #format(Document)}
|
||||
*
|
||||
* @param doc XML文档
|
||||
* @return XML字符串
|
||||
* @since 5.4.5
|
||||
*/
|
||||
public static String toStr(Node doc) {
|
||||
return toStr(doc, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* 将XML文档转换为String<br>
|
||||
* 字符编码使用XML文档中的编码,获取不到则使用UTF-8<br>
|
||||
@ -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<br>
|
||||
* 字符编码使用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<br>
|
||||
* 字符编码使用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);
|
||||
|
@ -362,6 +362,13 @@ public class BeanUtilTest {
|
||||
private Boolean slow;
|
||||
}
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
public static class SubPersonWithOverlayTransientField extends PersonWithTransientField {
|
||||
// 覆盖父类中 transient 属性
|
||||
private String name;
|
||||
}
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
public static class Person {
|
||||
@ -370,6 +377,13 @@ public class BeanUtilTest {
|
||||
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;
|
||||
}
|
||||
|
||||
/**
|
||||
* <a href="https://github.com/looly/hutool/issues/1173">#1173</a>
|
||||
*/
|
||||
@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;
|
||||
|
@ -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 {
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
@ -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());
|
||||
}
|
||||
}
|
||||
|
@ -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());
|
||||
}
|
||||
}
|
||||
|
@ -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"))));
|
||||
}
|
||||
}
|
||||
|
@ -7,7 +7,7 @@
|
||||
<parent>
|
||||
<groupId>cn.hutool</groupId>
|
||||
<artifactId>hutool-parent</artifactId>
|
||||
<version>5.4.5-SNAPSHOT</version>
|
||||
<version>5.4.6-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>hutool-cron</artifactId>
|
||||
|
@ -9,7 +9,7 @@
|
||||
<parent>
|
||||
<groupId>cn.hutool</groupId>
|
||||
<artifactId>hutool-parent</artifactId>
|
||||
<version>5.4.5-SNAPSHOT</version>
|
||||
<version>5.4.6-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>hutool-crypto</artifactId>
|
||||
|
@ -9,7 +9,7 @@
|
||||
<parent>
|
||||
<groupId>cn.hutool</groupId>
|
||||
<artifactId>hutool-parent</artifactId>
|
||||
<version>5.4.5-SNAPSHOT</version>
|
||||
<version>5.4.6-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>hutool-db</artifactId>
|
||||
|
@ -7,7 +7,7 @@
|
||||
<parent>
|
||||
<groupId>cn.hutool</groupId>
|
||||
<artifactId>hutool-parent</artifactId>
|
||||
<version>5.4.5-SNAPSHOT</version>
|
||||
<version>5.4.6-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>hutool-dfa</artifactId>
|
||||
|
Binary file not shown.
@ -9,7 +9,7 @@
|
||||
<parent>
|
||||
<groupId>cn.hutool</groupId>
|
||||
<artifactId>hutool-parent</artifactId>
|
||||
<version>5.4.5-SNAPSHOT</version>
|
||||
<version>5.4.6-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>hutool-extra</artifactId>
|
||||
@ -233,6 +233,12 @@
|
||||
<version>1.1.8</version>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.rnkrsoft.bopomofo4j</groupId>
|
||||
<artifactId>bopomofo4j</artifactId>
|
||||
<version>1.0.0</version>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>cglib</groupId>
|
||||
<artifactId>cglib</artifactId>
|
||||
|
@ -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的引擎。
|
||||
*
|
||||
* <p>
|
||||
* Bopomofo4j封装,项目:https://gitee.com/rnkrsoft/Bopomofo4j。
|
||||
* </p>
|
||||
*
|
||||
* <p>
|
||||
* 引入:
|
||||
* <pre>
|
||||
* <dependency>
|
||||
* <groupId>com.rnkrsoft.bopomofo4j</groupId>
|
||||
* <artifactId>bopomofo4j</artifactId>
|
||||
* <version>1.0.0</version>
|
||||
* </dependency>
|
||||
* </pre>
|
||||
*
|
||||
* @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);
|
||||
}
|
||||
}
|
@ -0,0 +1,20 @@
|
||||
/**
|
||||
* 封装了Bopomofo4j的引擎。
|
||||
*
|
||||
* <p>
|
||||
* Bopomofo4j封装,项目:https://gitee.com/rnkrsoft/Bopomofo4j。
|
||||
* </p>
|
||||
*
|
||||
* <p>
|
||||
* 引入:
|
||||
* <pre>
|
||||
* <dependency>
|
||||
* <groupId>com.rnkrsoft.bopomofo4j</groupId>
|
||||
* <artifactId>bopomofo4j</artifactId>
|
||||
* <version>1.0.0</version>
|
||||
* </dependency>
|
||||
* </pre>
|
||||
*
|
||||
* @author looly
|
||||
*/
|
||||
package cn.hutool.extra.pinyin.engine.bopomofo4j;
|
@ -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
|
||||
cn.hutool.extra.pinyin.engine.bopomofo4j.Bopomofo4jEngine
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -9,7 +9,7 @@
|
||||
<parent>
|
||||
<groupId>cn.hutool</groupId>
|
||||
<artifactId>hutool-parent</artifactId>
|
||||
<version>5.4.5-SNAPSHOT</version>
|
||||
<version>5.4.6-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>hutool-http</artifactId>
|
||||
|
@ -9,9 +9,19 @@ public enum Header {
|
||||
|
||||
//------------------------------------------------------------- 通用头域
|
||||
/**
|
||||
* 提供验证头
|
||||
* 提供验证头,例如:
|
||||
* <pre>
|
||||
* Authorization: Basic YWxhZGRpbjpvcGVuc2VzYW1l
|
||||
* </pre>
|
||||
*/
|
||||
AUTHORIZATION("Authorization"),
|
||||
/**
|
||||
* 提供给代理服务器的用于身份验证的凭证,例如:
|
||||
* <pre>
|
||||
* Proxy-Authorization: Basic YWxhZGRpbjpvcGVuc2VzYW1l
|
||||
* </pre>
|
||||
*/
|
||||
PROXY_AUTHORIZATION("Proxy-Authorization"),
|
||||
/**
|
||||
* 提供日期和时间标志,说明报文是什么时间创建的
|
||||
*/
|
||||
|
@ -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;
|
||||
|
@ -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<HttpRequest> {
|
||||
}
|
||||
|
||||
/**
|
||||
* 简单验证
|
||||
* 简单验证,生成的头信息类似于:
|
||||
* <pre>
|
||||
* Authorization: Basic YWxhZGRpbjpvcGVuc2VzYW1l
|
||||
* </pre>
|
||||
*
|
||||
* @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));
|
||||
}
|
||||
|
||||
/**
|
||||
* 简单代理验证,生成的头信息类似于:
|
||||
* <pre>
|
||||
* Proxy-Authorization: Basic YWxhZGRpbjpvcGVuc2VzYW1l
|
||||
* </pre>
|
||||
*
|
||||
* @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<HttpRequest> {
|
||||
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();
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
/**
|
||||
* 构建简单的账号秘密验证信息,构建后类似于:
|
||||
* <pre>
|
||||
* Basic YWxhZGRpbjpvcGVuc2VzYW1l
|
||||
* </pre>
|
||||
*
|
||||
* @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);
|
||||
}
|
||||
}
|
||||
|
@ -143,4 +143,5 @@ public class HttpRequestTest {
|
||||
HttpResponse execute = get.execute();
|
||||
Console.log(execute.body());
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -9,7 +9,7 @@
|
||||
<parent>
|
||||
<groupId>cn.hutool</groupId>
|
||||
<artifactId>hutool-parent</artifactId>
|
||||
<version>5.4.5-SNAPSHOT</version>
|
||||
<version>5.4.6-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>hutool-json</artifactId>
|
||||
|
@ -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));
|
||||
}
|
||||
|
@ -351,6 +351,18 @@ public class JSONObject implements JSON, JSONGetter<String>, Map<String, Object>
|
||||
@Override
|
||||
@Deprecated
|
||||
public JSONObject put(String key, Object value) throws JSONException {
|
||||
return set(key, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置键值对到JSONObject中,在忽略null模式下,如果值为<code>null</code>,将此键移除
|
||||
*
|
||||
* @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<String>, Map<String, Object>
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置键值对到JSONObject中,在忽略null模式下,如果值为<code>null</code>,将此键移除
|
||||
*
|
||||
* @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<String>, Map<String, Object>
|
||||
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<String>, Map<String, Object>
|
||||
*/
|
||||
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<String>, Map<String, Object>
|
||||
@Override
|
||||
public void putAll(Map<? extends String, ?> m) {
|
||||
for (Entry<? extends String, ?> 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<String>, Map<String, Object>
|
||||
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<String>, Map<String, Object>
|
||||
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<String>, Map<String, Object>
|
||||
} 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);
|
||||
|
@ -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<String, String> of = MapUtil.of("test", "testValue");
|
||||
final Set<Map.Entry<String, String>> entries = of.entrySet();
|
||||
final Map.Entry<String, String> next = entries.iterator().next();
|
||||
|
||||
final JSONObject jsonObject = JSONUtil.parseObj(next);
|
||||
Console.log(jsonObject);
|
||||
}
|
||||
}
|
||||
|
@ -9,7 +9,7 @@
|
||||
<parent>
|
||||
<groupId>cn.hutool</groupId>
|
||||
<artifactId>hutool-parent</artifactId>
|
||||
<version>5.4.5-SNAPSHOT</version>
|
||||
<version>5.4.6-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>hutool-log</artifactId>
|
||||
|
@ -8,7 +8,7 @@
|
||||
<parent>
|
||||
<groupId>cn.hutool</groupId>
|
||||
<artifactId>hutool-parent</artifactId>
|
||||
<version>5.4.5-SNAPSHOT</version>
|
||||
<version>5.4.6-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>hutool-poi</artifactId>
|
||||
|
@ -8,7 +8,7 @@
|
||||
<parent>
|
||||
<groupId>cn.hutool</groupId>
|
||||
<artifactId>hutool-parent</artifactId>
|
||||
<version>5.4.5-SNAPSHOT</version>
|
||||
<version>5.4.6-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>hutool-script</artifactId>
|
||||
|
@ -9,7 +9,7 @@
|
||||
<parent>
|
||||
<groupId>cn.hutool</groupId>
|
||||
<artifactId>hutool-parent</artifactId>
|
||||
<version>5.4.5-SNAPSHOT</version>
|
||||
<version>5.4.6-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>hutool-setting</artifactId>
|
||||
|
@ -9,7 +9,7 @@
|
||||
<parent>
|
||||
<groupId>cn.hutool</groupId>
|
||||
<artifactId>hutool-parent</artifactId>
|
||||
<version>5.4.5-SNAPSHOT</version>
|
||||
<version>5.4.6-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>hutool-socket</artifactId>
|
||||
|
@ -9,7 +9,7 @@
|
||||
<parent>
|
||||
<groupId>cn.hutool</groupId>
|
||||
<artifactId>hutool-parent</artifactId>
|
||||
<version>5.4.5-SNAPSHOT</version>
|
||||
<version>5.4.6-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>hutool-system</artifactId>
|
||||
|
2
pom.xml
2
pom.xml
@ -8,7 +8,7 @@
|
||||
|
||||
<groupId>cn.hutool</groupId>
|
||||
<artifactId>hutool-parent</artifactId>
|
||||
<version>5.4.5-SNAPSHOT</version>
|
||||
<version>5.4.6-SNAPSHOT</version>
|
||||
<name>hutool</name>
|
||||
<description>Hutool是一个小而全的Java工具类库,通过静态方法封装,降低相关API的学习成本,提高工作效率,使Java拥有函数式语言般的优雅,让Java语言也可以“甜甜的”。</description>
|
||||
<url>https://github.com/looly/hutool</url>
|
||||
|
Loading…
x
Reference in New Issue
Block a user