我需要在我的脚本中通过一系列日期执行一些操作,给定一个起始和结束日期。
请为我提供使用Java实现此功能的指导。
for ( currentDate = starDate; currentDate < endDate; currentDate++) {
}
我知道上面的代码根本不可能实现,但我这样做是为了向您展示我想要实现的内容。
嗯,你可以使用Java 8的时间API来解决这个问题,特别是可以使用java.time.LocalDate
(或者对于Java 7及更早版本可以使用等效的Joda Time类)。
for (LocalDate date = startDate; date.isBefore(endDate); date = date.plusDays(1))
{
...
}
我会强烈推荐使用java.time
(或Joda Time)而不是内置的Date
/Calendar
类。
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)
。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);
这本质上是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);
}
Apache Commons
for (Date dateIter = fromDate; !dateIter.after(toDate); dateIter = DateUtils.addDays(dateIter, 1)) {
// ...
}
addDays(..)
,它甚至可以更短。 - Priidu Neemre目前为止,之前的回答似乎仅考虑了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
你可以像我展示的那样使用方法引用System.out::println
,同样地,你也可以迭代多年。
LocalDate.datesUntil(LocalDate)
文档——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 20 00:00:00 IST 2010,Tue Dec 21 00:00:00 IST 2010,Wed Dec 22 00:00:00 IST 2010,Thu Dec 23 00:00:00 IST 2010,Fri Dec 24 00:00:00 IST 2010,Sat Dec 25 00:00:00 IST 2010]
[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]
Date
和Calendar
类多年前被java.time类所取代。具体来说,被Instant
和ZonedDateTime
替代。 - Basil Bourqueprivate 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
}
}
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);
}
}
这是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