Java Date Nuances的痛苦提醒
這些天,我不再需要使用java.util.Date了,但是最近選擇這樣做,這讓我想起了使用與Java Date關(guān)聯(lián)的API的痛苦 。 在這篇文章中,我看了棄用的參數(shù)化Date構(gòu)造函數(shù)的一些令人驚訝的API期望,該構(gòu)造函數(shù)接受六個整數(shù) 。
在2016年,如果使用Java SE 8編寫新代碼,則Java開發(fā)人員很可能會使用Java 8的新Date / Time API,或者如果使用Java的版本,則可能會使用第三方Java日期/時間庫(例如Joda-Time) 。 Java早于Java8。我選擇最近在一個非常簡單的基于Java的工具中使用Date ,我希望將它作為單個Java源代碼文件交付(無需構(gòu)建工具即可輕松編譯)并且不依賴于外部的任何庫。 Java SE。 此簡單工具的目標(biāo)部署環(huán)境是Java SE 7,因此不能選擇Java 8 Date / Time API。
接受六個整數(shù)的Date構(gòu)造函數(shù)的缺點(diǎn)之一是這六個整數(shù)之間的區(qū)別,并確保按正確的順序提供它們。 即使強(qiáng)制執(zhí)行正確的命令,指定月份和年份也會有一些細(xì)微的意外。 正確實(shí)例化Date對象的最簡單方法也許是通過SimpleDateFormat 。 parse(String)或通過不建議使用的Date(long)構(gòu)造函數(shù)接受從時期零開始的毫秒數(shù)。
我的第一個代碼清單演示了一個用0小時,0分鐘和0秒表示一個表示“ 2016年9月26日”的Date實(shí)例。 此代碼清單使用String通過SimpleDateFormat.parse(String)實(shí)例化Date實(shí)例。
final SimpleDateFormat formatter = new SimpleDateFormat(DEFAULT_FORMAT); final Date controlDate = formatter.parse(CONTROL_DATE_TIME_STR); printDate("Control Date/Time", controlDate);運(yùn)行上述命令時,打印結(jié)果將達(dá)到預(yù)期效果,并且輸出日期與為Date實(shí)例提供并分析的字符串匹配。
============================================================= = Control Date/Time -> Mon Sep 26 00:00:00 MDT 2016 =============================================================使用接受整數(shù)以表示Date實(shí)例的不同“字段”的Date構(gòu)造函數(shù)可能會很誘人,但它們會帶來前面提到的細(xì)微差別。
下一個代碼清單顯示了一種非常幼稚的方法來調(diào)用Date構(gòu)造函數(shù),該構(gòu)造函數(shù)接受六個以下列順序表示這些字段的整數(shù):年,月,日期,小時,分鐘,秒。
// This will NOT be the intended Date of 26 September 2016 // with 0 hours, 0 minutes, and 0 seconds because both the // "month" and "year" parameters are NOT appropriate. final Date naiveDate = new Date(2016, 9, 26, 0, 0, 0); printDate("new Date(2016, 9, 26, 0, 0, 0)", naiveDate);運(yùn)行上述代碼的輸出與前面顯示的“控制”案例沒有相同的月份(10月而不是9月)或年份(不是2016年)。
============================================================= = new Date(2016, 9, 26, 0, 0, 0) -> Thu Oct 26 00:00:00 MDT 3916 =============================================================月比我們預(yù)期的晚了一個月(10月而不是9月),因?yàn)閙onth參數(shù)是從零開始的參數(shù),一月由0表示,九月由8而不是9表示。這是處理以下問題的最簡單方法之一從零開始的月份,對Date構(gòu)造函數(shù)的更可讀的調(diào)用是為月份使用適當(dāng)?shù)膉ava.util.Calendar字段。 下一個示例演示如何使用Calendar.SEPTEMBER進(jìn)行此操作。
// This will NOT be the intended Date of 26 September 2016 // with 0 hours, 0 minutes, and 0 seconds because the // "year" parameter is not correct. final Date naiveDate = new Date(2016, Calendar.SEPTEMBER, 26, 0, 0, 0); printDate("new Date(2016, Calendar.SEPTEMBER, 26, 0, 0, 0)", naiveDate);剛剛列出的代碼段修復(fù)了月份規(guī)范,但是年份仍然不正確,如下面顯示的關(guān)聯(lián)輸出所示。
============================================================= = new Date(2016, Calendar.SEPTEMBER, 26, 0, 0, 0) -> Tue Sep 26 00:00:00 MDT 3916 =============================================================這一年仍然相距1900年(而不是2016年為3916年)。 這是由于決定將六整數(shù)Date構(gòu)造函數(shù)的第一個整數(shù)參數(shù)指定為年份,減去1900年。因此,提供“ 2016”作為第一個參數(shù),將年份指定為2016 + 1900 = 3916。 ,要解決此問題,我們需要提供116(2016-1900)作為構(gòu)造函數(shù)的第一個int參數(shù)。 為了使普通人更容易理解這一點(diǎn),我喜歡將其字面編碼為2016-1900,如下面的代碼清單所示。
final Date date = new Date(2016-1900, Calendar.SEPTEMBER, 26, 0, 0, 0); printDate("new Date(2016-1900, Calendar.SEPTEMBER, 26, 0, 0, 0)", date);在使用從零開始的月份并將預(yù)期年份表示為當(dāng)前年份減去1900的情況下,正確地實(shí)例化Date ,如在下一個輸出列表中所示。
============================================================= = new Date(2016-1900, Calendar.SEPTEMBER, 26, 0, 0, 0) -> Mon Sep 26 00:00:00 MDT 2016 =============================================================Date的Javadoc文檔確實(shí)描述了這些細(xì)微差別,但這提醒人們,最好使用清晰,可理解的API,不需要注釋中描述的細(xì)微差別。 Date(int,int,int,int,int,int)構(gòu)造函數(shù)的Javadoc確實(shí)宣告,年需要減去1900,并且月份由0到11之間的整數(shù)表示。它還描述了為什么此六整數(shù)構(gòu)造函數(shù)已棄用 :“從JDK版本1.1開始,由Calendar.set(年+ 1900,月,日期,小時,分鐘,秒)或GregorianCalendar(年+ 1900,月,日期,小時,分鐘,秒)代替。”
不建議使用類似的六整數(shù)GregorianCalendar(int,int,int,int,int,int)構(gòu)造函數(shù),盡管它仍然期望從零開始的month參數(shù),但是在證明時,它不希望一個參數(shù)將1900減去實(shí)際年份。年參數(shù)。 當(dāng)使用適當(dāng)?shù)腃alendar month常量指定月份時,當(dāng)可以在年份中傳遞2016年并且可以在月份中傳遞Calendar.SEPTEMBER時,這將使API調(diào)用更具可讀性。
我現(xiàn)在很少直接使用Date類,以至于我忘記了它的細(xì)微差別,并且在極少數(shù)場合讓我再次使用Date時必須重新學(xué)習(xí)它們。 因此,我將這些有關(guān)Date觀察留給我自己。
通過使用他人的API,我們可以學(xué)到很多有關(guān)使API有用且易于學(xué)習(xí)的知識,以及使API較難學(xué)習(xí)的知識。 希望這些經(jīng)驗(yàn)教訓(xùn)將有助于我們編寫自己的API。 這篇文章的重點(diǎn)是Date(int, int, int, int, int, int)構(gòu)造函數(shù),它提出了一些問題,這些問題導(dǎo)致API不夠理想。 相同類型的多個參數(shù)可以輕松地亂序提供參數(shù),而與提供年份和月份有關(guān)的“不自然”規(guī)則給客戶端開發(fā)人員增加了負(fù)擔(dān),使他們不得不閱讀Javadoc來理解這些不太明顯的內(nèi)容規(guī)則。
翻譯自: https://www.javacodegeeks.com/2016/09/painful-reminder-java-date-nuances.html
總結(jié)
以上是生活随笔為你收集整理的Java Date Nuances的痛苦提醒的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: junit白盒测试 案例_JUnit通过
- 下一篇: 气壮山什么 气壮山什么的四字成语