如何实现每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; } }
关键改动说明
- 时段标识:用
epochSecond / 60替代取模,确保每个分钟时段有唯一的数值,不会跨小时混淆 - 完整性校验:
shouldCalculateDiff方法确保待处理的分钟已经结束,且SUPPLY和RETURN两侧都有该时段的脉冲数据,避免计算不完整的差值 - 计数隔离:仅对
lastProcessedMinute + 1这个待处理时段的脉冲进行计数,防止后续时段的脉冲混入当前累计 - 状态更新:每次计算完成后重置计数并更新已处理的分钟,保证逻辑的连续性
内容的提问来源于stack exchange,提问作者VitalyT
相关产品推荐
相关产品推荐

