用 joda time 计算平均时间

calculate an average time with joda time

我有很多时间戳显示用户进入房间的时间。我想计算平均时间。当某些动作发生在晚上时,就会出现问题。 我试着用milis算了一下,结果不对

ArrayList<String> times = new ArrayList<String>();

    times.add("00:20:01");
    times.add("00:00:01");
    times.add("23:40:01");
    times.add("23:20:01");
    times.add("23:20:01");
    times.add("00:20:01");
    times.add("23:40:01");
    times.add("23:40:01");
    times.add("00:00:01");
    long commonMillis=0;
    for (String date:times){
        LocalTime time = new LocalTime(date);
        long dayMilis = time.getMillisOfDay();
        commonMillis = commonMillis + dayMilis;
    }
    LocalTime average = new LocalTime(commonMillis/times.size());

此代码,例如returns值14:08:54.333。因为时间00:00 and 23:00——以毫秒计算——彼此相差太远。

请帮我找到计算平均时间的正确方法?

一种天真的方法是收集所有日期中的 long 毫秒值,将它们相加并除以日期数,将它们转换回 LocalDate。不过,您可能需要一个 BigInteger 来保存总和。

三件事:

  1. 您必须定义一个偏移时间:
    如果你想在不知道日期的情况下求出不同日期的平均时间,你必须自己定义一个偏移时间。这个时间用来判断一个时间是否属于第二天。
    这个偏移时间可能会根据你得到的值推导出来。
    如果没有偏移时间,您将隐含地使用 0 点钟。

  2. 避免溢出:
    如果您的 times 列表变长,并且 long 字段不足以存储累积值,您可能 运行 溢出。您可以使用像 BigInteger 这样的防溢出数据结构或使用 (culmulative) moving average 方法。

  3. 错误的结果构造函数:
    构造函数 LocalTime(long instant) 隐含地使用本地 DateTimeZoneInstant 计算本地时间。这会导致在不同时区之间使用相同代码时出现不同时间。
    您要使用的方法是 LocalTime#fromMillisOfDay.

考虑到以上几点,这里有一个方法:

    long movingAverage = 0;

    // 1. define offset
    LocalTime offset = new LocalTime("12:00:00");
    long offsetMillis = offset.getMillisOfDay();

    for (String date : times) {
        long sampleMillis = new LocalTime(date).getMillisOfDay();

        // align to offset
        if (sampleMillis < offsetMillis)
            sampleMillis += DateTimeConstants.MILLIS_PER_DAY;

        long diff = sampleMillis - offsetMillis;

        // 2. use moving average
        movingAverage = movingAverage + diff / times.size();
    }

    // 3. avoid LocalTime(long) constructor
    LocalTime result = offset.plusMillis((int) movingAverage);
    System.out.println(result); // 23:48:54.329