【问题标题】:Iterate between two date range using Joda使用 Joda 在两个日期范围之间进行迭代
【发布时间】:2015-03-25 01:43:03
【问题描述】:

在我的代码中,我需要使用 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 );
}

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

【问题讨论】:

标签: java date datetime jodatime


【解决方案1】:

其实你发布的原始代码有一个简单的方法,见下面我的实现,只是修改了你的 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.isEqual(endDate) 短。换句话说,使用“不大于”作为“小于或等于”的较短版本。有关完整示例,请参阅my Answer。我现在看到this Answer 有同样的想法,但在for 循环与我的while 循环中。
【解决方案2】:

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

在 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!

【讨论】:

  • 抱歉,我不明白您是在迭代日期数组,还是有固定数据并一次递增 1 天,但我已经给出了这两种情况的示例。 HTH
  • 感谢您的回复,您的第二个示例正在运行,谢谢:D
【解决方案3】:

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

以下示例将打印 2017 年 6 月 1 日到 2017 年 6 月 10 日。

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

【讨论】:

    【解决方案4】:

    使用 java.time

    Joda-Time 项目现在位于maintenance mode,团队建议迁移到java.time 类。见Tutorial by Oracle

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

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

    顺便说一句,您可能需要添加一个健全性检查来验证结尾不在开头之前。

    不是之后

    我相信您正在寻找的逻辑(包括结束日期)是“不在之后”。 LocalDate 类包含一个 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

    日期:[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]

    半开

    当 currentDate 到达 endDate 的前一天时,迭代停止

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

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

    这里的代码与上面类似,但使用isBefore 而不是NOT isAfter,以使用Half-Open 方法。结局是 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

    开始:2017-01-23 |停止:2017-02-03

    日期:[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 框架内置于 Java 8 及更高版本中。这些类取代了麻烦的旧 legacy 日期时间类,例如 java.util.DateCalendarSimpleDateFormat

    Joda-Time 项目现在位于maintenance mode,建议迁移到java.time 类。

    要了解更多信息,请参阅Oracle Tutorial。并在 Stack Overflow 上搜索许多示例和解释。规格为JSR 310

    从哪里获得 java.time 类?

    ThreeTen-Extra 项目通过附加类扩展了 java.time。该项目是未来可能添加到 java.time 的试验场。您可以在这里找到一些有用的类,例如IntervalYearWeekYearQuartermore

    【讨论】:

      【解决方案5】:

      不确定 joda 类型,但您可以使用 Calendar API 以间隔(秒、分钟、小时、日、月、年)进行迭代,herehere 是示例

      【讨论】:

        【解决方案6】:

        最终选择了这个解决方案:

        Range.inclusive(3, 0).map(i =&gt; LocalDate.now.minusDays(i)).foreach()

        【讨论】:

          猜你喜欢
          • 2010-11-13
          • 1970-01-01
          • 2021-12-14
          • 2023-03-30
          • 1970-01-01
          • 2019-02-14
          • 1970-01-01
          • 2021-10-23
          • 2020-02-20
          相关资源
          最近更新 更多