【问题标题】:Check if timestamp older than 30 seconds检查时间戳是否超过 30 秒
【发布时间】:2017-08-27 19:36:04
【问题描述】:

我正在尝试确定时间戳是否早于 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;

}

【问题讨论】:

  • 请发帖Minimal, Complete, and Verifiable example。您的代码不是那样,例如什么是target,你怎么称呼cooldown()
  • 所有这些代码都是多余的。唯一的问题是为什么时间戳比原来更早。
  • 如果其余代码非常冗余,那么创建一个最小示例应该很容易,对吧?
  • 刚刚在链接中查看了您在 Ideone 上的代码。在该代码中,不会创建您的类 Ideone 的实例。所以secondsAgo 永远不会设置为 30。@Andreas 的怀疑是正确的。
  • 当我问你是否确定secondsAgo 的值是30,你说是的,甚至没有检查。我问,因为这是我能看到的唯一原因,它会显示结果,所以我相当肯定它是0,事实证明,我是对的。下一次,验证,例如使用调试器。如果您不知道如何调试,现在是学习的好时机。是程序员必备的技能。见What is a debugger and how can it help me diagnose problems?

标签: java timestamp unix-timestamp


【解决方案1】:

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

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

【讨论】:

  • 我不知道。你告诉我。再次。我正在尝试存储并检查时间戳(无论哪种类型的时间戳),以查看它是否超过 30 秒,或者我定义的任何时间,甚至是几分钟。 SO 上的许多示例使用 System.currentTimeMillis() 作为时间戳。请发布问题的答案而不是问题。这可以保存以供评论。
  • 要求澄清应该在评论中。这当然不是答案。等到你有离开 cmets 所需的 50 个代表。在那之前,删除这个答案以清除我刚刚给出的否定代表。
【解决方案2】:

试试这个:

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;
    }

}

【讨论】:

    【解决方案3】:

    这个:

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

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

    System.currentTimeMillis();
    

    并在cooldown.get(id)和timeAgo之间验证这个条件

    所以他们遇到 cooldown.get(id) - timeAgo 或不...

    【讨论】:

      【解决方案4】:

      使用 java.time

      您正在使用麻烦的旧日期时间类,它们现在是遗留的,被 java.time 类所取代。

      Instant 类表示UTC 中时间轴上的时刻,分辨率为nanoseconds(最多九 (9) 位小数)。

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

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

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

      表示您的 30 秒限制。

      Duration limit = Duration.ofSeconds( 30 );
      

      通过调用Duration::compareToComparable 方法进行比较。

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

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


      关于java.time

      java.time 框架内置于 Java 8 及更高版本中。这些类取代了麻烦的旧 legacy 日期时间类,例如 java.util.DateCalendarSimpleDateFormat

      Joda-Time 项目现在位于maintenance mode,建议迁移到java.time 类。

      要了解更多信息,请参阅Oracle Tutorial。并在 Stack Overflow 上搜索许多示例和解释。规格为JSR 310

      从哪里获得 java.time 类?

      ThreeTen-Extra 项目通过附加类扩展了 java.time。该项目是未来可能添加到 java.time 的试验场。您可以在这里找到一些有用的类,例如IntervalYearWeekYearQuartermore

      【讨论】:

      • 而不是compareTo() 我想我只考虑duration.getSeconds() &lt; secondsAgo(其中secondsAgo 必须是30)。当然,将limit 声明为Duration 会告诉读者这就是它的本质,所以有利有弊。这是一个细节。无论如何,这个问题是 java.time 类在哪里有用的一个很好的例子。
      • @OleV.V.当然是个好建议。 compareTo 语法笨拙且不直观。但实际上,Duration 应该有比较方法。类似isEquallongerThanshorterThan
      【解决方案5】:

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

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

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

      【讨论】:

        猜你喜欢
        • 2012-12-27
        • 1970-01-01
        • 2011-01-24
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-03-05
        • 2021-07-11
        相关资源
        最近更新 更多