日本不卡不码高清免费观看,久久国产精品久久w女人spa,黄色aa久久,三上悠亚国产精品一区二区三区

您的位置:首頁技術文章
文章詳情頁

解決Java Calendar類set()方法的陷阱

瀏覽:180日期:2022-09-05 08:30:47

在項目中,需要獲取指定年份和月份的最后一天。我在網上找到了一個用Calendar類獲取的方法,代碼如下:

import java.text.SimpleDateFormat;import java.util.Calendar;import java.util.Date; public class TestCalendar {public static void main(String[] args) {String s = new SimpleDateFormat('yyyy-MM-dd').format(getLastDay(2017, 9));System.out.println(s);} public static Date getLastDay(int year, int month) {//獲取Calendar類的實例Calendar c = Calendar.getInstance();//設置年份c.set(Calendar.YEAR, year);//設置月份,因為月份從0開始,所以用month - 1c.set(Calendar.MONTH, month - 1);//獲取當前時間下,該月的最大日期的數字int lastDay = c.getActualMaximum(Calendar.DAY_OF_MONTH);//將獲取的最大日期數設置為Calendar實例的日期數c.set(Calendar.DAY_OF_MONTH, lastDay); return c.getTime();}}

剛開始使用這個方法的時候,很正常。后來在10月31號(這個日期很重要)當天測試的時候,傳遞的參數時2017年9月,即上面的代碼,但是結果卻出現的了問題,結果如下圖:

解決Java Calendar類set()方法的陷阱

本來該是2017-09-30,可是結果卻是2017-10-01,我原先測試過,這個方法是沒有問題的,可是出了這樣的問題。后來我斷點測試,在剛獲取到Calendar實例的時候,實例中的字段值如下圖:

解決Java Calendar類set()方法的陷阱

但是發現在執行完

c.set(Calendar.MONTH, month - 1);

這行的代碼的時候,Calendar的實例中,MONTH字段的值不是我預想中的8(月份字段從0開始),而是9,而且DAY_OF_MONTH字段的值從31變成了1,如下圖所示:

解決Java Calendar類set()方法的陷阱

因此,可以判斷Calendar實例獲取到的時候,是10月31號,實例中的DAY_OF_MONTH的值是31,當把MONTH字段的值設置為8后,因為9月份只有30天,那DAY_OF_MONTH的值就多1,會自動向后順延1天,變成了2017-10-01 。

但是,還是有其他的問題,因為下面還執行了

c.set(Calendar.DAY_OF_MONTH, lastDay);

這句代碼,最后的日期應該是2017-10-31才對,但是run的結果卻是2017-10-01,debug的結果是2017-10-31 。

我第一感覺認為Calendar類是不是存在線程安全問題,可是后來一想就覺得不對,畢竟我只是在主線程中運行,沒有多線程,并不存在這個問題。

第二天我又嘗試了下,發現了問題的原因,如上面的最后一張圖所示,在debug的過程中,我用IDEA的watches功能查看了Calendar實例的字段值,用了get()方法,如果我刪除掉這幾個get方法之后,發現run和debug的值是一樣的,都是2017-10-01,說明問題出在get()方法上。

因此,可以做如下修改:

解決Java Calendar類set()方法的陷阱

在代碼中,直接打印變量c的值,可以發現,在調用get()方法之前,變量c的各字段值是set()方法設置的,但是并沒有對其進行驗證計算,在調用get()方法的過程中,會對各字段驗證計算。我查看了部分源碼,在調用get(),add(),getTime()等方法的過程中,底層都會調用computeTime()方法,對各字段的時間驗證計算。

另外,又做了一個demo測試,以佐證上面的結論,如下:

import java.text.SimpleDateFormat;import java.util.Calendar; public class TestCalendar2 { public static void main(String[] args) {Calendar c = Calendar.getInstance();c.set(Calendar.MONTH, 8); //將月份設置為9月c.set(Calendar.DAY_OF_MONTH, 32); //將日期設置為32System.out.println(c); //直接打印Calendar實例,不使用getTime()方法c.get(Calendar.MONTH);System.out.println(c);}}

結果如下:

解決Java Calendar類set()方法的陷阱

即使設置的DAY_OF_MONTH值是明顯非法的,但是并不會在調用get()方法之前進行計算進位。

在查詢問題的過程中,也看到了其他的一些問題,下面對add(),set(),roll()方法的區別做了解釋:

示例代碼:

Calendar c = Calendar.getInstance(); c.set(2014, Calendar.MARCH, 31);c.add(Calendar.MONTH, 13);System.out.println(c.getTime());// 2015-04-30 c.set(2014, Calendar.MARCH, 31);c.set(Calendar.MONTH, c.get(Calendar.MONTH) + 13);System.out.println(c.getTime());// 2015-05-01 c.set(2014, Calendar.MARCH, 31);c.roll(Calendar.MONTH, 13);System.out.println(c.getTime());//2014-04-30

ADD方法

以調整的單位為基點(本例中為月),較大的單位(年)會發生借位、進位。 較小的單位會往小調整。 本例中,2014-03-31,加上13個月,年份會進位為2015年。 4月31日是不存在的,所以往小調整為4月30日。 比較典型的運用場景是,日歷的按月切換。 當前日期為2014-03-31,點擊【下一月】按鈕時,日期會變成2014-04-30.

SET方法

所有的單位都會往大調整。 本例中,2014-03-31,加上13個月,年份會進位為2015年。 4月31日是不存在的,所以往大調整為5月1日

ROLL方法

以調整的單位為基點(本例中為月),較大的單位(年)不會發生改變。 較小的單位會往小調整。 本例中,2014-03-31,加上13個月,年份依然為2014年。 4月31日是不存在的,所以往小調整為4月30日。 日會根據年、月來判斷出日的取值范圍,然后在1~31之間無限循環滾動,但并不會影響到年、月的值。

總結三點:

1、add() 有兩條規則: a)當被修改的字段超出它的取值范圍時,那么比它大的字段會自動修正。 b)如果比它小的字段是不可變的/不在取值范圍內(由 Calendar 的實現類決定),那么該小字段會修正到變化最小的值。 2、Roll() 的規則只有第二條 當被修改的字段超出它的取值范圍時,那么比它大的字段不會被修正。比它小的字段會修正到變化最小的值。 3、Set() 比被修改的字段大的字段會根據字段是增大還是減小自動改變大小,比被修改字段小的字段如果是不可變的/不在取值范圍內,會自動增大到變化最小的值。

回到最初的問題,獲取指定年份和月份的最大的日期的方法要怎么辦?

方法可以改為:

public static Date getLastDay(int year, int month) {Calendar c = Calendar.getInstance(); //獲取Calendar類的實例c.clear();c.set(Calendar.YEAR, year); //設置年份c.set(Calendar.MONTH, month - 1); //設置月份,因為月份從0開始,所以用month - 1int lastDay = c.getActualMaximum(Calendar.DAY_OF_MONTH); //獲取當前時間下,該月的最大日期的數字c.set(Calendar.DAY_OF_MONTH, lastDay); //將獲取的最大日期數設置為Calendar實例的日期數return c.getTime(); //返回日期}

用clear()方法,將Calendar實例的字段和時間都設置為未定義,這樣可以解決這個問題。

當然網上也有將月份設置為下個月,然后用add(Calendar.DAY_OF_MONTH, -1)這樣的方法也可以得到結果,不過這里就不詳細介紹了。

到此這篇關于解決Java Calendar類set()方法的陷阱的文章就介紹到這了,更多相關Java Calendar set()內容請搜索好吧啦網以前的文章或繼續瀏覽下面的相關文章希望大家以后多多支持好吧啦網!

標簽: Java
相關文章:
日本不卡不码高清免费观看,久久国产精品久久w女人spa,黄色aa久久,三上悠亚国产精品一区二区三区
免费观看在线综合| 国产一区二区三区亚洲综合| 精品黄色一级片| 日韩午夜视频在线| 91精品国产自产在线丝袜啪| 国产日韩三级| 国产一区二区亚洲| 性欧美xxxx免费岛国不卡电影| 偷拍欧美精品| 婷婷综合国产| 精品丝袜久久| 青青青免费在线视频| 色爱av综合网| 亚洲激情社区| 欧美精品影院| 日韩综合精品| 在线观看一区| 狠狠久久伊人| 国产一区视频在线观看免费| 午夜在线观看免费一区| 欧美久久久网站| www.com.cn成人| 欧美日韩在线观看首页| 久久av影院| 国产激情一区| 欧美国产极品| 久久精品青草| 亚洲精品影院在线观看| 欧美激情五月| 亚洲黄色影院| 麻豆久久久久久| 欧美亚洲激情| 国产精品一区二区av交换 | 99热精品在线观看| 亚洲精品免费观看| 91综合网人人| 亚洲毛片在线| 伊人久久国产| 日韩精品视频一区二区三区| 日韩亚洲一区在线| 婷婷综合一区| 欧洲av一区二区| 日韩福利在线观看| 亚洲精品在线影院| 日韩av中文在线观看| 精品捆绑调教一区二区三区| 日韩精品一级中文字幕精品视频免费观看 | 欧美一区成人| 高清在线一区| 中文无码久久精品| а√天堂8资源在线| 蜜桃久久久久久| 91视频精品| 日韩精品午夜视频| 亚洲视频www| 日韩久久一区二区三区| 国产精选一区| 香蕉精品视频在线观看| 精品国产成人| 欧美久久亚洲| 亚洲免费观看高清完整版在线观| 蜜桃av.网站在线观看| 国产免费播放一区二区| 国产毛片一区| 亚洲va在线| 福利视频一区| 国产精品美女久久久久久不卡| 亚洲在线观看| 在线日韩av| 中文字幕在线视频网站| 国产精品v一区二区三区| 日欧美一区二区| 91精品高清| 在线日韩av| 久久在线免费| 亚洲成人一区在线观看| 国产suv精品一区二区四区视频| 国产欧美日韩影院| 久久亚洲欧美| 亚洲激情另类| 欧美日韩国产免费观看| 色老板在线视频一区二区| 国产在视频一区二区三区吞精| 国产精品自拍区| 欧美亚洲免费| 91精品在线免费视频| 日韩手机在线| 巨乳诱惑日韩免费av| 午夜免费一区| 亚洲免费观看| 中日韩男男gay无套| 欧美一区二区三区激情视频 | 91精品国产自产观看在线| 免费视频一区二区| 中文字幕一区二区av| 天堂成人国产精品一区| 亚洲免费中文| 老牛国产精品一区的观看方式| 国产视频一区免费看| 亚洲精品888| 亚洲自啪免费| 日韩av一区二区三区| 亚洲香蕉久久| 国产精品日韩| 男女激情视频一区| 婷婷精品在线| 免费在线观看一区| 水蜜桃久久夜色精品一区| 91综合网人人| 激情久久久久久| 国产一区二区高清| 亚洲影视一区| 国产日韩1区| 精品免费在线| 精品视频久久| 91亚洲国产| 亚洲午夜一级| 一级成人国产| 六月丁香综合在线视频| 日韩成人高清| 欧美资源在线| 鲁大师精品99久久久| 国产精品视频首页| 久久精品二区亚洲w码| 日韩免费av| 国产亚洲高清视频| 日本一区二区中文字幕| 欧美黑人巨大videos精品| 亚洲永久av| 欧美特黄视频| 日韩1区2区3区| 国产成人黄色| 91精品观看| 日本午夜精品久久久久| 精品国产乱码| 夜夜精品视频| 久久99免费视频| 亚洲高清毛片| 日韩精品午夜视频| 樱桃视频成人在线观看| 首页亚洲欧美制服丝腿| 欧美国产日本| 亚洲精品1区2区| 国产精品欧美一区二区三区不卡| 成人在线免费观看网站| 在线视频精品| 国产精品视频一区二区三区四蜜臂 | 精品视频网站| 亚洲综合二区| 国产一区二区三区免费在线| 午夜久久福利| 精品亚洲二区| 视频在线在亚洲| 国产成人精品亚洲线观看| 亚洲精品电影| 国产精品www994| 亚洲综合精品四区| 国产精品成人a在线观看| 在线看片一区| 欧美日韩免费看片| 国产精品一国产精品| 性欧美69xoxoxoxo| 久久精品网址| 日韩精品欧美大片| 欧美日韩第一| 欧美国产美女| 国产精品网站在线看| 视频一区在线播放| 国产综合色区在线观看| 91精品在线免费视频| 婷婷亚洲五月| 国产v日韩v欧美v| 国产亚洲欧美日韩精品一区二区三区 | 久久www成人_看片免费不卡| 精品国产鲁一鲁****| 91综合久久爱com| 99国产成+人+综合+亚洲欧美| 激情久久99| 国产欧美88| 日韩在线电影| 综合日韩在线| 免费视频久久| 91高清一区| 欧美日韩国产一区二区三区不卡 | 精品国产亚洲一区二区三区在线| 日本欧美一区二区在线观看| 欧美另类综合| 久久人人88| 三级小说欧洲区亚洲区| 国产激情在线播放| 久久永久免费| 美腿丝袜亚洲三区| 国产视频网站一区二区三区| 亚洲乱码久久| 亚洲精品四区| 日韩高清欧美激情| 亚洲我射av| 亚洲精品进入| 日本在线观看不卡视频| 日本在线不卡视频|