Split java.util.Date collection by Days

Could you help me, please. I can't figure out the algorithm.

I have a sorted collection of Dates, for example ArrayList like this:

Wed Jan 22 00:00:00 MSK 2014
Wed Jan 22 00:30:00 MSK 2014
Wed Jan 23 01:00:00 MSK 2014
Wed Jan 23 01:30:00 MSK 2014
Wed Jan 23 02:00:00 MSK 2014
Wed Jan 24 02:30:00 MSK 2014
Wed Jan 24 03:00:00 MSK 2014
Wed Jan 24 03:30:00 MSK 2014
Wed Jan 24 04:00:00 MSK 2014
Wed Jan 28 04:30:00 MSK 2014
Wed Jan 28 05:00:00 MSK 2014

I need another version of this list, grouped by day (from 00:00:00 till 23:59:59), so it could be an array of lists, like List<List<Date>>. Following the example it should be the list with size 4, with second Object ==

List<Date> {Wed Jan 23 01:00:00 MSK 2014;
Wed Jan 23 01:30:00 MSK 2014;
Wed Jan 23 02:00:00 MSK 2014; }

Seems like an easy task. but I can't find convenient way to solve it. Thanks in advance.

UPDATE According to TEXHIK's answer, width JDK 7 it could be done like this:

 public List<List<Date>> split(List<Date> value) {
        List<List<Date>> result = new ArrayList<>();

        int day = value.iterator().next().getDate();
        List<Date> newListEntry = new ArrayList<>();

        for (Date date : value) {
            if (date.getDate() == day) {
                newListEntry.add(date);
            }
            else {
                day = date.getDate();
                result.add(newListEntry);
                newListEntry = new ArrayList<>();
                newListEntry.add(date);
            }
        }
        result.add(newListEntry);//because the last sublist was not added

        return result;
    }

It's OK, unless it's deprecated methods of java.util.Date. Will be glad to see the answers using Java 8 or Joda Time.

Jon Skeet
people
quotationmark

If you're happy with UTC days, life becomes simpler:

  • The milliseconds-since-the-unix-epoch starts on a day boundary, so you can just divide
  • Each day is 24 hours long, which is handy in many cases (e.g. if you're doing analytics with the data)

In that case, you can just use something like:

long millisPerDay = TimeUnit.DAYS.toMillis(1);
Map<Long, List<Date>> datesByDay = new HashMap<>();
for (Date date : dates) {
    long day = date.getTime() / millisPerDay;
    List<Dates> dayDates = datesByDay.get(day);
    if (dayDates == null) {
        dayDates = new ArrayList<>();
        datesByDay.put(day, dayDates);
    }
    dayDates.add(date);
}

Of course, a Multimap, e.g. from Guava, will make this simpler:

long millisPerDay = TimeUnit.DAYS.toMillis(1);
Multimap<Long, Date> datesByDay = ArrayListMultimap.create();
for (Date date : dates) {
    long day = date.getTime() / millisPerDay;
    datesByDay.put(day, date);
}

people

See more on this question at Stackoverflow