检查时间戳是否早于 30 秒

Check if timestamp older than 30 seconds

我正在尝试确定时间戳是否早于 30 秒,但由于某种原因,它在还不到几秒的时候就返回早于 30 秒。

示例:https://ideone.com/KLIIBz

public static Boolean cooldown(int id) {

    Calendar now = Calendar.getInstance();
    now.add(Calendar.SECOND, -secondsAgo);
    long timeAgo = now.getTimeInMillis();
    if ( cooldown.containsKey(id) ) {

        System.out.println(cooldown.get(id) + " | " + timeAgo);

        // Stored timestamp always older than timeAgo
        if ( cooldown.get(id) < timeAgo ) {

            cooldown.remove(id);

        } else {

            // This code should be executed, as I am running the function one after another from same UUID not even a second or two apart.
            return false;

        }

    }

    now = Calendar.getInstance();
    cooldown.put(id, now.getTimeInMillis());

    return true;

}

currentTimeMillis returns:当前时间与 1970 年 1 月 1 日午夜 UTC 之间的差异,以毫秒为单位

你能解释一下你为什么使用它吗?

试试这个:

public class JavaApplication11 
{
    public static void main(String[] args)
    {
        // TODO code application logic here
        Calendar now = Calendar.getInstance();
        now.add(Calendar.SECOND, -30);//Set Calendar 30 seconds in the past.

        System.out.println(has30SecsPassed(now));
    }

    static boolean has30SecsPassed(Calendar calendar)
    {
        Long numberOfMilliSec = Calendar.getInstance().getTimeInMillis() - calendar.getTimeInMillis();
        double numberOfSecondsPassed = numberOfMilliSec / 1000.0;
        System.out.println("seconds passed: " + numberOfSecondsPassed);
        return numberOfSecondsPassed >= 30;
    }

}

这个:

Calendar now = Calendar.getInstance();
now.add(Calendar.SECOND, -secondsAgo);
long timeAgo = now.getTimeInMillis();

开销太大或者只是在您的应用中获取实际时间戳...您可以调用

System.currentTimeMillis();

并在 cooldown.get(id) 和 timeAgo

之间验证此条件

所以他们满足 cooldown.get(id) - timeAgo < 30*1000 或不...

使用java.time

您正在使用麻烦的旧日期时间 类,现在已成为遗留问题,已被 java.time 类.

取代

Instant class represents a moment on the timeline in UTC with a resolution of nanoseconds(最多九 (9) 位小数)。

Instant start = Instant.now();
…
Instant stop = Instant.now();

将开始和停止之间的时间跨度捕获为 Duration

Duration duration = Duration.between( start , stop );

表示您的 30 秒限制。

Duration limit = Duration.ofSeconds( 30 );

通过调用 Comparable method of Duration::compareTo 进行比较。

Boolean exceededLimit = ( duration.compareTo( limit ) > 0 );

顺便说一句,集合和方法都命名为 cooldown 没有帮助。


关于java.time

java.time framework is built into Java 8 and later. These classes supplant the troublesome old legacy date-time classes such as java.util.Date, Calendar, & SimpleDateFormat.

Joda-Time project, now in maintenance mode, advises migration to the java.time 类.

要了解更多信息,请参阅 Oracle Tutorial. And search Stack Overflow for many examples and explanations. Specification is JSR 310

在哪里获取java.time类?

  • Java SE 8 and SE 9 及更高版本
    • 内置。
    • 标准 Java API 的一部分,带有捆绑实施。
    • Java 9 添加了一些小功能和修复。
  • Java SE 6 and SE 7
  • Android
    • ThreeTenABP 项目专门为 Android 改编 ThreeTen-Backport(如上所述)。

ThreeTen-Extra project extends java.time with additional classes. This project is a proving ground for possible future additions to java.time. You may find some useful classes here such as Interval, YearWeek, YearQuarter, and more.

the code on Ideone that you link to判断,问题是secondsAgo是0,不是30。你在构造函数中设置为30,但是由于你从来没有从[=31创建对象=],永远不会执行构造函数。 secondsAgo 是一个静态字段,因此您可以在没有对象且未初始化的情况下访问它。你只是得到所有 int 字段的初始值,即 0.

我在 Ideone 中看到的输出肯定证实了我所说的。在 1491194338577 | 1491194338578 形式的所有行中,数字要么相同,要么仅相隔 1 毫秒。即使您从获得 timeAgoCalendar 对象中减去 secondsAgo 秒,timeAgo 也永远不会比您放入地图的时间戳早 30 秒一毫秒前。所以不,你不是在减去 30 秒;而是在减去 30 秒。你正在减去 0 秒。

也就是说我仍然同意 Basil Bourque 的回答:如果有任何方法可以使用 Java 8,你应该扔掉 Calendar class 并使用 InstantDuration。您将获得更清晰、更易读的代码。将 Instant 对象而不是 Longs 放在地图中,它们是什么突然不言自明了。