Java - create group of dates by Month from 2 dates

java 8 date between two dates
get list of months between two dates in java
java group dates by week
java group list of objects by date
java sql date to localdatetime
get months between two dates in java
get all dates between two dates java
group by java object

Using Java 8

Goal

From two dates (for example: firstDay 2018-09-01 and lastDay 2018-11-10), I would like to create two arrays of firstDay and lastDay created by month. For example:

List<LocalDate> firstDays = [2018-09-01,2018-10-01,2018-11-01]
List<LocalDate> lastDays = [2018-09-30, 2018-10-31,2018-11-10]

Eventually, I would like this method to apply also for years (for example: firstDay 2018-12-10 and lastDay 2019-01-06).

Issue

I don't now what to use to fullfill that goal. I'm still searching. Could you help me please?

In an iterative style, and handling edge cases:

LocalDate startDate = LocalDate.of(2018, 9, 1);
LocalDate endDate = LocalDate.of(2018, 11, 10);

List<LocalDate> firstDays = new ArrayList<>();
List<LocalDate> lastDays = new ArrayList<>();

LocalDate firstOfMonth = startDate.withDayOfMonth(1);
LocalDate lastOfMonth = startDate.withDayOfMonth(startDate.lengthOfMonth());

while (firstOfMonth.isBefore(endDate)) {
    firstDays.add(firstOfMonth.isBefore(startDate) ? startDate : firstOfMonth);
    lastDays.add(endDate.isBefore(lastOfMonth) ? endDate : lastOfMonth);

    firstOfMonth = firstOfMonth.plus(1, ChronoUnit.MONTHS);
    lastOfMonth = firstOfMonth.withDayOfMonth(firstOfMonth.lengthOfMonth());
}

System.out.println(firstDays);
System.out.println(lastDays);

Output:

[2018-09-01, 2018-10-01, 2018-11-01]
[2018-09-30, 2018-10-31, 2018-11-10]

How to Get All Dates Between Two Dates?, How can I get a list of dates between two dates? In this program, you'll learn to add two dates in Java using Calendar. Since, Java epoch is 1970, any time represented in a Date object will not work. This means, your Dates will start from 1970 and when two Date objects are added, the sum misses by about 1970 years. So, we use Calendar instead.

You can use plusMonth like so :

LocalDate firstDay = LocalDate.parse("2018-09-01");
LocalDate lastDay = LocalDate.parse("2018-11-10");

Long timeBetween = ChronoUnit.MONTHS.between(firstDay, lastDay);

// First day of firstDays is not changeable so add it like it is
List<LocalDate> firstDays = new ArrayList<>(Arrays.asList(firstDay));

// Generate the dates between the start and end date
firstDays.addAll(LongStream.rangeClosed(1, timeBetween)
        .mapToObj(f -> firstDay.withDayOfMonth(1).plusMonths(f))
        .collect(Collectors.toList()));

// For the lastDays, generate the dates
List<LocalDate> lastDays = LongStream.range(0, timeBetween)
        .mapToObj(f -> {
            LocalDate newDate = firstDay.plusMonths(f);
            return newDate.withDayOfMonth(newDate.lengthOfMonth());
        }).collect(Collectors.toList());
// Last day of lastDays is not changeable so add it like it is
lastDays.add(lastDay);

Output

[2018-09-01, 2018-10-01, 2018-11-01]
[2018-09-30, 2018-10-31, 2018-11-10]

How can I determine if a date is between two dates in Java?, How do you check whether a date is between two dates in Java? list of all months between two dates in java list of all months between two dates in java Hi, I want to get list of all months with year between two dates. How to do this in Java? Thanks Hi, This is the example code which can be used: package test.app

There are a couple of good answers already. Allow me to see if I can still devise something elegant.

Create just one list of objects

First, I suggest that you don’t want two lists. That’s an anti-pattern described here: Anti-pattern: parallel collections. Since each first day belongs to a corresponding last day from the other list, everything will be more convenient and less error-prone when you keep them together. For this purpose you may use some library class or devise your own:

public class DateInterval {

    LocalDate firstDay;
    LocalDate lastDay;

    public DateInterval(LocalDate firstDay, LocalDate lastDay) {
        if (lastDay.isBefore(firstDay)) {
            throw new IllegalArgumentException("Dates in wrong order");
        }
        this.firstDay = firstDay;
        this.lastDay = lastDay;
    }

    // getters and other stuff

    @Override
    public String toString() {
        return "" + firstDay + " - " + lastDay;
    }

}

