From 72c4d0df710dbea5a3cf6ef589db3372d82a94c1 Mon Sep 17 00:00:00 2001 From: 6tail <6tail@6tail.cn> Date: Fri, 30 Oct 2020 12:54:22 +0800 Subject: [PATCH] =?UTF-8?q?=E6=96=B0=E5=A2=9E=E5=8F=AF=E8=87=AA=E5=AE=9A?= =?UTF-8?q?=E4=B9=89=E8=8A=82=E5=81=87=E6=97=A5=E6=95=B0=E6=8D=AE=EF=BC=9B?= =?UTF-8?q?=E6=96=B0=E5=A2=9E=E9=98=B3=E5=8E=86=E6=97=A5=E6=9C=9F=E6=8C=89?= =?UTF-8?q?=E5=B7=A5=E4=BD=9C=E6=97=A5=E6=8E=A8=E7=A7=BB=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/com/nlf/calendar/Solar.java | 30 +++++++- .../com/nlf/calendar/util/HolidayUtil.java | 74 ++++++++++++++++--- src/test/java/test/HolidayTest.java | 49 ++++++++++++ src/test/java/test/SolarTest.java | 23 ++++++ 4 files changed, 164 insertions(+), 12 deletions(-) create mode 100644 src/test/java/test/HolidayTest.java diff --git a/src/main/java/com/nlf/calendar/Solar.java b/src/main/java/com/nlf/calendar/Solar.java index da65889..9a63ee7 100644 --- a/src/main/java/com/nlf/calendar/Solar.java +++ b/src/main/java/com/nlf/calendar/Solar.java @@ -5,6 +5,7 @@ import java.util.Date; import java.util.List; +import com.nlf.calendar.util.HolidayUtil; import com.nlf.calendar.util.LunarUtil; import com.nlf.calendar.util.SolarUtil; @@ -536,9 +537,36 @@ public String toFullString(){ * @return 阳历日期 */ public Solar next(int days){ + return next(days,false); + } + + public Solar next(int days, boolean onlyWorkday){ Calendar c = Calendar.getInstance(); c.set(year,month-1,day,hour,minute,second); - c.add(Calendar.DATE,days); + if(0!=days) { + if(!onlyWorkday){ + c.add(Calendar.DATE,days); + }else { + int rest = Math.abs(days); + int add = days < 1 ? -1 : 1; + while (rest > 0) { + c.add(Calendar.DATE, add); + boolean work = true; + Holiday holiday = HolidayUtil.getHoliday(c.get(Calendar.YEAR), c.get(Calendar.MONTH)+1, c.get(Calendar.DAY_OF_MONTH)); + if(null==holiday){ + int week = c.get(Calendar.DAY_OF_WEEK); + if(1==week||7==week){ + work = false; + } + }else{ + work = holiday.isWork(); + } + if(work){ + rest--; + } + } + } + } return new Solar(c); } diff --git a/src/main/java/com/nlf/calendar/util/HolidayUtil.java b/src/main/java/com/nlf/calendar/util/HolidayUtil.java index 2bda280..ee04fa9 100644 --- a/src/main/java/com/nlf/calendar/util/HolidayUtil.java +++ b/src/main/java/com/nlf/calendar/util/HolidayUtil.java @@ -7,7 +7,7 @@ import java.util.List; /** - * 法定节假日工具(自2001年12月29日起) + * 法定节假日工具(默认自2001年12月29日起,至2020年12月31日止) * * @author 6tail */ @@ -17,11 +17,16 @@ public class HolidayUtil { private static final int SIZE = 18; /** 0 */ private static final char ZERO = '0'; - /** 节假日名称(元旦0,春节1,清明2,劳动3,端午4,中秋5,国庆6,国庆中秋7,抗战胜利日8) */ - private static final String[] NAMES = {"元旦节","春节","清明节","劳动节","端午节","中秋节","国庆节","国庆中秋","抗战胜利日"}; - /** 节假日数据,日期YYYYMMDD+名称下标+是否调休+对应节日YYYYMMDD */ + /** 默认节假日名称(元旦0,春节1,清明2,劳动3,端午4,中秋5,国庆6,国庆中秋7,抗战胜利日8) */ + public static final String[] NAMES = {"元旦节","春节","清明节","劳动节","端午节","中秋节","国庆节","国庆中秋","抗战胜利日"}; + /** 默认节假日数据,日期YYYYMMDD+名称下标+是否调休+对应节日YYYYMMDD */ private static final String DATA = "200112290020020101200112300020020101200201010120020101200201020120020101200201030120020101200202091020020212200202101020020212200202121120020212200202131120020212200202141120020212200202151120020212200202161120020212200202171120020212200202181120020212200204273020020501200204283020020501200205013120020501200205023120020501200205033120020501200205043120020501200205053120020501200205063120020501200205073120021001200209286020021001200209296020021001200210016120021001200210026120021001200210036120021001200210046120021001200210056120021001200210066120021001200210076120021001200301010120030101200302011120030201200302021120030201200302031120030201200302041120030201200302051120030201200302061120030201200302071120030201200302081020030201200302091020030201200304263020030501200304273020030501200305013120030501200305023120030501200305033120030501200305043120030501200305053120030501200305063120030501200305073120031001200309276020031001200309286020031001200310016120031001200310026120031001200310036120031001200310046120031001200310056120031001200310066120031001200310076120031001200401010120040101200401171020040122200401181020040122200401221120040122200401231120040122200401241120040122200401251120040122200401261120040122200401271120040122200401281120040122200405013120040501200405023120040501200405033120040501200405043120040501200405053120040501200405063120040501200405073120041001200405083020040501200405093020040501200410016120041001200410026120041001200410036120041001200410046120041001200410056120041001200410066120041001200410076120041001200410096020041001200410106020041001200501010120050101200501020120050101200501030120050101200502051020050209200502061020050209200502091120050209200502101120050209200502111120050209200502121120050209200502131120050209200502141120050209200502151120050209200504303020050501200505013120050501200505023120050501200505033120050501200505043120050501200505053120050501200505063120050501200505073120051001200505083020050501200510016120051001200510026120051001200510036120051001200510046120051001200510056120051001200510066120051001200510076120051001200510086020051001200510096020051001200512310020060101200601010120060101200601020120060101200601030120060101200601281020060129200601291120060129200601301120060129200601311120060129200602011120060129200602021120060129200602031120060129200602041120060129200602051020060129200604293020060501200604303020060501200605013120060501200605023120060501200605033120060501200605043120060501200605053120060501200605063120060501200605073120061001200609306020061001200610016120061001200610026120061001200610036120061001200610046120061001200610056120061001200610066120061001200610076120061001200610086020061001200612300020070101200612310020070101200701010120070101200701020120070101200701030120070101200702171020070218200702181120070218200702191120070218200702201120070218200702211120070218200702221120070218200702231120070218200702241120070218200702251020070218200704283020070501200704293020070501200705013120070501200705023120070501200705033120070501200705043120070501200705053120070501200705063120070501200705073120070501200709296020071001200709306020071001200710016120071001200710026120071001200710036120071001200710046120071001200710056120071001200710066120071001200710076120071001200712290020080101200712300120080101200712310120080101200801010120080101200802021020080206200802031020080206200802061120080206200802071120080206200802081120080206200802091120080206200802101120080206200802111120080206200802121120080206200804042120080404200804052120080404200804062120080404200805013120080501200805023120080501200805033120080501200805043020080501200806074120080608200806084120080608200806094120080608200809135120080914200809145120080914200809155120080914200809276020081001200809286020081001200809296120081001200809306120081001200810016120081001200810026120081001200810036120081001200810046120081001200810056120081001200901010120090101200901020120090101200901030120090101200901040020090101200901241020090125200901251120090125200901261120090125200901271120090125200901281120090125200901291120090125200901301120090125200901311120090125200902011020090125200904042120090404200904052120090404200904062120090404200905013120090501200905023120090501200905033120090501200905284120090528200905294120090528200905304120090528200905314020090528200909276020091001200910016120091001200910026120091001200910036120091001200910046120091001200910055120091003200910065120091003200910075120091003200910085120091003200910105020091003201001010120100101201001020120100101201001030120100101201002131120100213201002141120100213201002151120100213201002161120100213201002171120100213201002181120100213201002191120100213201002201020100213201002211020100213201004032120100405201004042120100405201004052120100405201005013120100501201005023120100501201005033120100501201006124020100616201006134020100616201006144120100616201006154120100616201006164120100616201009195020100922201009225120100922201009235120100922201009245120100922201009255020100922201009266020101001201010016120101001201010026120101001201010036120101001201010046120101001201010056120101001201010066120101001201010076120101001201010096020101001201101010120110101201101020120110101201101030120110101201101301020110203201102021120110203201102031120110203201102041120110203201102051120110203201102061120110203201102071120110203201102081120110203201102121020110203201104022020110405201104032120110405201104042120110405201104052120110405201104303120110501201105013120110501201105023120110501201106044120110606201106054120110606201106064120110606201109105120110912201109115120110912201109125120110912201110016120111001201110026120111001201110036120111001201110046120111001201110056120111001201110066120111001201110076120111001201110086020111001201110096020111001201112310020120101201201010120120101201201020120120101201201030120120101201201211020120123201201221120120123201201231120120123201201241120120123201201251120120123201201261120120123201201271120120123201201281120120123201201291020120123201203312020120404201204012020120404201204022120120404201204032120120404201204042120120404201204283020120501201204293120120501201204303120120501201205013120120501201205023020120501201206224120120623201206234120120623201206244120120623201209295020120930201209305120120930201210016120121001201210026120121001201210036120121001201210046120121001201210056120121001201210066120121001201210076120121001201210086020121001201301010120130101201301020120130101201301030120130101201301050020130101201301060020130101201302091120130210201302101120130210201302111120130210201302121120130210201302131120130210201302141120130210201302151120130210201302161020130210201302171020130210201304042120130404201304052120130404201304062120130404201304273020130501201304283020130501201304293120130501201304303120130501201305013120130501201306084020130612201306094020130612201306104120130612201306114120130612201306124120130612201309195120130919201309205120130919201309215120130919201309225020130919201309296020131001201310016120131001201310026120131001201310036120131001201310046120131001201310056120131001201310066120131001201310076120131001201401010120140101201401261020140131201401311120140131201402011120140131201402021120140131201402031120140131201402041120140131201402051120140131201402061120140131201402081020140131201404052120140405201404062120140405201404072120140405201405013120140501201405023120140501201405033120140501201405043020140501201405314120140602201406014120140602201406024120140602201409065120140908201409075120140908201409085120140908201409286020141001201410016120141001201410026120141001201410036120141001201410046120141004201410056120141001201410066120141001201410076120141001201410116020141001201501010120150101201501020120150101201501030120150101201501040020150101201502151020150219201502181120150219201502191120150219201502201120150219201502211120150219201502221120150219201502231120150219201502241120150219201502281020150219201504042120150405201504052120150405201504062120150405201505013120150501201505023120150501201505033120150501201506204120150620201506214120150620201506224120150620201509038120150903201509048120150903201509058120150903201509068020150903201509265120150927201509275120150927201510016120151001201510026120151001201510036120151001201510046120151004201510056120151001201510066120151001201510076120151001201510106020151001201601010120160101201601020120160101201601030120160101201602061020160208201602071120160208201602081120160208201602091120160208201602101120160208201602111120160208201602121120160208201602131120160208201602141020160208201604022120160404201604032120160404201604042120160404201604303120160501201605013120160501201605023120160501201606094120160609201606104120160609201606114120160609201606124020160609201609155120160915201609165120160915201609175120160915201609185020160915201610016120161001201610026120161001201610036120161001201610046120161004201610056120161001201610066120161001201610076120161001201610086020161001201610096020161001201612310120170101201701010120170101201701020120170101201701221020170128201701271120170128201701281120170128201701291120170128201701301120170128201701311120170128201702011120170128201702021120170128201702041020170128201704012020170404201704022120170404201704032120170404201704042120170404201704293120170501201704303120170501201705013120170501201705274020170530201705284120170530201705294120170530201705304120170530201709306020171001201710016120171001201710026120171001201710036120171001201710045120171004201710056120171001201710066120171001201710076120171001201710086120171001201712300120180101201712310120180101201801010120180101201802111020180216201802151120180216201802161120180216201802171120180216201802181120180216201802191120180216201802201120180216201802211120180216201802241020180216201804052120180405201804062120180405201804072120180405201804082020180405201804283020180501201804293120180501201804303120180501201805013120180501201806164120180618201806174120180618201806184120180618201809225120180924201809235120180924201809245120180924201809296020181001201809306020181001201810016120181001201810026120181001201810036120181001201810046120181001201810056120181001201810066120181001201810076120181001201812290020190101201812300120190101201812310120190101201901010120190101201902021020190205201902031020190205201902041120190205201902051120190205201902061120190205201902071120190205201902081120190205201902091120190205201902101120190205201904052120190405201904062120190405201904072120190405201904283020190501201905013120190501201905023120190501201905033120190501201905043120190501201905053020190501201906074120190607201906084120190607201906094120190607201909135120190913201909145120190913201909155120190913201909296020191001201910016120191001201910026120191001201910036120191001201910046120191001201910056120191001201910066120191001201910076120191001201910126020191001202001010120200101202001191020200125202001241120200125202001251120200125202001261120200125202001271120200125202001281120200125202001291120200125202001301120200125202001311120200125202002011120200125202002021120200125202004042120200404202004052120200404202004062120200404202004263020200501202005013120200501202005023120200501202005033120200501202005043120200501202005053120200501202005093020200501202006254120200625202006264120200625202006274120200625202006284020200625202009277020201001202010017120201001202010026120201001202010036120201001202010046120201001202010056120201001202010066120201001202010076120201001202010086120201001202010106020201001"; + /** 使用的节假日名称 */ + private static String[] NAMES_IN_USE = NAMES; + /** 使用的节假日数据 */ + private static String DATA_IN_USE = DATA; + private HolidayUtil(){} private static String padding(int n){ @@ -30,7 +35,7 @@ private static String padding(int n){ private static Holiday buildHolidayForward(String s){ String day = s.substring(0,8); - String name = NAMES[s.charAt(8)-ZERO]; + String name = NAMES_IN_USE[s.charAt(8)-ZERO]; boolean work = s.charAt(9)==ZERO; String target = s.substring(10,SIZE); return new Holiday(day,name,work,target); @@ -39,18 +44,18 @@ private static Holiday buildHolidayForward(String s){ private static Holiday buildHolidayBackward(String s){ int size = s.length(); String day = s.substring(size-18,size-10); - String name = NAMES[s.charAt(size-10)-ZERO]; + String name = NAMES_IN_USE[s.charAt(size-10)-ZERO]; boolean work = s.charAt(size-9)==ZERO; String target = s.substring(size-8); return new Holiday(day,name,work,target); } private static String findForward(String key){ - int start = DATA.indexOf(key); + int start = DATA_IN_USE.indexOf(key); if(start<0) { return null; } - String right = DATA.substring(start); + String right = DATA_IN_USE.substring(start); int n = right.length()%SIZE; if(n>0){ right = right.substring(n); @@ -62,11 +67,11 @@ private static String findForward(String key){ } private static String findBackward(String key){ - int start = DATA.lastIndexOf(key); + int start = DATA_IN_USE.lastIndexOf(key); if(start<0) { return null; } - String left = DATA.substring(0,start+key.length()); + String left = DATA_IN_USE.substring(0,start+key.length()); int size = left.length(); int n = size%SIZE; if(n>0){ @@ -173,7 +178,54 @@ public static List getHolidaysByTarget(String ymd){ * @param day 日 * @return 节假日列表 */ - public static List getHolidaysByTarget(int year,int month, int day){ + public static List getHolidaysByTarget(int year, int month, int day){ return findHolidaysBackward(year+padding(month)+padding(day)); } + + /** + * 修正或追加节假日数据。节假日名称下标从0开始,超过9的,按ASCII码表依次往后排列;调休标识0为上班,否则放假 + * @param names 用于替换默认的节假日名称列表,传null即可使用默认名称 + * @param data 需要修正或追加的节假日数据,每18位表示1天依次排列,格式:当天年月日YYYYMMDD(8位)+节假日名称下标(1位)+调休标识(1位)+节假日当天YYYYMMDD(8位)。例:202005023120200501代表2020-05-02为劳动节放假,对应节假日为2020-05-01 + */ + public static void fix(String[] names, String data){ + if(null!=names){ + NAMES_IN_USE = names; + } + if(null==data){ + return; + } + StringBuilder append = new StringBuilder(); + while(data.length()>=SIZE){ + String segment = data.substring(0,SIZE); + String day = segment.substring(0,8); + Holiday holiday = getHoliday(day); + if(null==holiday){ + append.append(segment); + }else{ + int nameIndex = -1; + for(int i=0,j=NAMES_IN_USE.length;i-1) { + String old = day+(char)(nameIndex+ZERO)+(holiday.isWork()?ZERO:'1')+holiday.getTarget().replace("-",""); + DATA_IN_USE = DATA_IN_USE.replace(old, segment); + } + } + data = data.substring(SIZE); + } + if(append.length()>0){ + DATA_IN_USE += append.toString(); + } + } + + /** + * 使用默认的节假日名称来修正或追加节假日数据。节假日名称下标从0开始,最大为8(元旦节0,春节1,清明节2,劳动节3,端午节4,中秋节5,国庆节6,国庆中秋7,抗战胜利日8);调休标识0为上班,否则放假 + * @param data 需要修正或追加的节假日数据,每18位表示1天依次排列,格式:当天年月日YYYYMMDD(8位)+节假日名称下标(1位)+调休标识(1位)+节假日当天YYYYMMDD(8位)。例:202005023120200501代表2020-05-02为劳动节放假,对应节假日为2020-05-01 + */ + public static void fix(String data){ + fix(null, data); + } } diff --git a/src/test/java/test/HolidayTest.java b/src/test/java/test/HolidayTest.java new file mode 100644 index 0000000..15aa8f9 --- /dev/null +++ b/src/test/java/test/HolidayTest.java @@ -0,0 +1,49 @@ +package test; + +import com.nlf.calendar.util.HolidayUtil; +import org.junit.Assert; +import org.junit.Test; + +public class HolidayTest { + + @Test + public void test(){ + Assert.assertEquals("2020-01-01 元旦节 2020-01-01",HolidayUtil.getHoliday("2020-01-01")+""); + + // 将2020-01-01修改为春节 + HolidayUtil.fix("202001011120200101"); + Assert.assertEquals("2020-01-01 春节 2020-01-01",HolidayUtil.getHoliday("2020-01-01")+""); + + // 追加2099-01-01为元旦节 + HolidayUtil.fix("209901010120990101"); + Assert.assertEquals("2099-01-01 元旦节 2099-01-01",HolidayUtil.getHoliday("2099-01-01")+""); + + // 将2020-01-01修改为春节,并追加2099-01-01为元旦节 + HolidayUtil.fix("202001011120200101209901010120990101"); + Assert.assertEquals("2020-01-01 春节 2020-01-01",HolidayUtil.getHoliday("2020-01-01")+""); + Assert.assertEquals("2099-01-01 元旦节 2099-01-01",HolidayUtil.getHoliday("2099-01-01")+""); + + // 更改节假日名称 + String[] names = HolidayUtil.NAMES; + names[0] = "元旦"; + names[1] = "大年初一"; + + HolidayUtil.fix(names, null); + Assert.assertEquals("2020-01-01 大年初一 2020-01-01",HolidayUtil.getHoliday("2020-01-01")+""); + Assert.assertEquals("2099-01-01 元旦 2099-01-01",HolidayUtil.getHoliday("2099-01-01")+""); + + // 追加节假日名称和数据 + names = new String[12]; + for(int i=0,j=HolidayUtil.NAMES.length;i