mirror of
https://gitee.com/chinabugotech/hutool.git
synced 2025-05-09 23:51:34 +08:00
修复DateUtil.rangeContains未重置问题(issue#IB8OFS@gitee)
This commit is contained in:
parent
32331c2b23
commit
74e10f9547
@ -18,9 +18,9 @@ package org.dromara.hutool.core.date;
|
|||||||
|
|
||||||
import org.dromara.hutool.core.collection.ListUtil;
|
import org.dromara.hutool.core.collection.ListUtil;
|
||||||
import org.dromara.hutool.core.comparator.CompareUtil;
|
import org.dromara.hutool.core.comparator.CompareUtil;
|
||||||
|
import org.dromara.hutool.core.date.format.DateFormatManager;
|
||||||
import org.dromara.hutool.core.date.format.DatePrinter;
|
import org.dromara.hutool.core.date.format.DatePrinter;
|
||||||
import org.dromara.hutool.core.date.format.FastDateFormat;
|
import org.dromara.hutool.core.date.format.FastDateFormat;
|
||||||
import org.dromara.hutool.core.date.format.DateFormatManager;
|
|
||||||
import org.dromara.hutool.core.date.format.parser.PositionDateParser;
|
import org.dromara.hutool.core.date.format.parser.PositionDateParser;
|
||||||
import org.dromara.hutool.core.date.format.parser.RegisterDateParser;
|
import org.dromara.hutool.core.date.format.parser.RegisterDateParser;
|
||||||
import org.dromara.hutool.core.lang.Assert;
|
import org.dromara.hutool.core.lang.Assert;
|
||||||
|
@ -17,13 +17,10 @@
|
|||||||
package org.dromara.hutool.core.lang.range;
|
package org.dromara.hutool.core.lang.range;
|
||||||
|
|
||||||
import org.dromara.hutool.core.lang.Assert;
|
import org.dromara.hutool.core.lang.Assert;
|
||||||
import org.dromara.hutool.core.thread.lock.NoLock;
|
|
||||||
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.NoSuchElementException;
|
import java.util.NoSuchElementException;
|
||||||
import java.util.concurrent.locks.Lock;
|
|
||||||
import java.util.concurrent.locks.ReentrantLock;
|
|
||||||
import java.util.concurrent.locks.ReentrantReadWriteLock;
|
import java.util.concurrent.locks.ReentrantReadWriteLock;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -37,13 +34,9 @@ import java.util.concurrent.locks.ReentrantReadWriteLock;
|
|||||||
* @param <T> 生成范围对象的类型
|
* @param <T> 生成范围对象的类型
|
||||||
* @author Looly
|
* @author Looly
|
||||||
*/
|
*/
|
||||||
public class Range<T> implements Iterable<T>, Iterator<T>, Serializable {
|
public class Range<T> implements Iterable<T>, Serializable {
|
||||||
private static final long serialVersionUID = 1L;
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
/**
|
|
||||||
* 锁保证线程安全
|
|
||||||
*/
|
|
||||||
private Lock lock = new ReentrantLock();
|
|
||||||
/**
|
/**
|
||||||
* 起始对象
|
* 起始对象
|
||||||
*/
|
*/
|
||||||
@ -52,18 +45,11 @@ public class Range<T> implements Iterable<T>, Iterator<T>, Serializable {
|
|||||||
* 结束对象
|
* 结束对象
|
||||||
*/
|
*/
|
||||||
private final T end;
|
private final T end;
|
||||||
/**
|
|
||||||
* 下一个对象
|
|
||||||
*/
|
|
||||||
private T next;
|
|
||||||
/**
|
/**
|
||||||
* 步进
|
* 步进
|
||||||
*/
|
*/
|
||||||
private final Stepper<T> stepper;
|
private final Stepper<T> stepper;
|
||||||
/**
|
|
||||||
* 索引
|
|
||||||
*/
|
|
||||||
private int index = 0;
|
|
||||||
/**
|
/**
|
||||||
* 是否包含第一个元素
|
* 是否包含第一个元素
|
||||||
*/
|
*/
|
||||||
@ -108,51 +94,45 @@ public class Range<T> implements Iterable<T>, Iterator<T>, Serializable {
|
|||||||
this.start = start;
|
this.start = start;
|
||||||
this.end = end;
|
this.end = end;
|
||||||
this.stepper = stepper;
|
this.stepper = stepper;
|
||||||
this.next = safeStep(this.start);
|
|
||||||
this.includeStart = isIncludeStart;
|
this.includeStart = isIncludeStart;
|
||||||
this.includeEnd = isIncludeEnd;
|
this.includeEnd = isIncludeEnd;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Iterator<T> iterator() {
|
||||||
|
return new Iterator<T>(){
|
||||||
/**
|
/**
|
||||||
* 禁用锁,调用此方法后不再使用锁保护
|
* 下一个对象
|
||||||
*
|
|
||||||
* @return this
|
|
||||||
* @since 4.3.1
|
|
||||||
*/
|
*/
|
||||||
public Range<T> disableLock() {
|
private T next = safeStep(start);
|
||||||
this.lock = new NoLock();
|
/**
|
||||||
return this;
|
* 索引
|
||||||
}
|
*/
|
||||||
|
private int index = 0;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean hasNext() {
|
public boolean hasNext() {
|
||||||
lock.lock();
|
if (0 == this.index && includeStart) {
|
||||||
try {
|
|
||||||
if (0 == this.index && this.includeStart) {
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (null == this.next) {
|
if (null == this.next) {
|
||||||
return false;
|
return false;
|
||||||
} else if (!includeEnd && this.next.equals(this.end)) {
|
} else {
|
||||||
return false;
|
return includeEnd || !this.next.equals(end);
|
||||||
}
|
}
|
||||||
} finally {
|
|
||||||
lock.unlock();
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public T next() {
|
public T next() {
|
||||||
lock.lock();
|
|
||||||
try {
|
|
||||||
if (!this.hasNext()) {
|
if (!this.hasNext()) {
|
||||||
throw new NoSuchElementException("Has no next range!");
|
throw new NoSuchElementException("Has no next range!");
|
||||||
}
|
}
|
||||||
return nextUncheck();
|
return nextUncheck();
|
||||||
} finally {
|
|
||||||
lock.unlock();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void remove() {
|
||||||
|
throw new UnsupportedOperationException("Can not remove ranged element!");
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -162,7 +142,7 @@ public class Range<T> implements Iterable<T>, Iterator<T>, Serializable {
|
|||||||
final T current;
|
final T current;
|
||||||
if(0 == this.index){
|
if(0 == this.index){
|
||||||
current = start;
|
current = start;
|
||||||
if(!this.includeStart){
|
if(!includeStart){
|
||||||
// 获取下一组元素
|
// 获取下一组元素
|
||||||
index ++;
|
index ++;
|
||||||
return nextUncheck();
|
return nextUncheck();
|
||||||
@ -186,38 +166,14 @@ public class Range<T> implements Iterable<T>, Iterator<T>, Serializable {
|
|||||||
final int index = this.index;
|
final int index = this.index;
|
||||||
T next = null;
|
T next = null;
|
||||||
try {
|
try {
|
||||||
next = stepper.step(base, this.end, index);
|
next = stepper.step(base, end, index);
|
||||||
} catch (final Exception e) {
|
} catch (final Exception e) {
|
||||||
// ignore
|
// ignore
|
||||||
}
|
}
|
||||||
|
|
||||||
return next;
|
return next;
|
||||||
}
|
}
|
||||||
|
};
|
||||||
@Override
|
|
||||||
public void remove() {
|
|
||||||
throw new UnsupportedOperationException("Can not remove ranged element!");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Iterator<T> iterator() {
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 重置Range
|
|
||||||
*
|
|
||||||
* @return this
|
|
||||||
*/
|
|
||||||
public Range<T> reset() {
|
|
||||||
lock.lock();
|
|
||||||
try {
|
|
||||||
this.index = 0;
|
|
||||||
this.next = safeStep(this.start);
|
|
||||||
} finally {
|
|
||||||
lock.unlock();
|
|
||||||
}
|
|
||||||
return this;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -247,4 +203,9 @@ public class Range<T> implements Iterable<T>, Iterator<T>, Serializable {
|
|||||||
*/
|
*/
|
||||||
T step(T current, T end, int index);
|
T step(T current, T end, int index);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "Range [start=" + start + ", end=" + end + "]";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -25,6 +25,7 @@ import org.junit.jupiter.api.Test;
|
|||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
|
import java.util.Iterator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
public class Issue3081Test {
|
public class Issue3081Test {
|
||||||
@ -35,10 +36,10 @@ public class Issue3081Test {
|
|||||||
final Date end = DateUtil.parse("2023-04-25 00:00:00");
|
final Date end = DateUtil.parse("2023-04-25 00:00:00");
|
||||||
|
|
||||||
final DateRange dateTimes = new DateRange(start, end, DateField.DAY_OF_MONTH, 30, true, true);
|
final DateRange dateTimes = new DateRange(start, end, DateField.DAY_OF_MONTH, 30, true, true);
|
||||||
|
final Iterator<DateTime> iterator = dateTimes.iterator();
|
||||||
final List<DateTime> dateTimeList = new ArrayList<>();
|
final List<DateTime> dateTimeList = new ArrayList<>();
|
||||||
while (dateTimes.hasNext()) {
|
while (iterator.hasNext()) {
|
||||||
dateTimeList.add(dateTimes.next());
|
dateTimeList.add(iterator.next());
|
||||||
}
|
}
|
||||||
Assertions.assertEquals(4, dateTimeList.size());
|
Assertions.assertEquals(4, dateTimeList.size());
|
||||||
|
|
||||||
|
@ -0,0 +1,41 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2024 Hutool Team and hutool.cn
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.dromara.hutool.core.date;
|
||||||
|
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class IssueIB8OFSTest {
|
||||||
|
@Test
|
||||||
|
void rangeTest() {
|
||||||
|
DateRange startRange = DateUtil.range(
|
||||||
|
DateUtil.parse("2017-01-01"),
|
||||||
|
DateUtil.parse("2017-01-31"), DateField.DAY_OF_YEAR);
|
||||||
|
DateRange endRange = DateUtil.range(
|
||||||
|
DateUtil.parse("2017-01-31"),
|
||||||
|
DateUtil.parse("2017-02-02"), DateField.DAY_OF_YEAR);
|
||||||
|
|
||||||
|
List<DateTime> dateTimes = DateUtil.rangeContains(startRange, endRange);
|
||||||
|
System.out.println("交集: ");
|
||||||
|
dateTimes.forEach(System.out::println);
|
||||||
|
|
||||||
|
List<DateTime> dateNotTimes = DateUtil.rangeNotContains(startRange, endRange);
|
||||||
|
System.out.println("差集: ");
|
||||||
|
dateNotTimes.forEach(System.out::println);
|
||||||
|
}
|
||||||
|
}
|
@ -25,6 +25,7 @@ import org.junit.jupiter.api.Assertions;
|
|||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
|
import java.util.Iterator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.NoSuchElementException;
|
import java.util.NoSuchElementException;
|
||||||
|
|
||||||
@ -47,11 +48,12 @@ public class RangeTest {
|
|||||||
return current.offsetNew(DateField.DAY_OF_YEAR, 1);
|
return current.offsetNew(DateField.DAY_OF_YEAR, 1);
|
||||||
});
|
});
|
||||||
|
|
||||||
Assertions.assertTrue(range.hasNext());
|
final Iterator<DateTime> iterator = range.iterator();
|
||||||
Assertions.assertEquals(DateUtil.parse("2017-01-01"), range.next());
|
Assertions.assertTrue(iterator.hasNext());
|
||||||
Assertions.assertTrue(range.hasNext());
|
Assertions.assertEquals(DateUtil.parse("2017-01-01"), iterator.next());
|
||||||
Assertions.assertEquals(DateUtil.parse("2017-01-02"), range.next());
|
Assertions.assertTrue(iterator.hasNext());
|
||||||
Assertions.assertFalse(range.hasNext());
|
Assertions.assertEquals(DateUtil.parse("2017-01-02"), iterator.next());
|
||||||
|
Assertions.assertFalse(iterator.hasNext());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@ -86,23 +88,24 @@ public class RangeTest {
|
|||||||
final Date end = DateUtil.parse("2021-03-31");
|
final Date end = DateUtil.parse("2021-03-31");
|
||||||
|
|
||||||
final DateRange range = DateUtil.range(start, end, DateField.MONTH);
|
final DateRange range = DateUtil.range(start, end, DateField.MONTH);
|
||||||
|
final Iterator<DateTime> iterator = range.iterator();
|
||||||
Assertions.assertTrue(range.hasNext());
|
Assertions.assertTrue(iterator.hasNext());
|
||||||
Assertions.assertEquals(DateUtil.parse("2021-01-31"), range.next());
|
Assertions.assertEquals(DateUtil.parse("2021-01-31"), iterator.next());
|
||||||
Assertions.assertTrue(range.hasNext());
|
Assertions.assertTrue(iterator.hasNext());
|
||||||
Assertions.assertEquals(DateUtil.parse("2021-02-28"), range.next());
|
Assertions.assertEquals(DateUtil.parse("2021-02-28"), iterator.next());
|
||||||
Assertions.assertTrue(range.hasNext());
|
Assertions.assertTrue(iterator.hasNext());
|
||||||
Assertions.assertEquals(DateUtil.parse("2021-03-31"), range.next());
|
Assertions.assertEquals(DateUtil.parse("2021-03-31"), iterator.next());
|
||||||
Assertions.assertFalse(range.hasNext());
|
Assertions.assertFalse(iterator.hasNext());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void intRangeTest() {
|
public void intRangeTest() {
|
||||||
final Range<Integer> range = new Range<>(1, 1, (current, end, index) -> current >= end ? null : current + 10);
|
final Range<Integer> range = new Range<>(1, 1, (current, end, index) -> current >= end ? null : current + 10);
|
||||||
|
final Iterator<Integer> iterator = range.iterator();
|
||||||
|
|
||||||
Assertions.assertTrue(range.hasNext());
|
Assertions.assertTrue(iterator.hasNext());
|
||||||
Assertions.assertEquals(Integer.valueOf(1), range.next());
|
Assertions.assertEquals(Integer.valueOf(1), iterator.next());
|
||||||
Assertions.assertFalse(range.hasNext());
|
Assertions.assertFalse(iterator.hasNext());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@ -112,19 +115,21 @@ public class RangeTest {
|
|||||||
|
|
||||||
// 测试包含开始和结束情况下步进为1的情况
|
// 测试包含开始和结束情况下步进为1的情况
|
||||||
DateRange range = DateUtil.range(start, end, DateField.DAY_OF_YEAR);
|
DateRange range = DateUtil.range(start, end, DateField.DAY_OF_YEAR);
|
||||||
Assertions.assertEquals(range.next(), DateUtil.parse("2017-01-01"));
|
Iterator<DateTime> iterator = range.iterator();
|
||||||
Assertions.assertEquals(range.next(), DateUtil.parse("2017-01-02"));
|
Assertions.assertEquals(iterator.next(), DateUtil.parse("2017-01-01"));
|
||||||
Assertions.assertEquals(range.next(), DateUtil.parse("2017-01-03"));
|
Assertions.assertEquals(iterator.next(), DateUtil.parse("2017-01-02"));
|
||||||
|
Assertions.assertEquals(iterator.next(), DateUtil.parse("2017-01-03"));
|
||||||
try {
|
try {
|
||||||
range.next();
|
iterator.next();
|
||||||
Assertions.fail("已超过边界,下一个元素不应该存在!");
|
Assertions.fail("已超过边界,下一个元素不应该存在!");
|
||||||
} catch (final NoSuchElementException ignored) {
|
} catch (final NoSuchElementException ignored) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// 测试多步进的情况
|
// 测试多步进的情况
|
||||||
range = new DateRange(start, end, DateField.DAY_OF_YEAR, 2);
|
range = new DateRange(start, end, DateField.DAY_OF_YEAR, 2);
|
||||||
Assertions.assertEquals(DateUtil.parse("2017-01-01"), range.next());
|
iterator = range.iterator();
|
||||||
Assertions.assertEquals(DateUtil.parse("2017-01-03"), range.next());
|
Assertions.assertEquals(DateUtil.parse("2017-01-01"), iterator.next());
|
||||||
|
Assertions.assertEquals(DateUtil.parse("2017-01-03"), iterator.next());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@ -134,11 +139,12 @@ public class RangeTest {
|
|||||||
|
|
||||||
// 测试不包含开始结束时间的情况
|
// 测试不包含开始结束时间的情况
|
||||||
final DateRange range = new DateRange(start, end, DateField.DAY_OF_YEAR, 1, false, false);
|
final DateRange range = new DateRange(start, end, DateField.DAY_OF_YEAR, 1, false, false);
|
||||||
Assertions.assertEquals(DateUtil.parse("2017-01-02"), range.next());
|
final Iterator<DateTime> iterator = range.iterator();
|
||||||
Assertions.assertEquals(DateUtil.parse("2017-01-03"), range.next());
|
Assertions.assertEquals(DateUtil.parse("2017-01-02"), iterator.next());
|
||||||
Assertions.assertEquals(DateUtil.parse("2017-01-04"), range.next());
|
Assertions.assertEquals(DateUtil.parse("2017-01-03"), iterator.next());
|
||||||
|
Assertions.assertEquals(DateUtil.parse("2017-01-04"), iterator.next());
|
||||||
try {
|
try {
|
||||||
range.next();
|
iterator.next();
|
||||||
Assertions.fail("不包含结束时间情况下,下一个元素不应该存在!");
|
Assertions.fail("不包含结束时间情况下,下一个元素不应该存在!");
|
||||||
} catch (final NoSuchElementException ignored) {
|
} catch (final NoSuchElementException ignored) {
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user