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

您的位置:首頁(yè)技術(shù)文章
文章詳情頁(yè)

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

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

在項(xiàng)目中,需要獲取指定年份和月份的最后一天。我在網(wǎng)上找到了一個(gè)用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類的實(shí)例Calendar c = Calendar.getInstance();//設(shè)置年份c.set(Calendar.YEAR, year);//設(shè)置月份,因?yàn)樵路輳?開(kāi)始,所以用month - 1c.set(Calendar.MONTH, month - 1);//獲取當(dāng)前時(shí)間下,該月的最大日期的數(shù)字int lastDay = c.getActualMaximum(Calendar.DAY_OF_MONTH);//將獲取的最大日期數(shù)設(shè)置為Calendar實(shí)例的日期數(shù)c.set(Calendar.DAY_OF_MONTH, lastDay); return c.getTime();}}

剛開(kāi)始使用這個(gè)方法的時(shí)候,很正常。后來(lái)在10月31號(hào)(這個(gè)日期很重要)當(dāng)天測(cè)試的時(shí)候,傳遞的參數(shù)時(shí)2017年9月,即上面的代碼,但是結(jié)果卻出現(xiàn)的了問(wèn)題,結(jié)果如下圖:

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

本來(lái)該是2017-09-30,可是結(jié)果卻是2017-10-01,我原先測(cè)試過(guò),這個(gè)方法是沒(méi)有問(wèn)題的,可是出了這樣的問(wèn)題。后來(lái)我斷點(diǎn)測(cè)試,在剛獲取到Calendar實(shí)例的時(shí)候,實(shí)例中的字段值如下圖:

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

但是發(fā)現(xiàn)在執(zhí)行完

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

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

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

因此,可以判斷Calendar實(shí)例獲取到的時(shí)候,是10月31號(hào),實(shí)例中的DAY_OF_MONTH的值是31,當(dāng)把MONTH字段的值設(shè)置為8后,因?yàn)?月份只有30天,那DAY_OF_MONTH的值就多1,會(huì)自動(dòng)向后順延1天,變成了2017-10-01 。

但是,還是有其他的問(wèn)題,因?yàn)橄旅孢€執(zhí)行了

c.set(Calendar.DAY_OF_MONTH, lastDay);

這句代碼,最后的日期應(yīng)該是2017-10-31才對(duì),但是run的結(jié)果卻是2017-10-01,debug的結(jié)果是2017-10-31 。

我第一感覺(jué)認(rèn)為Calendar類是不是存在線程安全問(wèn)題,可是后來(lái)一想就覺(jué)得不對(duì),畢竟我只是在主線程中運(yùn)行,沒(méi)有多線程,并不存在這個(gè)問(wèn)題。

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

因此,可以做如下修改:

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

在代碼中,直接打印變量c的值,可以發(fā)現(xiàn),在調(diào)用get()方法之前,變量c的各字段值是set()方法設(shè)置的,但是并沒(méi)有對(duì)其進(jìn)行驗(yàn)證計(jì)算,在調(diào)用get()方法的過(guò)程中,會(huì)對(duì)各字段驗(yàn)證計(jì)算。我查看了部分源碼,在調(diào)用get(),add(),getTime()等方法的過(guò)程中,底層都會(huì)調(diào)用computeTime()方法,對(duì)各字段的時(shí)間驗(yàn)證計(jì)算。

另外,又做了一個(gè)demo測(cè)試,以佐證上面的結(jié)論,如下:

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); //將月份設(shè)置為9月c.set(Calendar.DAY_OF_MONTH, 32); //將日期設(shè)置為32System.out.println(c); //直接打印Calendar實(shí)例,不使用getTime()方法c.get(Calendar.MONTH);System.out.println(c);}}

結(jié)果如下:

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

即使設(shè)置的DAY_OF_MONTH值是明顯非法的,但是并不會(huì)在調(diào)用get()方法之前進(jìn)行計(jì)算進(jìn)位。

在查詢問(wèn)題的過(guò)程中,也看到了其他的一些問(wèn)題,下面對(duì)add(),set(),roll()方法的區(qū)別做了解釋:

示例代碼:

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方法

