使用 Joda 在两个日期范围之间迭代

Iterate between two date range using Joda

在我的代码中,我需要使用 Joda 在一系列日期之间进行迭代,我已经试过了:

for(LocalDate currentdate = startDate; currenDate.isBefore(endDate); currenDate= currenDate.plusDays(1)){
    System.out.println(currentdate);
}

上面的代码可以工作,但是当 currenDate 到达 endDate 的前一天时迭代停止。我想要实现的是当 currentDateendDate.

完全相同时迭代停止
for(Date currentdate = startDate; currentdate <= endDate; currentdate++){
    System.out.println(currentdate );
}

我知道上面的代码是不可能的,但我这样做是为了弄清楚我想要什么。

不确定 joda 类型,但您可以在 Calendar API, here & here 的间隔(秒、分钟、小时、日、月、年)进行迭代

如果您希望循环在您的迭代日期与今天的日期相同时停止,您可以为此使用相等性检查。

在 LocalDate

上查看 .equals()

这是一个简单的例子:

public class DateIterator {

    public static void main(String[] args) {

        LocalDate lastMonth = LocalDate.now().minusMonths(1);
        LocalDate lastWeek = LocalDate.now().minusWeeks(1);
        LocalDate yesterday = LocalDate.now().minusDays(1);
        LocalDate today = LocalDate.now();
        LocalDate tomorrow = LocalDate.now().plusDays(1);

        List<LocalDate> dates = Arrays.asList(lastMonth, lastWeek, yesterday, today, tomorrow);

        for (LocalDate date : dates) {
            if (date.isEqual(today)) {
                System.out.println("Date is equal to todays date! Break out, or do something else here");
            } else if (date.isBefore(today)) {
                System.out.println("The date " + date.toString() + " is in the past");
            } else {
                System.out.println("The date " + date.toString() + " is in the future");
            }
        }
    }
}

输出为:

The date 2015-02-25 is in the past
The date 2015-03-18 is in the past
The date 2015-03-24 is in the past
Date is equal to todays date! Break out, or do something else here
The date 2015-03-26 is in the future

显然,如果相等性检查通过,您将需要跳出循环等。

这是另一个使用特定日期并每次递增 1 天的方法,我认为这更像您想要的

public class DateIterator {

    public static void main(String[] args) {

        LocalDate specificDate = LocalDate.now().minusWeeks(1);
        LocalDate today = LocalDate.now();

        boolean matchFound = false;
        while (!matchFound) {
            if (!specificDate.isEqual(today)) {
                System.out.println(specificDate.toString() + " is in the past, incrementing day and checking again...");
                specificDate = specificDate.plusDays(1);
            } else {
                System.out.println("Date matches today!");
                matchFound = true;
            }
        }
    }
}

输出:

2015-03-18 is in the past, incrementing day and checking again...
2015-03-19 is in the past, incrementing day and checking again...
2015-03-20 is in the past, incrementing day and checking again...
2015-03-21 is in the past, incrementing day and checking again...
2015-03-22 is in the past, incrementing day and checking again...
2015-03-23 is in the past, incrementing day and checking again...
2015-03-24 is in the past, incrementing day and checking again...
Date matches today!

实际上有一个简单的方法可以解决您发布的原始代码,请参阅下面我的实现,只是修改了您的 for 循环实现:

    //test data
    LocalDate startDate = LocalDate.now(); //get current date
    LocalDate endDate = startDate.plusDays(5); //add 5 days to current date

    System.out.println("startDate : " + startDate);
    System.out.println("endDate : " + endDate);

    for(LocalDate currentdate = startDate; 
            currentdate.isBefore(endDate) || currentdate.isEqual(endDate); 
            currentdate= currentdate.plusDays(1)){
        System.out.println(currentdate);
    }

下面是输出(关于我的 localDate):

开始日期:2015-03-26
结束日期:2015-03-31
2015-03-26
2015-03-27
2015-03-28
2015-03-29
2015-03-30
2015-03-31

希望对您有所帮助!干杯。 :)

如果您希望循环包含结束日期,您可以使用 !currentDate.isAfter( endDate )。这在逻辑上等同于 currentDate.isBefore(endDate) || currentDate.equals(endDate).

以下示例将打印 6/1/2017 到 6/10/2017。

