Java日期與日曆


Answers

新代碼(如果您的政策允許第三方代碼)的最佳方式是使用joda-time.sourceforge.net

DateCalendar都具有如此多的設計問題,既不是新代碼的良好解決方案。

Question

有人可以提供有關DateCalendar類型的最新“最佳做法”建議。

在編寫新代碼時,是否最好始終支持Calendar over Date ,或者是否存在Date是更合適的數據類型的情況?




順便說一句“日期”通常被標記為“過時/棄用”(我不知道到底是為什麼) - 關於它的一些東西寫在那裡Java:為什麼Date構造函數不推薦使用,我該怎麼用?

它看起來像只是構造函數的一個問題 - 通過新的Date(int year,int month,int day) ,推薦的方法是通過Calendar並分別設置params ..( Calendar cal = Calendar.getInstance();




我總是主張joda-time.sourceforge.net 。 這是為什麼。

  1. 該API是一致且直觀的。 與java.util.Date/Calendar API不同
  2. 它不會遇到線程問題,與java.text.SimpleDateFormat等不同(我已經看到許多客戶端問題與沒有意識到標準日期/時間格式不是線程安全的)
  3. 它是新的Java日期/時間API( JSR310 ,計劃用於Java 8)的基礎。因此,您將使用將成為核心Java API的API。



TL;博士

建議DateCalendar周圍的當前“最佳做法”

最好總是讚成Calendar over Date

完全避免這些遺留類 。 改用java.time類。

細節

Ortomala Lokni的回答是正確的建議使用現代java.time類而不是麻煩的舊的遺留日期 - 時間類( DateCalendar等)。 但是那個答案表明錯誤的類是等價的(請參閱我對該答案的評論)。

使用java.time

java.time類相對於傳統的日期時間類,日夜差異有了巨大的改進。 舊班級設計不佳,令人困惑和麻煩。 只要有可能,你應該避免使用舊的類。 但是,當你需要轉換/從舊/新,你可以通過調用新的方法添加到舊的類。

有關轉換的更多信息,請參閱我的答案和漂亮的圖到另一個問題, 將java.util.Date轉換為什麼“java.time”類型? 。

搜索堆棧溢出提供了許多關於使用java.time的示例問題和解答。 但這裡有一個簡短的概要。

Instant

使用Instant獲取當前時刻。 Instant類表示UTC時間軸上的某個時刻,分辨率為nanoseconds (小數點後最多九位數字)。

Instant instant = Instant.now();

ZonedDateTime

要通過某個特定區域的掛鐘時間的鏡頭查看同一時刻 ,請應用時區( ZoneId )以獲取ZonedDateTime

時區

continent/region格式指定適當的時區名稱 ,例如America/MontrealAfrica/CasablancaPacific/Auckland 。 切勿使用3-4字母縮寫(如ESTIST因為它們不是真正的時區,不是標準化的,甚至不是唯一的(!)。

ZoneId z = ZoneId.of( "America/Montreal" );
ZonedDateTime zdt = instant.atZone();

抵消

時區是一個區域offset-from-UTC變化的歷史記錄。 但是有時候只有在沒有完整區域的情況下才會給出偏移量。 在這種情況下,使用OffsetDateTime類。

ZoneOffset offset = ZoneOffset.parse( "+05:30" );
OffsetDateTime odt = instant.atOffset( offset );

使用時區比使用單純的偏移更可取。

LocalDateTime

Local…類中的“Local”意味著任何地點,而不是特定的地點。 所以這個名字可能是反直覺的。

LocalDateTimeLocalDateLocalTime故意缺少有關偏移或時區的任何信息。 所以他們不代表實際的時刻,他們不是時間線上的要點。 如有疑問或疑惑,請使用ZonedDateTime而不是LocalDateTime 。 搜索堆棧溢出進行更多討論。

字符串

不要將日期 - 時間對象與代表其值的字符串混淆。 您可以解析一個字符串來獲取日期時間對象,並且可以從日期時間對像中生成一個字符串。 但是這個字符串從來就不是日期時間本身。

了解標準ISO 8601格式,默認情況下在java.time類中使用。

關於java.time

java.time框架內置於Java 8及更高版本中。 這些類取代了諸如java.util.DateCalendarSimpleDateFormat等麻煩的舊式legacy日期時間類。

現在處於維護模式Joda-Time項目建議遷移到java.time類。

要了解更多信息,請參閱Oracle教程 。 並蒐索堆棧溢出了很多例子和解釋。 規範是JSR-310

使用符合JDBC 4.2或更高版本的JDBC驅動程序 ,您可以直接與數據庫交換java.time對象。 不需要字符串和java.sql。*類。

何處獲取java.time類?

  • Java SE 8Java SE 9和更高版本
    • 內置。
    • 帶有捆綁實現的標準Java API的一部分。
    • Java 9增加了一些次要功能和修復。
  • Java SE 6Java SE 7
  • Android
    • 後續版本的java.time類的Android捆綁實現。
    • 對於早期的Android, ThreeTenABP項目採用ThreeTen-Backport (上文提到)。 請參閱如何使用ThreeTenABP ...。

ThreeTen-Extra項目將java.time擴展到其他類。 這個項目是未來可能增加java.time的一個試驗場。 您可以在這裡找到一些有用的課程,例如IntervalYearWeekYearQuarter等。




如果可能,我通常使用Date。 儘管它是可變的,但實際上已經不贊成了。 最後,它基本上包含了一段代表日期/時間的長度。 相反,如果我必須操作這些值,我會使用日曆。

你可以這樣想:只有當你需要有可以容易操作的字符串時才使用StringBuffer,然後使用toString()方法將它們轉換為字符串。 以同樣的方式,如果我需要操作時態數據,我只使用日曆。

為了最佳實踐,我傾向於盡可能在域模型之外使用不可變對象。 它顯著減少了任何副作用的機會,並且它由編譯器完成,而不是JUnit測試。 您可以通過在班級中創建私人最終字段來使用此技巧。

然後回到StringBuffer的比喻。 以下是一些代碼,告訴您如何在日曆和日期之間進行轉換

String s = "someString"; // immutable string
StringBuffer buf = new StringBuffer(s); // mutable "string" via StringBuffer
buf.append("x");
assertEquals("someStringx", buf.toString()); // convert to immutable String

// immutable date with hard coded format.  If you are hard
// coding the format, best practice is to hard code the locale
// of the format string, otherwise people in some parts of Europe
// are going to be mad at you.
Date date =     new SimpleDateFormat("yyyy-MM-dd", Locale.ENGLISH).parse("2001-01-02");

// Convert Date to a Calendar
Calendar cal = Calendar.getInstance();
cal.setTime(date);

// mutate the value
cal.add(Calendar.YEAR, 1);

// convert back to Date
Date newDate = cal.getTime();

// 
assertEquals(new SimpleDateFormat("yyyy-MM-dd", Locale.ENGLISH).parse("2002-01-02"), newDate);



日期最適合存儲日期對象。 它是持續的,序列化的...

日曆最適合操作日期。

注意:我們有時也贊成在Date上使用java.lang.Long,因為Date是可變的,因此不是線程安全的。 在Date對像上,使用setTime()和getTime()在兩者之間切換。 例如,應用程序中的常量Date(例如:1970年1月1日的零,或者設置為2099年12月31日的應用END_OF_TIME;這些非常有用,可以將空值替換為開始時間和結束時間,特別是當你將它們存在數據庫中時,因為SQL對於空值是特殊的)。




Related