如何在 Java 中迭代通过日期范围?

在我的脚本中,我需要通过一系列的日期来执行一系列的操作,给出一个开始和结束的日期。
请为我提供使用 Java 实现这一点的指导。

for ( currentDate = starDate; currentDate < endDate; currentDate++) {


}

我知道上面的代码简直是不可能的,但我这样做是为了向您展示我想要实现的目标。

161097 次浏览

对于这个问题,您可以使用 Java8的时间-API来做类似的事情,特别是 java.time.LocalDate(或者对于 Java7和更老版本来说等效的 乔达时间类)

for (LocalDate date = startDate; date.isBefore(endDate); date = date.plusDays(1))
{
...
}

我建议 彻底使用 java.time(或 Joda Time)而不是内置的 Date/Calendar类。

JodaTime 很不错,但是,为了完整起见和/或如果您更喜欢 API 提供的工具,这里有一些标准的 API 方法。

当开始使用 java.util.Date实例时,如下所示:

SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd");
Date startDate = formatter.parse("2010-12-20");
Date endDate = formatter.parse("2010-12-26");

以下是遗留的 java.util.Calendar方法,以防您还没有使用 Java8:

Calendar start = Calendar.getInstance();
start.setTime(startDate);
Calendar end = Calendar.getInstance();
end.setTime(endDate);


for (Date date = start.getTime(); start.before(end); start.add(Calendar.DATE, 1), date = start.getTime()) {
// Do your job here with `date`.
System.out.println(date);
}

下面是 Java8的 java.time.LocalDate方法,基本上就是 JodaTime 方法:

LocalDate start = startDate.toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
LocalDate end = endDate.toInstant().atZone(ZoneId.systemDefault()).toLocalDate();


for (LocalDate date = start; date.isBefore(end); date = date.plusDays(1)) {
// Do your job here with `date`.
System.out.println(date);
}

如果您想迭代 包容性的结束日期,那么分别使用 !start.after(end)!date.isAfter(end)

这与 BalusC 给出的答案基本相同,但是用 while 循环代替 for 循环更具可读性:

Calendar start = Calendar.getInstance();
start.setTime(startDate);


Calendar end = Calendar.getInstance();
end.setTime(endDate);


while( !start.after(end)){
Date targetDay = start.getTime();
// Do Work Here


start.add(Calendar.DATE, 1);
}
private static void iterateBetweenDates(Date startDate, Date endDate) {
Calendar startCalender = Calendar.getInstance();
startCalender.setTime(startDate);
Calendar endCalendar = Calendar.getInstance();
endCalendar.setTime(endDate);


for(; startCalender.compareTo(endCalendar)<=0;
startCalender.add(Calendar.DATE, 1)) {
// write your main logic here
}


}

Apache Commons

    for (Date dateIter = fromDate; !dateIter.after(toDate); dateIter = DateUtils.addDays(dateIter, 1)) {
// ...
}

Java8 样式,使用 爪哇时间类:

// Monday, February 29 is a leap day in 2016 (otherwise, February only has 28 days)
LocalDate start = LocalDate.parse("2016-02-28"),
end   = LocalDate.parse("2016-03-02");


// 4 days between (end is inclusive in this example)
Stream.iterate(start, date -> date.plusDays(1))
.limit(ChronoUnit.DAYS.between(start, end) + 1)
.forEach(System.out::println);

产出:

2016-02-28
2016-02-29
2016-03-01
2016-03-02

选择:

LocalDate next = start.minusDays(1);
while ((next = next.plusDays(1)).isBefore(end.plusDays(1))) {
System.out.println(next);
}

Java9 添加了 直至()方法:

start.datesUntil(end.plusDays(1)).forEach(System.out::println);

这是 Java8代码,我想这个代码可以解决你的问题

    LocalDate start = LocalDate.now();
LocalDate end = LocalDate.of(2016, 9, 1);//JAVA 9 release date
Long duration = start.until(end, ChronoUnit.DAYS);
System.out.println(duration);
// Do Any stuff Here there after
IntStream.iterate(0, i -> i + 1)
.limit(duration)
.forEach((i) -> {});
//old way of iteration
for (int i = 0; i < duration; i++)
System.out.print("" + i);// Do Any stuff Here
public static final void generateRange(final Date dateFrom, final Date dateTo)
{
final Calendar current = Calendar.getInstance();
current.setTime(dateFrom);


while (!current.getTime().after(dateTo))
{
// TODO


current.add(Calendar.DATE, 1);
}
}

这将帮助您开始30天回到和循环,直到今天的日期。你可以很容易地改变日期和方向的范围。

private void iterateThroughDates() throws Exception {
Calendar start = Calendar.getInstance();
start.add(Calendar.DATE, -30);
Calendar end = Calendar.getInstance();
for (Calendar date = start; date.before(end); date.add(Calendar.DATE, 1))
{
System.out.println(date.getTime());
}
}

为什么不使用时代和循环通过容易。

long startDateEpoch = new java.text.SimpleDateFormat("dd/MM/yyyy").parse(startDate).getTime() / 1000;


long endDateEpoch = new java.text.SimpleDateFormat("dd/MM/yyyy").parse(endDate).getTime() / 1000;




