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

时间:2010-12-26 18:22:02

标签: java date iteration

在我的脚本中,我需要在给定开始和结束日期的日期范围内执行一系列操作 请向我提供使用Java实现此目的的指导。

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

}

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

15 个答案:

答案 0 :(得分:166)

嗯,您可以使用Java 8's time-API执行此类操作,特别针对此问题java.time.LocalDate(或Java 7及更早版本的等效Joda Time类)

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

彻底建议在内置java.time / Date类上使用Calendar(或Joda Time)。

答案 1 :(得分:138)

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");

如果您还没有使用Java8,那么这是遗留的java.util.Calendar方法:

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)

答案 2 :(得分:65)

Java 8 样式,使用java.time类:

// 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);
}

Java 9 添加了datesUntil()方法:

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

答案 3 :(得分:25)

这与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);
}

答案 4 :(得分:4)

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
    }

}

答案 5 :(得分:4)

Apache Commons

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

答案 6 :(得分:3)

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);
    }
}

答案 7 :(得分:2)

这是Java 8代码。我认为此代码可以解决您的问题。快乐编码

    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

答案 8 :(得分:2)

为什么不使用epoch并轻松循环。

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);

    }

答案 9 :(得分:1)

我们可以将逻辑迁移到 Java 7,Java 8和Java 9 的各种方法:

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);

输出为:

  

[IST 2010年12月20日星期一00:00:00,星期二12月21日00:00:00 IST 2010年12月3日   IST 2010,星期四12月23日00:00:00 IST 2010,星期五12月24日00:00:00   IST 2010,00:00:00,2010年12月25日星期六,00:00:00]]

     

[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]

答案 10 :(得分:1)

您可以尝试以下方法:

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

答案 11 :(得分:0)

这将帮助您在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());
        }
}

答案 12 :(得分:0)

你可以编写一个类似的类(实现迭代器接口)并迭代它。

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();

}

答案 13 :(得分:0)

以下代码段(使用Java 8的 java.time.format )可用于遍历日期范围:

    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()来增加时间单位。 上图显示了一天的增量。

答案 14 :(得分:0)

它内置于:LocalDate.datesUntil(),自 Java 9 起

到目前为止,答案似乎只考虑了 Java 8 及更早版本。 Java 9+ 的方式是:

    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 放在演示中一样。

链接