fix DateRange bug

This commit is contained in:
Looly 2021-06-28 21:55:53 +08:00
parent 16910ed709
commit 5719c28158
6 changed files with 73 additions and 39 deletions

View File

@ -22,6 +22,7 @@
* 【core 】 修复IdcardUtil.getIdcardInfo.getProvinceCode获取为汉字的问题issue#I3XP4Q@Gitee
* 【core 】 修复CollUtil.subtract使用非标准Set等空指针问题issue#I3XN1Z@Gitee
* 【core 】 修复SqlFormatter部分SQL空指针问题issue#I3XS44@Gitee
* 【core 】 修复DateRange计算问题issue#I3Y1US@Gitee
-------------------------------------------------------------------------------------------------------------

View File

@ -16,8 +16,8 @@ public class DateRange extends Range<DateTime> {
/**
* 构造包含开始和结束日期时间
*
* @param start 起始日期时间
* @param end 结束日期时间
* @param start 起始日期时间包括
* @param end 结束日期时间包括
* @param unit 步进单位
*/
public DateRange(Date start, Date end, final DateField unit) {
@ -27,8 +27,8 @@ public class DateRange extends Range<DateTime> {
/**
* 构造包含开始和结束日期时间
*
* @param start 起始日期时间
* @param end 结束日期时间
* @param start 起始日期时间包括
* @param end 结束日期时间包括
* @param unit 步进单位
* @param step 步进数
*/
@ -48,11 +48,12 @@ public class DateRange extends Range<DateTime> {
*/
public DateRange(Date start, Date end, final DateField unit, final int step, boolean isIncludeStart, boolean isIncludeEnd) {
super(DateUtil.date(start), DateUtil.date(end), (current, end1, index) -> {
DateTime dt = current.offsetNew(unit, step);
final DateTime dt = DateUtil.date(start).offsetNew(unit, (index + 1) * step);
if (dt.isAfter(end1)) {
return null;
}
return current.offsetNew(unit, step);
return dt;
}, isIncludeStart, isIncludeEnd);
}

View File

@ -329,8 +329,7 @@ public class DateTime extends Date {
//noinspection MagicConstant
cal.add(datePart.getValue(), offset);
DateTime dt = ObjectUtil.clone(this);
return dt.setTimeInternal(cal.getTimeInMillis());
return ObjectUtil.clone(this).setTimeInternal(cal.getTimeInMillis());
}
// -------------------------------------------------------------------- offset end

View File

@ -1788,7 +1788,7 @@ public class DateUtil extends CalendarUtil {
/**
* 创建日期范围生成器
*
* @param start 起始日期时间
* @param start 起始日期时间包括
* @param end 结束日期时间
* @param unit 步进单位
* @return {@link DateRange}

View File

@ -17,36 +17,53 @@ import java.util.concurrent.locks.ReentrantReadWriteLock;
* 此类使用{@link ReentrantReadWriteLock}保证线程安全
* </p>
*
* @author Looly
*
* @param <T> 生成范围对象的类型
* @author Looly
*/
public class Range<T> implements Iterable<T>, Iterator<T>, Serializable {
private static final long serialVersionUID = 1L;
/** 锁保证线程安全 */
/**
* 锁保证线程安全
*/
private Lock lock = new ReentrantLock();
/** 起始对象 */
/**
* 起始对象
*/
private final T start;
/** 结束对象 */
/**
* 结束对象
*/
private final T end;
/** 当前对象 */
/**
* 当前对象
*/
private T current;
/** 下一个对象 */
/**
* 下一个对象
*/
private T next;
/** 步进 */
/**
* 步进
*/
private final Steper<T> steper;
/** 索引 */
/**
* 索引
*/
private int index = 0;
/** 是否包含第一个元素 */
/**
* 是否包含第一个元素
*/
private final boolean includeStart;
/** 是否包含最后一个元素 */
/**
* 是否包含最后一个元素
*/
private boolean includeEnd;
/**
* 构造
*
* @param start 起始对象
* @param start 起始对象包括
* @param steper 步进
*/
public Range(T start, Steper<T> steper) {
@ -56,8 +73,8 @@ public class Range<T> implements Iterable<T>, Iterator<T>, Serializable {
/**
* 构造
*
* @param start 起始对象包含
* @param end 结束对象包含
* @param start 起始对象包含
* @param end 结束对象包含
* @param steper 步进
*/
public Range(T start, T end, Steper<T> steper) {
@ -67,11 +84,11 @@ public class Range<T> implements Iterable<T>, Iterator<T>, Serializable {
/**
* 构造
*
* @param start 起始对象
* @param end 结束对象
* @param steper 步进
* @param start 起始对象
* @param end 结束对象
* @param steper 步进
* @param isIncludeStart 是否包含第一个元素
* @param isIncludeEnd 是否包含最后一个元素
* @param isIncludeEnd 是否包含最后一个元素
*/
public Range(T start, T end, Steper<T> steper, boolean isIncludeStart, boolean isIncludeEnd) {
this.start = start;
@ -99,7 +116,7 @@ public class Range<T> implements Iterable<T>, Iterator<T>, Serializable {
public boolean hasNext() {
lock.lock();
try {
if(0 == this.index && this.includeStart) {
if (0 == this.index && this.includeStart) {
return true;
}
if (null == this.next) {
@ -193,9 +210,8 @@ public class Range<T> implements Iterable<T>, Iterator<T>, Serializable {
* 3限制range个数通过实现此接口在实现类中定义一个对象属性可灵活定义limit限制range个数
* </pre>
*
* @author Looly
*
* @param <T> 需要增加步进的对象
* @author Looly
*/
public interface Steper<T> {
/**
@ -204,8 +220,8 @@ public class Range<T> implements Iterable<T>, Iterator<T>, Serializable {
* 用户需根据end参数自行定义边界当达到边界时返回null表示结束否则Range中边界对象无效会导致无限循环
*
* @param current 上一次增加步进后的基础对象
* @param end 结束对象
* @param index 当前索引步进到第几个元素从0开始计数
* @param end 结束对象
* @param index 当前索引步进到第几个元素从0开始计数
* @return 增加步进后的对象
*/
T step(T current, T end, int index);

View File

@ -1,6 +1,7 @@
package cn.hutool.core.lang;
import cn.hutool.core.date.DateField;
import cn.hutool.core.date.DateRange;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import org.junit.Assert;
@ -12,30 +13,46 @@ import org.junit.Test;
*
*/
public class RangeTest {
@Test
public void dateRangeTest() {
DateTime start = DateUtil.parse("2017-01-01");
DateTime end = DateUtil.parse("2017-01-02");
final Range<DateTime> range = new Range<>(start, end, (current, end1, index) -> {
if (current.isAfterOrEquals(end1)) {
return null;
}
return current.offsetNew(DateField.DAY_OF_YEAR, 1);
});
Assert.assertTrue(range.hasNext());
Assert.assertEquals(range.next(), DateUtil.parse("2017-01-01"));
Assert.assertEquals(DateUtil.parse("2017-01-01"), range.next());
Assert.assertTrue(range.hasNext());
Assert.assertEquals(range.next(), DateUtil.parse("2017-01-02"));
Assert.assertEquals(DateUtil.parse("2017-01-02"), range.next());
Assert.assertFalse(range.hasNext());
}
@Test
public void dateRangeTest2() {
DateTime start = DateUtil.parse("2021-01-31");
DateTime end = DateUtil.parse("2021-03-31");
final DateRange range = DateUtil.range(start, end, DateField.MONTH);
Assert.assertTrue(range.hasNext());
Assert.assertEquals(DateUtil.parse("2021-01-31"), range.next());
Assert.assertTrue(range.hasNext());
Assert.assertEquals(DateUtil.parse("2021-02-28"), range.next());
Assert.assertTrue(range.hasNext());
Assert.assertEquals(DateUtil.parse("2021-03-31"), range.next());
Assert.assertFalse(range.hasNext());
}
@Test
public void intRangeTest() {
final Range<Integer> range = new Range<>(1, 1, (current, end, index) -> current >= end ? null : current + 10);
Assert.assertTrue(range.hasNext());
Assert.assertEquals(Integer.valueOf(1), range.next());
Assert.assertFalse(range.hasNext());