以調(diào)整的單位為基點(diǎn)(本例中為月),較大的單位(年)會(huì)發(fā)生借位、進(jìn)位。 較小的單位會(huì)往小調(diào)整。 本例中,2014-03-31,加上13個(gè)月,年份會(huì)進(jìn)位為2015年。 4月31日是不存在的,所以往小調(diào)整為4月30日。 比較典型的運(yùn)用場(chǎng)景是,日歷的按月切換。 當(dāng)前日期為2014-03-31,點(diǎn)擊【下一月】按鈕時(shí),日期會(huì)變成2014-04-30.

SET方法

所有的單位都會(huì)往大調(diào)整。 本例中,2014-03-31,加上13個(gè)月,年份會(huì)進(jìn)位為2015年。 4月31日是不存在的,所以往大調(diào)整為5月1日

ROLL方法

以調(diào)整的單位為基點(diǎn)(本例中為月),較大的單位(年)不會(huì)發(fā)生改變。 較小的單位會(huì)往小調(diào)整。 本例中,2014-03-31,加上13個(gè)月,年份依然為2014年。 4月31日是不存在的,所以往小調(diào)整為4月30日。 日會(huì)根據(jù)年、月來(lái)判斷出日的取值范圍,然后在1~31之間無(wú)限循環(huán)滾動(dòng),但并不會(huì)影響到年、月的值。

總結(jié)三點(diǎn):

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

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

方法可以改為:

