You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何实现每1分钟计算SUPPLY与RETURN侧脉冲计数差值并同步?

问题:实现每分钟同步SUPPLY/RETURN脉冲并计算计数差值

需要同步来自SUPPLY、RETURN两侧持续传入的脉冲,同一代码处理两侧逻辑,每个脉冲带有count值。要求每1分钟计算一次两侧计数差值,且确保该时段内两侧脉冲均已到达。当前代码仅能在1秒后通过时间戳对比完成验证,现需替换原有1秒逻辑为1分钟逻辑,询问是否可使用取模%60实现。

原代码如下:

public class Detector {

    long supplyEpochSecond = -1;
    long returnEpochSecond = -1;
    int supplyCount;
    int returnCount;

    void calcDiffs (SensorPulse pulse, Source source){

        LocalDateTime pulseTime = pulse.getLocalDateTime();
        long epochSecond = pulseTime.toEpochSecond(ZoneOffset.UTC);
        boolean oneSecondPassed = oneSecondPassed(epochSecond, source == Source.SUPPLY);
        if (oneSecondPassed) {
            /**
             * TODO add logic instead of make after one second
             * need sync after 1 min and calculate diff between supply and return counts
             */
            int diff = supplyCount - returnCount;
            System.out.println("Count diff after 1 sec:" + diff); // need after 1 min pass

           supplyCount = 0;
           returnCount = 0;
        }
        int count = pulse.getCount();
        if (source == Source.SUPPLY) {
            supplyEpochSecond = epochSecond;
            supplyCount += count;
        } else {
            returnEpochSecond = epochSecond;
            returnCount += count;
        }
    }

    private boolean oneSecondPassed(long epochSecond, boolean isSupply) {
        if (supplyEpochSecond == -1 || returnEpochSecond == -1) { // not started yet
            return false;
        }
        if (supplyEpochSecond == returnEpochSecond) { // got measures from both last time
            return epochSecond > supplyEpochSecond;
        }
        return (supplyEpochSecond > returnEpochSecond) == isSupply; // one measure is missing
    }
}

解答

可以基于分钟级的时间戳划分时段,但不建议直接用%60——因为取模只能得到0-59的分钟数,无法区分不同小时的同一分钟(比如10:05和11:05取模结果都是5),会导致时段判断混乱。更可靠的方式是将秒级时间戳转换为从epoch开始的分钟数(即epochSecond / 60),以此唯一标识每个分钟时段。

以下是修改后的代码,实现每分钟计算差值并确保两侧脉冲均到达:

import java.time.LocalDateTime;
import java.time.ZoneOffset;

public class Detector {
    // 记录最后一个已完成计算的分钟时段(格式:从epoch开始的分钟数)
    long lastProcessedMinute = -1;
    // 当前正在累计的分钟时段的两侧计数
    int currentSupplyCount;
    int currentReturnCount;
    // 记录两侧最新脉冲所在的分钟时段
    long supplyLatestMinute = -1;
    long returnLatestMinute = -1;

    void calcDiffs(SensorPulse pulse, Source source) {
        LocalDateTime pulseTime = pulse.getLocalDateTime();
        long epochSecond = pulseTime.toEpochSecond(ZoneOffset.UTC);
        long currentMinute = epochSecond / 60; // 转换为分钟级唯一标识

        // 检查是否有已结束的完整分钟需要计算差值
        boolean shouldCalculate = shouldCalculateDiff(currentMinute);
        if (shouldCalculate) {
            int diff = currentSupplyCount - currentReturnCount;
            System.out.println("Count diff after 1 min: " + diff);
            
            // 重置计数,准备累计下一个时段
            currentSupplyCount = 0;
            currentReturnCount = 0;
            // 更新已处理的分钟时段
            lastProcessedMinute++;
        }

        // 仅累计当前待处理时段的计数(避免跨时段数据混入)
        int count = pulse.getCount();
        long targetMinute = lastProcessedMinute + 1;
        if (source == Source.SUPPLY) {
            supplyLatestMinute = currentMinute;
            if (currentMinute == targetMinute) {
                currentSupplyCount += count;
            }
        } else {
            returnLatestMinute = currentMinute;
            if (currentMinute == targetMinute) {
                currentReturnCount += count;
            }
        }
    }

    private boolean shouldCalculateDiff(long currentMinute) {
        // 初始化阶段,无任何脉冲数据时不计算
        if (supplyLatestMinute == -1 || returnLatestMinute == -1) {
            return false;
        }

        long targetMinute = lastProcessedMinute + 1;
        // 满足两个条件才计算:
        // 1. 当前脉冲的时段已超过待处理的目标分钟(目标分钟已结束)
        // 2. 两侧都有目标分钟的脉冲数据
        return currentMinute > targetMinute 
                && supplyLatestMinute >= targetMinute 
                && returnLatestMinute >= targetMinute;
    }
}

// 补充原代码依赖的枚举和类
enum Source { SUPPLY, RETURN }
class SensorPulse {
    private LocalDateTime localDateTime;
    private int count;

    public LocalDateTime getLocalDateTime() { return localDateTime; }
    public int getCount() { return count; }
}

关键改动说明

  1. 时段标识:用epochSecond / 60替代取模,确保每个分钟时段有唯一的数值,不会跨小时混淆
  2. 完整性校验:shouldCalculateDiff方法确保待处理的分钟已经结束,且SUPPLY和RETURN两侧都有该时段的脉冲数据,避免计算不完整的差值
  3. 计数隔离:仅对lastProcessedMinute + 1这个待处理时段的脉冲进行计数,防止后续时段的脉冲混入当前累计
  4. 状态更新:每次计算完成后重置计数并更新已处理的分钟,保证逻辑的连续性

内容的提问来源于stack exchange,提问作者VitalyT

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.02 18:43:27