2017-04-03 720 views
-1

我正在嘗試確定時間戳是否超過30秒,但由於某種原因,它的返回時間超過了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; 

} 
+1

請發佈[最小,完整和可驗證示例](http://stackoverflow.com/help/mcve)。你的代碼並非如此什麼是「目標」,你如何稱呼「冷卻時間()」? – Andreas

+0

所有的代碼真的是多餘的。唯一的問題是爲什麼時間戳會比它更早。 – JordanSasquatchMan

+1

如果代碼的其餘部分非常冗餘,那麼創建一個最簡單的例子應該很簡單,對吧? –

回答

2

使用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方法進行比較。

順便說一句,具有收集和兩個命名cooldown的方法是沒有幫助的。


關於java.time

java.time框架是建立在Java 8和更高版本。這些類取代了日期時間類legacy,如java.util.Date,Calendar,& SimpleDateFormat

Joda-Time項目現在位於maintenance mode,建議遷移到java.time類。請參閱Oracle Tutorial。並搜索堆棧溢出了很多例子和解釋。規格是JSR 310

從何處獲取java.time類?

ThreeTen-Extra項目與其他類擴展java.time。這個項目是未來可能增加java.time的一個試驗場。您可以在這裏找到一些有用的類,如Interval,YearWeek,YearQuartermore

+0

而不是'compareTo()'我想我只考慮'duration.getSeconds()

+1

@ OleV.V。當然是一個很好的建議。 'compareTo'語法很尷尬且不直觀。實際上,'持續時間'應該有比較方法。類似於「isEqual」,「longerThan」,「shortThan」。 –

-2

的currentTimeMillis回報:區別,以毫秒爲單位,當前時間和午夜,1970年1月1日,UTC

你能解釋爲什麼你使用它之間。

+0

我不知道。你告訴我。再次。我試圖存儲,並檢查一個時間戳(無論什麼類型的時間戳),看它是否超過30秒,或者我定義的任何東西,甚至是幾分鐘。 許多關於SO的例子都使用System.currentTimeMillis()來表示時間戳。 請發佈問題的答案,而不是問題。這可以保存以供評論。 – JordanSasquatchMan

+2

要求澄清應在評論中。這當然不是一個答案。等到你有要求留下評論的50名代表。在此之前,請刪除此答案以清除我剛剛給出的負面報告。 – Andreas

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

} 
1

此:

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或不...

1

要從the code on Ideone that you link to判斷,問題在於secondsAgo是0,而不是30.您在構造函數中將其設置爲30,但由於您從不從類創建對象,所以構造函數從不執行。 secondsAgo是一個靜態字段,因此您可以在沒有對象且未初始化的情況下訪問它。你只要得到int字段所有的初始值,即0.

我在Ideone看到的輸出結果肯定了我的意思。在形式1491194338577 | 1491194338578的所有行中,數字要麼相同,要麼相隔1毫秒。即使您已從Calendar對象中減去secondsAgo秒,您從timeAgo開始,timeAgo永遠不會比您在毫秒前放入地圖的時間戳早30秒。所以不,你沒有減去30秒;你正在減去0秒。

不過我還是同意羅勒布爾克的回答是:如果你可以使用Java 8無論如何,你應該拋出的Calendar類拿走並使用InstantDuration。你得到更清晰,更易讀的代碼。將Instant對象放在您的地圖中,而不是Long s,它突然不言自明。