如何在Java中获取两个日期之间的月份列表

4

我正在尝试在 Java 中获取两个日期之间的月份列表(实际上是这些月份的第一天),但我没有得到预期的结果。

起始日期为 "2020年3月17日",结束日期为 "2021年3月17日",预期结果如下:

"01-Mar-2020"
"01-Apr-2020"
"01-May-2020"
"01-Jun-2020"
"01-Jul-2020"
"01-Aug-2020"
"01-Sep-2020"
"01-Oct-2020"
"01-Nov-2020"
"01-Dec-2020"
"01-Jan-2021"
"01-Feb-2021"
"01-Mar-2021"

下面是我正在使用的代码:

import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;

public class Main {
   public static void main(String[] args) {
       String date1 = "3/17/2020";
       String date2 = "3/17/2021";

    DateFormat formater = new SimpleDateFormat("MM/dd/yyyy");

    Calendar beginCalendar = Calendar.getInstance();
    Calendar finishCalendar = Calendar.getInstance();

    try {
        beginCalendar.setTime(formater.parse(date1));
        finishCalendar.setTime(formater.parse(date2));
    } catch (ParseException e) {
        e.printStackTrace();
    }
  DateFormat formaterYd = new SimpleDateFormat("01-MMM-YYYY");


    while (beginCalendar.before(finishCalendar)) {
        // add one month to date per loop
        String date =    formaterYd.format(beginCalendar.getTime()).toUpperCase();
        System.out.println(date);
        beginCalendar.add(Calendar.MONTH, 1);
       }
   }
}

使用上述代码,我得到了以下结果:

"01-Jan-2020"
"01-Feb-2020"
"01-Mar-2020"
"01-Apr-2020"
"01-May-2020"
"01-Jun-2020"
"01-Jul-2020"
"01-Aug-2020"
"01-Sep-2020"
"01-Oct-2020"
"01-Nov-2020"
"01-Dec-2020"

请帮助我理解问题,并提供Java 7的任何解决方案。


1
输入和输出与代码不一致。你能修复一下吗? - Federico klez Culloca
3
朝着正确方向迈出的一步是使用新的java.time包,不再应使用CalendarDate - jmizv
1
你的代码处理的是2015年的日期,而你的问题涉及到2020年的日期? - Sweeper
你只需要月份还是这些月份的第一天的日期? - deHaar
我已经编辑了问题,您能否请检查并帮助我回答? - kavya
显示剩余2条评论
3个回答

7
我建议您使用现代java.time日期时间API及其相应的格式化API(包,java.time.format),以执行此操作。从Trail: Date Time中了解有关现代日期时间API的更多信息。 java.util日期时间API和SimpleDateFormat已过时且容易出错。如果您尚未使用Java-8,则仍可以通过ThreeTenABP库使用Java-8日期时间API。

如果您正在Android上执行此操作,并且您的Android API级别仍未符合Java8,请检查通过解糖可用的Java 8+ API

import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoUnit;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;

public class Main {
    public static void main(String[] args) {
        // Test
        System.out.println(getDateList("3/17/2020",  "3/17/2021"));
    }

    static List<String> getDateList(String strStartDate, String strEndDate) {
        // Formatter for the input
        DateTimeFormatter inputFormatter = DateTimeFormatter.ofPattern("M/d/u");
        
        // Formatter for the output
        DateTimeFormatter outputFormatter = DateTimeFormatter.ofPattern("dd-MMM-uuuu");

        // Parse strings to LocalDate instances
        LocalDate startDate = LocalDate.parse(strStartDate, inputFormatter);
        LocalDate endDate = LocalDate.parse(strEndDate, inputFormatter);

        return Stream.iterate(startDate.withDayOfMonth(1), date -> date.plusMonths(1))
                .limit(ChronoUnit.MONTHS.between(startDate, endDate.plusMonths(1)))
                .map(date -> date.format(outputFormatter))
                .collect(Collectors.toList());
    }
}

输出:

[01-Mar-2020, 01-Apr-2020, 01-May-2020, 01-Jun-2020, 01-Jul-2020, 01-Aug-2020, 01-Sep-2020, 01-Oct-2020, 01-Nov-2020, 01-Dec-2020, 01-Jan-2021, 01-Feb-2021, 01-Mar-2021]

使用传统API:

import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;

public class Main {
    public static void main(String[] args) throws ParseException {
        // Test
        System.out.println(getDateList("3/17/2020", "3/17/2021"));
    }