long i;
for(i=startDateEpoch ; i<=endDateEpoch; i+=86400){


System.out.println(i);


}

您可以编写类似的类(实现迭代器接口)并对其进行迭代。

public class DateIterator implements Iterator<Date>, Iterable<Date>
{


private Calendar end = Calendar.getInstance();
private Calendar current = Calendar.getInstance();


public DateIterator(Date start, Date end)
{
this.end.setTime(end);
this.end.add(Calendar.DATE, -1);
this.current.setTime(start);
this.current.add(Calendar.DATE, -1);
}


@Override
public boolean hasNext()
{
return !current.after(end);
}


@Override
public Date next()
{
current.add(Calendar.DATE, 1);
return current.getTime();
}


@Override
public void remove()
{
throw new UnsupportedOperationException(
"Cannot remove");
}


@Override
public Iterator<Date> iterator()
{
return this;
}
}

然后像这样使用它:

Iterator<Date> dateIterator = new DateIterator(startDate, endDate);
while(dateIterator.hasNext()){
Date selectedDate = dateIterator .next();


}

我们可以把逻辑迁移到不同的方法上:

public static List<Date> getDatesRangeJava7(Date startDate, Date endDate) {
List<Date> datesInRange = new ArrayList<>();
Calendar startCalendar = new GregorianCalendar();
startCalendar.setTime(startDate);
Calendar endCalendar = new GregorianCalendar();
endCalendar.setTime(endDate);
while (startCalendar.before(endCalendar)) {
Date result = startCalendar.getTime();
datesInRange.add(result);
startCalendar.add(Calendar.DATE, 1);
}
return datesInRange;
}


public static List<LocalDate> getDatesRangeJava8(LocalDate startDate, LocalDate endDate) {
int numOfDays = (int) ChronoUnit.DAYS.between(startDate, endDate);
return IntStream.range(0, numOfDays)
.mapToObj(startDate::plusDays)
.collect(Collectors.toList());
}


public static List<LocalDate> getDatesRangeJava9(LocalDate startDate, LocalDate endDate) {
return startDate.datesUntil(endDate).collect(Collectors.toList());
}

然后我们可以调用这些方法:

SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd");
Date startDate = formatter.parse("2010-12-20");
Date endDate = formatter.parse("2010-12-26");
List<Date> dateRangeList = getDatesRangeJava7(startDate, endDate);
System.out.println(dateRangeList);


LocalDate startLocalDate = startDate.toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
LocalDate endLocalDate = endDate.toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
List<LocalDate> dateRangeList8 = getDatesRangeJava8(startLocalDate, endLocalDate);
System.out.println(dateRangeList8);
List<LocalDate> dateRangeList9 = getDatesRangeJava8(startLocalDate, endLocalDate);
System.out.println(dateRangeList9);

产出将是:

[ Mon Dec 2000:00:00 IST 2010,Tue Dec 2100:00:00 IST 2010,Wed Dec 2010,Mon Dec 2000:00:00 IST 2010,Tue Dec 2100:00:00 IST 2010,Wed Dec 2010年12月23日星期四2010年12月24日星期五 2010年12月25日

[2010-12-20,2010-12-21,2010-12-22,2010-12-23,2010-12-24, 2010-12-25]

[2010-12-20,2010-12-21,2010-12-22,2010-12-23,2010-12-24, 2010-12-25]

你可以试试这个:

OffsetDateTime currentDateTime = OffsetDateTime.now();
for (OffsetDateTime date = currentDateTime; date.isAfter(currentDateTime.minusYears(YEARS)); date = date.minusWeeks(1))
{
...
}

下面的代码片段(使用 Java8的 格式)可能用于在一个日期范围内进行迭代:

    DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
// Any chosen date format maybe taken
LocalDate startDate = LocalDate.parse(startDateString,formatter);
LocalDate endDate = LocalDate.parse(endDateString,formatter);
if(endDate.isBefore(startDate))
{
//error
}
LocalDate itr = null;
for (itr = startDate; itr.isBefore(endDate)||itr.isEqual(itr); itr = itr.plusDays(1))
{
//Processing  goes here
}

可以选择 plusMonths ()/plusYears ()作为时间单位增量。 在上面的例子中增加一天。

从 Java 9开始,它就内置了: LocalDate.datesuntil ()

到目前为止,答案似乎只是在考虑 Java8或更早的版本,Java9 + 的方法是:

    LocalDate startDate = LocalDate.of(2021, Month.JUNE, 29);
LocalDate endDate = LocalDate.of(2021, Month.JULY, 3);
    

startDate.datesUntil(endDate).forEach(System.out::println);

此示例的输出如下:

2021-06-29
2021-06-30
2021-07-01
2021-07-02

虽然开始日期是包含在内的,但结束日期是独家的,正如我对你的问题的理解一样。如果有人想把截止日期包括在内,这很简单,只需在上面加上一天:

    startDate.datesUntil(endDate.plusDays(1)).forEach(System.out::println);
2021-06-29
2021-06-30
2021-07-01
2021-07-02
2021-07-03

您显然可以用这种方式迭代几年,就像您可以放置一个更长的 lambda 一样,其中我只是放置了方法引用 System.out::println进行演示。

连结