1

We are starting with a List of timestamps, which are Date objects. We need to group all timestamps which belong to a unique day. For example, when a user logs into our server, a timestamp is added to a single List. We want to be able to parse this list and separate all the Date objects which belong to the same day. The end goal is to be able to easily show all logins separated by day on a UI, as well as to show the number of logins which occurred per each day.

The end HashMap construct should look like this:

Key                          List<Date> 

2018-07-11 
                  2018-07-11 08:14:08.540000 
                  2018-07-11 10:46:23.575000 

2018-07-12  
                  2018-07-12 12:51:48.928000 
                  2018-07-12 13:09:00.701000 
                  2018-07-12 16:04:45.890000 

2018-07-13 
                  2018-07-13 14:14:17.461000 
Ebony Maw
  • 514
  • 7
  • 23
  • Please keep in mind that a number of older projects out there are still using Java 7, therefore, a solution which doesn't depend on the Java 8 API would be appreciated. Thank you. – Ebony Maw Jul 14 '18 at 17:22

2 Answers2

2

Here's the java8 way of doing it.

List<LocalDateTime> loginTimes = Arrays.asList(LocalDateTime.of(2018, 5, 7, 8, 10),
        LocalDateTime.of(2018, 5, 7, 9, 15, 20), LocalDateTime.of(2018, 6, 22, 7, 40, 30));
Map<LocalDate, Long> loginCountByDate = loginTimes.stream()
        .collect(Collectors.groupingBy(LocalDateTime::toLocalDate, Collectors.counting()));

First group the login times by date and then count the number of logins by each date. This is the best solution I can suggest, but it mandates you to use Java8.

Here's the output.

{2018-05-07=2, 2018-06-22=1}
Ravindra Ranwala
  • 20,744
  • 6
  • 45
  • 63
0

This is the solution we came up with. The parseTimeStamps method takes the list of timeStamps iterates over it, and uses a Calendar object to set the hours, minutes, seconds, and milliseconds to 0, thereby giving us just the day. We then check our groupedUserLogins HashMap to see if it contains a key with that date. If it doesn't, we create a key with that day, and a new list of Date objects as the value associated with that key. Subsequently, we add the timestamp(ts) to the list associated with that day.

In the next iteration, if we come across a key in our HashMap which matches our stripped Calender object, we immediately add that timestamp (ts) to the list associated with that existing day.

I created the following method, which returns a HashMap> where the key is a Date object and the value is a List of Date Objects. The method accepts a List of timeStamps and groups them by day. It then returns those grouped timestamps in the aforementioned HashMap construct.

 public class GroupDatesByDay {

    HashMap<Date, List<Date>> groupedUserLogins = new HashMap<Date, List<Date>>();
    Calendar cal = Calendar.getInstance();

    public HashMap<Date, List<Date>> parseTimeStamps(List<Date> timeStamps) {

    DateFormat dateFormat = new SimpleDateFormat("HH:mm:ss.SSS", Locale.US);
    List<Date> timeStamps = new ArrayList<Date>();

        for (Date ts : timeStamps) {

            cal.setTime(ts);
            cal.set(cal.HOUR_OF_DAY, 0);
            cal.set(cal.MINUTE, 0);
            cal.set(cal.SECOND, 0);
            cal.set(cal.MILLISECOND, 0);

            if (!groupedUserLogins.containsKey(cal.getTime())) {

                groupedUserLogins.put(cal.getTime(), new ArrayList<Date>());
            }
            groupedUserLogins.get(cal.getTime()).add(ts);
        }

        keySet = groupedUserLogins.keySet();
        keyList.addAll(keySet);
        return groupedUserLogins;
    }
}

We end up with groupedUserLogins which has now conveniently stored all unique days as keys pointing to a List which holds our timestamps, as Date objects. The biggest advantage of this data-structure is that the keys, as well as the values are still Date objects, giving us future flexibility.

Please feel free to provide alternate solutions, or improve upon what I have presented.

Ebony Maw
  • 514
  • 7
  • 23