With this class we need just one list:

    LocalDate firstDayOverall = LocalDate.of(2018, Month.DECEMBER, 10);
    LocalDate lastDayOverall = LocalDate.of(2019, Month.JANUARY, 6);

    if (lastDayOverall.isBefore(firstDayOverall)) {
        throw new IllegalStateException("Overall dates in wrong order");
    }
    LocalDate firstDayOfLastMonth = lastDayOverall.withDayOfMonth(1);
    LocalDate currentFirstDay = firstDayOverall;
    List<DateInterval> intervals = new ArrayList<>();
    while (currentFirstDay.isBefore(firstDayOfLastMonth)) {
        intervals.add(new DateInterval(currentFirstDay, currentFirstDay.with(TemporalAdjusters.lastDayOfMonth())));
        currentFirstDay = currentFirstDay.withDayOfMonth(1).plusMonths(1);
    }
    intervals.add(new DateInterval(currentFirstDay, lastDayOverall));

    System.out.println("Intervals: " + intervals);

The output from the above code snippet is:

Intervals: [2018-12-10 - 2018-12-31, 2019-01-01 - 2019-01-06]

The special case of first and last day being in the same month is handled by the loop not looping at all and the add after the loop adding the single interval to the list.

If two lists of dates are required

If you do insist on two lists, the two-arg datesUntil method is handy:

    List<LocalDate> firstDays = new ArrayList<>();
    firstDays.add(firstDayOverall);
    // first day not to be included in first days
    LocalDate endExclusive = lastDayOverall.withDayOfMonth(1).plusMonths(1);
    List<LocalDate> remainingFirstDays = firstDayOverall.withDayOfMonth(1)
            .plusMonths(1)
            .datesUntil(endExclusive, Period.ofMonths(1))
            .collect(Collectors.toList());
    firstDays.addAll(remainingFirstDays);
    System.out.println("First days: " + firstDays);

    // Calculate last days as the day before each first day except the first
    List<LocalDate> lastDays = remainingFirstDays.stream()
            .map(day -> day.minusDays(1))
            .collect(Collectors.toCollection(ArrayList::new));
    lastDays.add(lastDayOverall);
    System.out.println("Last days:  " + lastDays);

Output:

First days: [2018-12-10, 2019-01-01]
Last days:  [2018-12-31, 2019-01-06]
Aside

At first I had a feeling that the YearMonth class would make for an elegant solution. I realized, however, that it would have required special treatment of first and last month, so I don’t think it could have led to more elegant code than what we have above. You may try if you like.

How to check if Date is within a certain range in Java? – Mkyong.com, How can I get data between two dates in Android? 2.38.1. The java.util.Date Class: 2.38.2. Show date and time using only Date methods. 2.38.3. Obtaining a Date Object From a String: 2.38.4. Convert from a java.util.Date Object to a java.sql.Date Object: 2.38.5. Convert a String Date Such as 2003/01/10 into a java.util.Date Object: 2.38.6. Create Yesterday's Date from a Date in the String Format of MM/DD/YYYY

generate dates between two date in Android, For this, first create the following Map : static final Map<String, You can get the behaviour you describe with java 8 streams: Map<LocalDate For example when grouping by month these dates will have the same key: 01/01/2017 --> key <Integer,ArrayList<Date>> 1. set filter=DAY/MONTH/YEAR 2.Iterate the date_obj 3. Tutorial: How to Write a Java Date Class (Basic OOP Concept) September 17, 20142 Commentsbeginner, implementation, java, programming languages. The basic concept of OOP (Object Oriented Programming) is not difficult to understand and every Computer Science students should be able to demonstrate the OOP using Java, which is considered the most elegant programming language that has full OOP concepts.

Grouping items by date, In Java 8, we can now create a continuous infinite Stream of dates and take only the relevant part. Unfortunately, there is no way of terminating an  Grouping dates in Access by date components. This function evaluates a date value and returns a specific component, so you can use it to group by month, year, day of the week, and so on.

Java exercises: Get year and months between two dates, Java Date, Time and Calendar exercises and solution: Write a Java program to get year and months between two dates. It provides constructors and methods to deal with date and time with java. Constructors. Date(): Creates date object representing current date and time. Date(long milliseconds): Creates a date object for the given milliseconds since January 1, 1970, 00:00:00 GMT. Date(int year, int month, int date) Date(int year, int month, int date, int hrs

Comments
  • Have you tried anything? This is basically just a problem statement.
  • for the lastDays did you mean 2018-11-10 or 2018-11-30 ?
  • for the lastDays I mean 2018-11-10
  • Nice use of streams, but I think lastDays is wrong for the last element: it should be 2018-11-10 and not 2018-11-30
  • Thank you @AlexM oops I don't see this, I will fix it, but I think it is a typo?
  • I think the user expects to see firstDay instead of the 1st of the first month, and lastDay instead of the last day of the last month. It was not made clear in the question but kinda makes sense.
  • Yes Alex M and YCF_L. I'm trying both versions. Yours and the iterative one below. I tested first the iterative one, because the first firstDay and the last lastDay correspond to the real two dates entered. Thanks a lot for your help. I need to do some code on top for my purpose. I tell you if it works.
  • YCF_L thanks it works. I use the one of AlexM because I understand it better. But both are working. Thanks to you and to @AlexM.