public static Date getLastDay(int year, int month) {Calendar c = Calendar.getInstance(); //獲取Calendar類的實(shí)例c.clear();c.set(Calendar.YEAR, year); //設(shè)置年份c.set(Calendar.MONTH, month - 1); //設(shè)置月份,因?yàn)樵路輳?開(kāi)始,所以用month - 1int lastDay = c.getActualMaximum(Calendar.DAY_OF_MONTH); //獲取當(dāng)前時(shí)間下,該月的最大日期的數(shù)字c.set(Calendar.DAY_OF_MONTH, lastDay); //將獲取的最大日期數(shù)設(shè)置為Calendar實(shí)例的日期數(shù)return c.getTime(); //返回日期}

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

當(dāng)然網(wǎng)上也有將月份設(shè)置為下個(gè)月,然后用add(Calendar.DAY_OF_MONTH, -1)這樣的方法也可以得到結(jié)果,不過(guò)這里就不詳細(xì)介紹了。

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

標(biāo)簽: Java
相關(guān)文章:
日本不卡不码高清免费观看,久久国产精品久久w女人spa,黄色aa久久,三上悠亚国产精品一区二区三区
欧美视频精品全部免费观看| 国产精品视频一区视频二区| 蜜桃成人av| 日韩高清在线观看一区二区| 日韩极品在线观看| 欧美日韩精品一区二区视频| 日本亚洲不卡| 欧美在线网站| 韩日一区二区| 日韩精品导航| 欧美亚洲国产激情| 国产精品日本| 久久精品国产久精国产爱| 开心激情综合| 精品久久精品| 久久国产精品久久久久久电车| 国产精品任我爽爆在线播放| 婷婷综合成人| 国产一级久久| 日韩精品中文字幕第1页| 精品一区二区三区免费看| 久久99免费视频| 国产伦理久久久久久妇女| 日本不卡一区二区三区| 日韩一区二区三区精品| 亚洲一级大片| 日韩高清一级| 日本午夜免费一区二区| 久久成人亚洲| 日韩精品网站| 福利在线一区| 精品国产日韩欧美精品国产欧美日韩一区二区三区 | 日韩欧美另类一区二区| 日韩在线观看中文字幕| 欧美成人午夜| 在线手机中文字幕| 精品丝袜久久| 色天使综合视频| 亚洲成人一区在线观看| 激情五月综合网| 国产亚洲在线观看| 国产欧美日韩影院| 国产精品成久久久久| 国内激情久久| 国产亚洲观看| 亚洲国产成人精品女人| 日本精品国产| 日韩精品亚洲专区在线观看| 国产一区二区三区亚洲| 久久精品亚洲人成影院 | 日韩理论片av| 免费污视频在线一区| 在线一区二区三区视频| 国产激情欧美| 蜜臀a∨国产成人精品| 国产一区二区三区网| 免费在线观看视频一区| 国产福利片在线观看| 免费日韩av| 日韩一区自拍| 欧美一区免费| 玖玖精品视频| 欧洲在线一区| 电影91久久久| 日韩av中文在线观看| 成人在线丰满少妇av| 涩涩涩久久久成人精品| 国产精品久久久久久久久久妞妞| 在线视频日韩| 精品91福利视频| 日韩不卡一区二区| 亚洲毛片视频| 奶水喷射视频一区| 精品国产欧美日韩| 国产精品magnet| 天堂va在线高清一区| 亚洲欧美不卡| 亚洲激情国产| 日韩一级精品| 性一交一乱一区二区洋洋av| 在线亚洲人成| 99视频精品全国免费| 精品欧美一区二区三区在线观看| 成人在线丰满少妇av| 国产精品**亚洲精品| 牛牛精品成人免费视频| 日韩av中文字幕一区二区 | 欧美一级鲁丝片| 国产不卡一区| 亚洲国产专区校园欧美| 欧美亚洲国产激情| 日韩中文字幕1| 国产精品jk白丝蜜臀av小说| 日韩精品欧美大片| 日本成人中文字幕| 国产日韩免费| 日韩欧美自拍| 蜜桃免费网站一区二区三区| 亚洲免费毛片| 免费日韩一区二区三区| 国产日韩电影| 奶水喷射视频一区| 国产乱子精品一区二区在线观看| 日韩成人免费| 亚洲一二av| 国产在线视频欧美一区| 欧美日韩激情在线一区二区三区| 日韩在线一二三区| 国产极品一区| 国产视频一区欧美| 久久精品系列| 久久亚洲欧洲| 日韩精品成人| 日韩中文字幕| 日韩一区二区三区免费| 欧美伊人久久| 久久av在线| 99国产精品一区二区| 久久精品99久久久| 鲁大师成人一区二区三区| 国产福利亚洲| 欧美日中文字幕| 你懂的国产精品永久在线| 亚洲午夜在线| 久久国产精品美女| 日韩精品免费视频人成| 亚洲一卡久久| 婷婷综合在线| 久久精品99久久无色码中文字幕| 国产日韩欧美一区二区三区在线观看| 午夜av一区| 亚洲高清二区| 色偷偷色偷偷色偷偷在线视频| 国产精品一区二区精品| 日本不卡不码高清免费观看| 欧美日韩国产免费观看视频| 日韩欧美二区| 国产精品99精品一区二区三区∴ | 欧美精品成人| 国产三级精品三级在线观看国产| 亚洲最大av| 日本视频在线一区| 青青草视频一区| 国产精品久久久久久久久久妞妞| 国产伦理一区| 国产精品伦理久久久久久| 国产成人1区| 日本不卡免费高清视频在线| 啪啪国产精品| av不卡免费看| 一区二区不卡| 欧美在线91| 日韩成人午夜精品| 精品视频网站| 亚洲精品888| 91精品美女| 日韩精品电影| 久久国产精品久久久久久电车| 亚洲五月综合| 视频在线不卡免费观看| 国产一区导航| 91欧美国产| 欧美中文字幕| 国产欧美日韩精品高清二区综合区| 91亚洲国产| 亚洲区第一页| 日韩免费福利视频| 欧美综合另类| 五月国产精品| 91精品蜜臀一区二区三区在线| 尤物在线精品| 精品国内亚洲2022精品成人| 国产91精品对白在线播放| 日韩专区视频网站| 国内激情久久| 国产成人久久精品麻豆二区 | 国产日本精品| 好看的亚洲午夜视频在线| 69精品国产久热在线观看| 999国产精品永久免费视频app| 麻豆国产欧美日韩综合精品二区| 黄色在线一区| 欧美91视频| 国产99久久| 日韩不卡免费高清视频| 国产不卡精品在线| 日韩va亚洲va欧美va久久| 国产精品v日韩精品v欧美精品网站 | 久久精品国产久精国产| 五月亚洲婷婷 | 久久青草久久| 日韩在线不卡| 日韩高清中文字幕一区二区| 91欧美国产| 日韩欧美综合| 在线日韩电影| 免费成人网www| 亚洲在线观看| 亚洲精品在线a| 国产欧美日韩一区二区三区四区 |