    static List<String> getDateList(String strStartDate, String strEndDate) throws ParseException {
        // List to be populated and returned
        List<String> dateList = new ArrayList<>();

        // Formatter for the input
        DateFormat inputFormatter = new SimpleDateFormat("M/d/yyyy");

        // Formatter for the output
        DateFormat outputFormatter = new SimpleDateFormat("dd-MMM-yyyy");

        // Parse strings to LocalDate instances
        Date startDate = inputFormatter.parse(strStartDate);
        Date endDate = inputFormatter.parse(strEndDate);

        // Calendar to start with
        Calendar startWith = Calendar.getInstance();
        startWith.setTime(startDate);
        startWith.set(Calendar.DAY_OF_MONTH, 1);

        for (Calendar calendar = startWith; calendar.getTime().getTime() <= endDate.getTime(); calendar
                .add(Calendar.MONTH, 1)) {
            dateList.add(outputFormatter.format(calendar.getTime()));
        }

        return dateList;
    }
}

输出:

[01-Mar-2020, 01-Apr-2020, 01-May-2020, 01-Jun-2020, 01-Jul-2020, 01-Aug-2020, 01-Sep-2020, 01-Oct-2020, 01-Nov-2020, 01-Dec-2020, 01-Jan-2021, 01-Feb-2021, 01-Mar-2021]

4

Java7 解决方案:

public static void main(String[] args) throws ParseException {
    DateFormat df1 = new SimpleDateFormat("MM/dd/yyyy", Locale.US);
    Date dateFrom = df1.parse("3/17/2020");
    Date dateTo = df1.parse("3/17/2021");
    final Locale locale = Locale.US;

    DateFormat df2 = new SimpleDateFormat("MMM-yyyy", Locale.US);
    List<String> months = getListMonths(dateFrom, dateTo, locale, df2);

    for (String month : months)
        System.out.println(month.toUpperCase(locale));
}

public static List<String> getListMonths(Date dateFrom, Date dateTo, Locale locale, DateFormat df) {
    Calendar calendar = Calendar.getInstance(locale);
    calendar.setTime(dateFrom);

    List<String> months = new ArrayList<>();

    while (calendar.getTime().getTime() <= dateTo.getTime()) {
        months.add(df.format(calendar.getTime()));
        calendar.add(Calendar.MONTH, 1);
    }

    return months;
}

输出:

MAR-2020
APR-2020
MAY-2020
JUN-2020
JUL-2020
AUG-2020
SEP-2020
OCT-2020
NOV-2020
DEC-2020
JAN-2021
FEB-2021
MAR-2021

3
使用java.time.LocalDate:
public static List<LocalDate> diff(LocalDate start, LocalDate end) {
    return start
            .datesUntil(end)
            .filter(e -> e.getDayOfMonth() == 1)
            .collect(Collectors.toList());
}

diff(LocalDate.now(), LocalDate.of(2020, 12, 20))

输出:

[2020-10-01, 2020-11-01, 2020-12-01]

您可以使用 DateTimeFormatter 字符串日期转换为 LocalDate,反之亦然。 编辑
仅使用Java 7(修改了问题中给出的代码):
public static void main(String[] args) throws IOException {


    String date1 = "3/17/2020";
    String date2 = "3/17/2021";

    DateFormat formater = new SimpleDateFormat("MM/dd/yyyy");

    Calendar beginCalendar = Calendar.getInstance();
    Calendar finishCalendar = Calendar.getInstance();

    try {
        beginCalendar.setTime(formater.parse(date1));
        finishCalendar.setTime(formater.parse(date2));
    } catch (ParseException e) {
        e.printStackTrace();
    }
    DateFormat formaterYd = new SimpleDateFormat("dd-MMM-YYYY");
    

    // mind this condition in while
    while (beginCalendar.compareTo(finishCalendar) <= 0) {
        Calendar tmp = (Calendar)beginCalendar.clone();
        tmp.set(Calendar.DAY_OF_MONTH, 1);
        String date = formaterYd.format(tmp.getTime()).toUpperCase();
        System.out.println(date);
        beginCalendar.add(Calendar.MONTH, 1);
    }
}

嗨,Hemant,感谢您的快速回复。我不能使用Java 8。您能否请以Java 7为参考分享您的答案。谢谢。 - kavya
@kavya,我已经更新了答案,并加入了你的代码。 - Pratapi Hemant Patel

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接