Java使用长纪元时间戳来检测日变化的最有效方法
Posted
技术标签:
【中文标题】Java使用长纪元时间戳来检测日变化的最有效方法【英文标题】:Java most efficient way using a long epoch timestamp to detect a change in day 【发布时间】:2021-04-30 12:04:33 【问题描述】:问题情况:我有大量记录都标有时间戳。我正在遍历所有这些以执行此操作,但我需要检测一天何时发生变化。
现在对于我正在执行的每个循环:
cal.setTimeInMillis(record.time);
int currentDay = cal.get(Calendar.DAY_OF_WEEK);
当它运行数十万次时,它是否像我想象的那样慢? 我想我错过了一个非常简单的模数答案或其他东西。
编辑:时区无关紧要,我收集的信息更多地解决了某人的消耗性报告。 24 小时每份报告更准确,因此实际上我不必担心是凌晨 5 点至凌晨 5 点还是下午 3 点至下午 3 点,只要我能够收集 24 小时的信息即可。
谢谢大家
【问题讨论】:
嗯,你希望它表现得如何,如何处理闰年、闰秒等。日期库会处理所有这些,但它肯定需要几纳秒- 你是否真的以有意义的方式衡量了性能,它真的很慢吗? 将一天的结束转换为时间戳并与record.time
进行比较可能更有效
ideone.com/23p0Y6 1M 次迭代耗时 0.76 秒。好像不慢我会更关心它的正确性(例如,您是否在正确的时区计算日期)。
添加了一个编辑,我真的不用担心时区,我只想分成 24 小时的块。
您的 24 小时数据块有哪些限制?您的意思是从当前时刻开始,然后以 24 小时为增量前进/后退吗?你需要更清楚地考虑这一点。说“当一天改变了”同时又说“分成 24 小时的时间段”是矛盾的。投票结束,因为不清楚。
【参考方案1】:
经过 Andy Turner 的时间测试,我不一定相信您需要任何优化的解决方案。无论如何,timsmelik 的建议非常简单:将日期变化的时间转换为自纪元以来的毫秒数,因此您只需要比较 long
值。我没有发现它对可读性的伤害非常严重。所以这里是代码。我正在使用并热烈推荐 java.time,现代 Java 日期和时间 API,如果只是用于从小时到毫秒的转换以及打印结果。即使这样的转换看起来微不足道,最好还是让标准库来做。它更不言自明,更不容易出错,读者更容易说服自己它是正确的。
final long twentyfourHoursAsMillis = Duration.ofHours(24).toMillis();
// Times are already sorted descending (from newest to oldest)
long[] times = 1_611_718_370_000L, 1_611_632_000_000L,
1_611_631_970_000L, 1_611_459_150_000L ;
List<List<Long>> chunks = new ArrayList<>();
List<Long> currentChunk = new ArrayList<>();
// Process first time separately to get started
currentChunk.add(times[0]);
long timeOfNextChunk = times[0] - twentyfourHoursAsMillis;
// Process remaining times
for (int i = 1; i < times.length; i++)
long currentTime = times[i];
if (currentTime <= timeOfNextChunk)
chunks.add(currentChunk);
currentChunk = new ArrayList<>();
do
timeOfNextChunk -= twentyfourHoursAsMillis;
while (currentTime <= timeOfNextChunk);
currentChunk.add(currentTime);
// Save last chunk, why not?
chunks.add(currentChunk);
// Print result
for (List<Long> chunk : chunks)
String chunkAsString = chunk.stream()
.map(Instant::ofEpochMilli)
.map(Instant::toString)
.collect(Collectors.joining(", "));
System.out.println(chunkAsString);
输出是:
2021-01-27T03:32:50Z, 2021-01-26T03:33:20Z 2021-01-26T03:32:50Z 2021-01-24T03:32:30Z
我正在打印Instant
对象。他们总是以 UTC 打印。对于您的情况,如果您需要打印时间,您可能需要做其他事情。
您应该检查您的假设,即时间是按排序顺序排列的。
我相信你的话,并在 24 小时内将其分成几块。 24 小时甚至可能不意味着凌晨 5 点 - 凌晨 5 点,但可能意味着例如从 3 月 13 日美国东部标准时间上午 5 点到 3 月 14 日美国东部时间 6 点,因为与此同时夏季时间 (DST) 已经开始。如果您希望在同一时钟时间进行拆分,可以修改代码以执行此操作。
【讨论】:
以上是关于Java使用长纪元时间戳来检测日变化的最有效方法的主要内容,如果未能解决你的问题,请参考以下文章