2016-02-19 139 views
0

我正在根據dueDate字段與當前日期的比較來設置顏色字段。 dueDate是SQL日期類型。我的問題是,當我通過當前日期Calendar.before()方法表示日期在當前日期之前。我的代碼是:爲什麼Calendar()方法在相同日期返回true

private String getDateDueColor(Date dateDue) { 
     Calendar today = Calendar.getInstance(); 
     today.setTime(new java.sql.Date(Calendar.getInstance().getTime().getTime())); 
     Calendar dueDate = Calendar.getInstance(); 
     dueDate.setTime(dateDue); 
     if(dueDate.before(today)){ 
     return RED; 
     }else{ 
     return NORMAL; 
     } 
    } 

我設置一個斷點,並比較dueDatetoday和所有在cdate字段中的信息爲每個對象看起來完全相同,但仍dueDate.before(today)返回true。任何幫助,將不勝感激!

+0

dateDue的值是什麼 – SDS

+3

'Calendar.getInstance().getTime()。getTime()'是一個不必要的冗長和神祕的做'System.currentTimeMillis()'的方法。 – VGR

+0

我在StackOverflow文章中發現了Calendar.getInstance()。getTime()。getTime()。感謝更短的版本。 – ponder275

回答

4

你確定他們是平等的嗎?方法equals對於DateCalendar意味着它們表示相同的時間值(與Epoch的毫秒偏移量)。請參閱javadocs for Calendar.equals method

將此日曆與指定的對象進行比較。當且僅當參數是同一日曆系統的日曆對象,並且在與該對象相同的日曆參數下表示相同時間值(與紀元毫秒偏移)時,結果爲true。

before method docs states 用於決定日曆實例是否在另一個之前。再次,compareTo正在使用毫秒精度。從the docs

比較時間值(從曆元毫秒偏移量)由兩個日曆對象表示。

的替代方案是:

  1. 如果你必須使用日曆,創建新實例,對他們使用clear方法,然後使用set method設定值(年,月,HOUROFDAY,分,秒) 。
  2. 使用新java.time API,選擇某種類型更好地代表了你想要的東西(也許java.time.LocalDate
  3. 使用Joda Time如果你不能去到Java 8
+0

感謝您的信息! – ponder275

+0

爲了我的目的,我只需要設置日,月和年。清除Calendar實例後,如何知道將字段設置爲的內容。我是否使用帶有未清除日曆實例的get方法? – ponder275

1

answer by marcospereira是正確的。我將添加一些關於修改問題中顯示的代碼的一般性建議,並顯示java.time的使用。

使用java.sql中只對數據庫傳輸

千萬不要錯過身邊的java.sql類型並對其執行業務邏輯。僅使用java.sql將數據傳入和傳出數據庫。對於java.sql.Timestamp/.Date /.Time立即將它們轉換爲java.time對象。然後繼續您的業務邏輯。

LocalDate due = myJavaSqlDate.toLocalDate(); 

避免舊日期,時間類

避免與最早版本的Java,如java.util.Date/.Calendar捆綁舊日期時間類。他們混亂,設計不好,麻煩。

java.time

在Java 8和更高版本,舊的日期時類已被java.time框架所取代。這些新課程是一個巨大的改進。受JSR 310定義的Joda-Time的啓發,並由ThreeTen-Extra項目擴展。

日期,唯一的價值

在問題的代碼暗示你想要只包含日期值,如java.sql.Date僞裝成工作。然而,你將它與java.util.Calendar混合在一起,它代表日期

在此答案的上方,您可以獲得java.time.LocalDate類。此課程僅表示沒有時間和時區的僅限日期的值。

時區

時區在處理僅限日期的值時至關重要。只有日期(沒有時間)是固有的模糊。世界上任何時候的日期都不一樣。新的一天在東部早些時候出現。在巴黎午夜之後的幾分鐘仍然是蒙特利爾的「昨天」。

所以要確定「今天」需要一個時區。如果未指定,則隱式應用JVM的當前默認時區。不好。根據主機操作系統和JVM的設置,運行結果可能會有所不同。默認時區甚至可以在運行時通過JVM中任何應用程序的任何線程中的任何代碼進行更改。

因此,最好明確指定所需的/預期的時區。

ZoneId zoneId = ZoneId.of("America/Montreal"); 
LocalDate today = LocalDate.now(zoneId); 

現在比較看是否已過期。

if(today.isAfter(due)) { 
    // Overdue. 
} 
+0

你是對的我只需要僅限日期的信息,但我還需要在日期的另一部分中更改日期15天,這就是爲什麼我使用Calendar類的原因。我們的項目使用Java 7,所以我不能使用新的框架。我可以問,看看我們是否可以包括Joda-Time。這段代碼永遠不會跨時區使用,所以我仍然需要擔心顯式聲明時區? – ponder275

+0

要更改日期,請調用'plusDays'或'minusDays'方法:'today.plusDays(15)'。至於指定時區,是的總是明確指定。如果系統管理員在主機操作系統上更改時區,或者在啓動JVM的命令行上指定開關,則軟件會出現錯誤的日期。嘗試調試時,這是一個*可怕的問題。如果您希望時區爲「America/LosAngeles」或「Europe/Paris」或「Asia/Kolkata」,請說出來。保持不變並全面使用它。至於Joda-Time,是的,如果在Java 8之前肯定會使用它;具有相同的LocalDate和時區類。 –

+1

@ ponder275 **更新:** Joda-Time項目現在處於維護模式。該項目建議遷移到java.time類。對於Java 6和7,使用* ThreeTen-Backport *項目而不是Joda-Time。對於較早的Android,請參閱* ThreeTenABP *項目。 –

0

另一種方法是比較yyyy,mm,dd字段。如果它們是相同的 - 不使用.after()和.before() Simon Franz

相關問題