LocalDate startDate = new LocalDate( 2017, 6, 1 );
LocalDate endDate = new LocalDate( 2017, 6, 10 );
for ( LocalDate currentDate = startDate; !currentDate.isAfter( endDate ); currentDate = currentDate.plusDays( 1 ) )
{
    System.out.println( currentDate );
}

使用java.time

Joda-Time project is now in maintenance mode, with the team advising migration to the java.time classes. See Tutorial by Oracle.

LocalDate class 表示没有时间和时区的仅日期值。

LocalDate start = LocalDate.of( 2017 , Month.JANUARY , 23 ) ;
LocalDate stop = LocalDate.of( 2017 , Month.FEBRUARY , 2 ) ;

顺便说一下,您可能想要添加完整性检查以验证结尾不在开头之前。

不在

之后

我相信您正在寻找的逻辑(包括结束日期)是“不在”之后。 LocalDate class 包含一个 isAfter 方法,您可以向其中添加逻辑“NOT”(!)。

此外,在这种情况下,while 循环似乎比 for 循环更合适且不言自明。

LocalDate ld = start ;
List<LocalDate> dates = new ArrayList<>() ;
while ( ! ld.isAfter( stop ) ) {
    dates.add( ld ); // Collect this date.
    ld = ld.plusDays( 1 ) ;  // Setup the next loop.
}

看到这个code run live at IdeOne.com

dates: [2017-01-23, 2017-01-24, 2017-01-25, 2017-01-26, 2017-01-27, 2017-01-28, 2017-01-29, 2017-01-30, 2017-01-31, 2017-02-01, 2017-02-02]

半开

the iteration stops when currentDate reaches the day before endDate

这其实是可取的。称为半开,日期时间处理中的常见方法是将开始视为 包含 ,而结尾为 不包含 。因此午休时间从 12:00:00(中午)开始,一直持续到 13:00:00(下午 1 点),但不包括在内。一月份从 1 月 1 日开始,一直到但不包括 2 月 1 日。一周从星期一开始,一直到但不包括下一个星期一。最有用的是,这种方法避免了确定日期时间的最后一秒的问题,其中一些系统使用毫秒(x.999),一些(x.999999),相同的纳秒(x.999999999),而其他系统使用诸如作为 5 个小数位 (x.99999)。相反,我们上升到但不包括下一小时或一天的第一时刻等

我发现在我的代码中始终如一地使用半开方法可以使代码更易于阅读、更容易理解,并且不太可能导致差一错误。我陷入了无数财务神秘问题,这些问题最终证明是对包含包含日期和不包含日期的日期的报告的混淆或误解。因此,如果可能,请训练您的用户始终如一地以半开放方式思考。如果不可行,请调整您的代码,使您的逻辑和循环至少在内部使用半开。

这里的代码与上面类似,但使用 isBefore 而不是 NOT isAfter,以使用半开方法。结束日期是 2 月 3 日,而不是 2 月 2 日。

LocalDate start = LocalDate.of( 2017 , Month.JANUARY , 23 ) ;
LocalDate stop = LocalDate.of( 2017 , Month.FEBRUARY , 3 ) ;  // Third instead of the Second of February, to be half-open.

LocalDate ld = start ;
List<LocalDate> dates = new ArrayList<>() ;
while ( ld.isBefore( stop ) ) {  // Using "isBefore" for Half-Open approach.
    dates.add( ld ); // Collect this date.
    ld = ld.plusDays( 1 ) ;  // Setup the next loop.
}

看到这个code run live at IdeOne.com

start: 2017-01-23 | stop: 2017-02-03

dates: [2017-01-23, 2017-01-24, 2017-01-25, 2017-01-26, 2017-01-27, 2017-01-28, 2017-01-29, 2017-01-30, 2017-01-31, 2017-02-01, 2017-02-02]


关于java.time

java.time framework is built into Java 8 and later. These classes supplant the troublesome old legacy date-time classes such as java.util.Date, Calendar, & SimpleDateFormat.

Joda-Time project, now in maintenance mode, advises migration to the java.time classes.

要了解更多信息,请参阅 Oracle Tutorial. And search Stack Overflow for many examples and explanations. Specification is JSR 310

在哪里获取java.time classes?

ThreeTen-Extra project extends java.time with additional classes. This project is a proving ground for possible future additions to java.time. You may find some useful classes here such as Interval, YearWeek, YearQuarter, and more.

最终采用了这个解决方案:

Range.inclusive(3, 0).map(i => LocalDate.now.minusDays(i)).foreach()