6

我有一组 java.util.Date 对象。我试图找到平均值。

例如,如果我有 2 个日期对象,分别是上午 7:40 和上午 7:50。我应该得到早上 7:45 的平均日期对象。

我正在考虑的方法效率低下:

  1. for 循环遍历所有日期
  2. 找出 0000 和时间之间的差异
  3. 将该时间差异添加到总数中
  4. 除以总数
  5. 将该时间转换为日期对象

有没有更简单的功能来做到这一点?

4

6 回答 6

21

好吧,从根本上讲,您可以将所有对象的“自 Unix 纪元以来的毫秒数”相加Date并找到它们的平均值。现在棘手的一点是避免溢出。选项是:

  1. 除以某个已知数量(例如 1000)以避免溢出;这会将准确性降低一个已知量(在本例中为第二个),但如果您有超过 1000 个项目,则会失败
  2. 将每个毫秒值除以平均日期数;这将始终有效,但会导致难以理解的精度降低
  3. BigInteger改为使用

方法 1 的示例:

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

方法 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());
于 2013-08-12T17:38:44.293 回答
2

有很多日期,将所有日期加在一起肯定会溢出。如果你想防止你应该这样做(在伪代码中):

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

这永远不会让你在溢出中运行。

于 2013-08-12T17:45:04.707 回答
0

尝试这个。在这里,每个日期都转换为长值 my getTime()。这将返回 mil-second 值。然后我们可以继续。

   SimpleDateFormat sdf = new SimpleDateFormat("HH:mma");
    Date date1=sdf.parse("7:40AM");
    Date date2=sdf.parse("7:50AM");
    long date1InMilSec=date1.getTime();
    long date2InMilSec=date2.getTime();
    System.out.println("Average "+sdf.format((date1InMilSec+date2InMilSec)/2));
于 2013-08-12T17:40:52.760 回答
0

这里已经有答案了:Sum two dates in Java

您只需要总结所有日期对象getTime(),然后将其除以对象数量并将其转换回Date对象。完毕。

于 2013-08-12T17:39:30.920 回答
0

为避免计算平均时间溢出:

首先按日期排序;
将第一个日期的值存储在time0

通过从所有时间减去 g first time0 来计算 deltaTimes 的平均值。然后总结和划分。

结果 = new Date(time0 + avgDeltas);

于 2013-08-12T17:39:44.643 回答
0

发布 java 8 后,您可以使用

Date avgDate = new Date( LongStream.of(datesAsLongArray).sum() / datesAsLongArray.length * 1000);
于 2013-08-12T17:52:02.390 回答