Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Get Average of two java.util.Date

Tags:

java

date

I have an array of java.util.Date objects. I am trying to find the average.

For example, if I have 2 date objects with 7:40AM and 7:50AM. I should get an average date object of 7:45AM.

The approach I am thinking of is inefficient:

  1. for loop through all dates
  2. find difference between 0000 and time
  3. add that time diff to a total
  4. divide that by the total count
  5. convert that time to a date object

Is there an easier function to do this?

like image 547
raaj Avatar asked Aug 12 '13 17:08

raaj


People also ask

How to calculate the Difference between two dates in Java?

getTime() – d1. getTime(). Use date-time mathematical formula to find the difference between two dates. It returns the years, days, hours, minutes, and seconds between the two specifies dates.

How to get number of days between 2 dates Java?

The Period class has a between() method - just as the previously discussed ChronoUnit . This method takes in two LocalDate objects, one representing the starting date, and the second being the end date. It returns a Period consisting of the number of years, months, and days between two dates.

How do you calculate average time in Java?

Something like this should work: String timeInHHmmss = "08:00:00 08:00:00 08:00:00"; String[] split = timeInHHmmss. split(" "); long sum = 0L; SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss"); for (int i = 0; i < split. length; i++) { sum += sdf.

How do you find the average of datetime?

The average formula is the same as multiplying your sum by 1/N. Or multiplying each individual X by 1/N and adding them together.


2 Answers

Well fundamentally you can just add up the "millis since the Unix epoch" of all the Date objects and find the average of those. Now the tricky bit is avoiding overflow. Options are:

  1. Divide by some known quantity (e.g. 1000) to avoid overflow; this reduces the accuracy by a known amount (in this case to the second) but will fail if you have more than 1000 items
  2. Divide each millis value by the number of dates you're averaging over; this will always work, but has hard-to-understand accuracy reduction
  3. Use BigInteger instead

An example of approach 1:

long totalSeconds = 0L;
for (Date date : dates) {
     totalSeconds += date.getTime() / 1000L;
}
long averageSeconds = totalSeconds / dates.size();
Date averageDate = new Date(averageSeconds * 1000L);

An example of approach 3:

BigInteger total = BigInteger.ZERO;
for (Date date : dates) {
     total = total.add(BigInteger.valueOf(date.getTime()));
}
BigInteger averageMillis = total.divide(BigInteger.valueOf(dates.size()));
Date averageDate = new Date(averageMillis.longValue());
like image 164
Jon Skeet Avatar answered Sep 18 '22 19:09

Jon Skeet


With a lot of dates, taking the sum of all dates together will certainly go into an overflow. If you want to prevent that you should do it like this (in pseudo code):

var first = dates.getFirst
var sumOfDifferences = 0
loop over all dates
    for each date sumOfDifferences += date - first
var averageDate = first + sumOfDifferences/countOfDates

This will never make you run in an overflow.

like image 42
ChristopherS Avatar answered Sep 16 '22 19:09

ChristopherS