如何查找给定月份的日期范围

How to Find date ranges for given months

我想查找给定月份列表的日期范围。我写的代码是

List<String> allDates = new ArrayList<>();
                String maxDate = "2017-11-06";
                SimpleDateFormat monthDate = new SimpleDateFormat("yyyy-MM-dd");
                Calendar cal = Calendar.getInstance();
                cal.setTime(monthDate.parse(maxDate));

            for (int i = 1; i <= 14; i++) {
                    String month_name1 = monthDate.format(cal.getTime());
                    allDates.add(month_name1);
                    cal.add(Calendar.MONTH, -1);
                }
                for (int j = 0; j < allDates.size() - 1; j++) {
                    JSONObject dateRange = new JSONObject();
                    dateRange.put("until", allDates.get(j)); 
                    System.out.println("to date:"+allDates.get(j));
                    dateRange.put("since", allDates.get(j + 1));
                    System.out.println("from date:"+ allDates.get(j + 1));

                }

我得到了:

to date:2017-11-06
from date:2017-10-06
to date:2017-10-06
from date:2017-09-06
to date:2017-09-06
from date:2017-08-06
to date:2017-08-06
from date:2017-07-06
to date:2017-07-06
from date:2017-06-06
to date:2017-06-06

但我想要这种格式:

to date:2017-11-06
from date:2017-10-06
to date:2017-10-05
from date:2017-09-05
to date:2017-09-04
from date:2017-08-04
to date:2017-08-03
from date:2017-07-03
to date:2017-07-02
from date:2017-06-02

您每个月只在 allDates 列表中存储一个字符串,并尝试将其用作 "to date" 和 "from date",这两个日期将以相同的字符串结尾。您应该为每个到和从日期添加两个不同的字符串。我已经相应地修改了你的循环:

    for (int i = 1; i <= 14; i++) {              
        String month_name1 = monthDate.format(cal.getTime());            
        allDates.add(month_name1);
        cal.add(Calendar.MONTH, -1);
        month_name1 = monthDate.format(cal.getTime());
        allDates.add(month_name1);            
        cal.add(Calendar.DATE, -1);   
    }
    for (int j = 0; j < allDates.size() - 1; j+=2) {
        JSONObject dateRange = new JSONObject();
        dateRange.put("until", allDates.get(j)); 
        System.out.println("to date:"+allDates.get(j));
        dateRange.put("since", allDates.get(j + 1));
        System.out.println("from date:"+ allDates.get(j + 1));
    }

每个范围只存储一个日期是可以的。标准方法是使用 半开范围 以便每个范围从一个存储日期 包含 到下一个日期 不包含.

我建议您存储日期而不是字符串。我发现每当需要字符串时格式化日期比每次需要日期时都解析字符串(并考虑解析中的任何异常)更自然。

我衷心建议跳过过时的 classes SimpleDateFormatCalendar 并使用 the modern Java date and time API known as java.time or JSR-310。正如您将看到的,后者更易于使用。

java.timeLocalDate class 非常符合我们存储没有时间的日期的需要。另一个优点是它的 toString 方法生成一个类似于 2017-10-06 的字符串,这是您在 JSON 对象中使用的格式,因此不再需要显式格式化程序(这可能不是巧合: 该格式是 ISO 8601 标准的一部分,该标准越来越多地用于日期和时间信息的交换,尤其是在 JSON 中)。此外,使用 LocalDate 比使用 Calendar 更自然地加减一天和一个月,只要您记住每次都会创建一个新对象。

    // store only the start date of each range
    List<LocalDate> allStartDates = new ArrayList<>();
    // add 1 day ot the last end date to obtain the start day of the following range
    LocalDate currentStartDate = LocalDate.of(2017, Month.NOVEMBER, 06).plusDays(1);

    for (int i = 1; i <= 14; i++) {
        allStartDates.add(currentStartDate);
        currentStartDate = currentStartDate.minusDays(1).minusMonths(1);
    }
    for (int j = 1; j < allStartDates.size(); j++) {
        JSONObject dateRange = new JSONObject();
        // subtract 1 day from the start day of the following range
        // to get the last day of this range 
        String endDate = allStartDates.get(j - 1).minusDays(1).toString();
        dateRange.put("until", endDate); 
        System.out.println("to date:" + endDate);
        String startDate = allStartDates.get(j).toString();
        dateRange.put("since", startDate);
        System.out.println("from date:" + startDate);
    }

输出为:

to date:2017-11-06
from date:2017-10-06
to date:2017-10-05
from date:2017-09-05
to date:2017-09-04
from date:2017-08-04
to date:2017-08-03
from date:2017-07-03
to date:2017-07-02
from date:2017-06-02
to date:2017-06-01
from date:2017-05-01
to date:2017-04-30
from date:2017-03-30
to date:2017-03-29
from date:2017-02-28
to date:2017-02-27
from date:2017-01-27
to date:2017-01-26
from date:2016-12-26
to date:2016-12-25
from date:2016-11-25
to date:2016-11-24
from date:2016-10-24
to date:2016-10-23
from date:2016-09-23

问题:我的 Java 版本可以使用现代 API 吗?

如果至少使用 Java 6,则可以。

  • 在 Java 8 和更高版本中内置了新的 API。
  • 在Java中6和7得到the ThreeTen Backport, the backport of the new classes (ThreeTen for JSR 310).
  • 在 Android 上,使用 ThreeTen Backport 的 Android 版本。它叫做 ThreeTenABP,我认为 .
  • 中有精彩的解释