如何在Java中将当前日期添加到工作日?

如何在Java中将当前日期添加到工作日?

public Calendar addBusinessDate(Calendar cal, int days) { // // code goes over here // } 

注意:

它也应该考虑周末。

您可能需要考虑使用ObjectLab Kit为您做繁重的工作。

假设要求只是在计算日期属于非工作日时返回下一个工作日:

 package bizdays.example; import java.util.HashSet; import net.objectlab.kit.datecalc.common.DateCalculator; import net.objectlab.kit.datecalc.common.DefaultHolidayCalendar; import net.objectlab.kit.datecalc.common.HolidayHandlerType; import net.objectlab.kit.datecalc.joda.LocalDateKitCalculatorsFactory; import static org.junit.Assert.assertThat; import org.junit.Before; import org.junit.Test; import static org.hamcrest.Matchers.equalTo; import org.joda.time.LocalDate; public class BizDayTest { private DateCalculator dateCalculator; private final LocalDate startDate = new LocalDate(2009, 12, 23); @Before public void setUp() { HashSet holidays = new HashSet(); holidays.add(new LocalDate(2009, 12, 25)); // Friday DefaultHolidayCalendar holidayCalendar = new DefaultHolidayCalendar(holidays); LocalDateKitCalculatorsFactory.getDefaultInstance() .registerHolidays("example", holidayCalendar); dateCalculator = LocalDateKitCalculatorsFactory.getDefaultInstance() .getDateCalculator("example", HolidayHandlerType.FORWARD); dateCalculator.setStartDate(startDate); } @Test public void should_not_change_calendar_start_date_even_after_moving() { assertThat( dateCalculator.moveByBusinessDays(6).getStartDate(), equalTo(startDate)); } @Test public void moveByBusinessDays_will_return_24_dec_2009_as_next_business_day() { assertThat( dateCalculator.moveByBusinessDays(1).getCurrentBusinessDate(), equalTo(new LocalDate(2009, 12, 24))); } @Test public void moveByBusinessDays_will_return_28_dec_2009_as_two_business_days_later() { assertThat( dateCalculator.moveByBusinessDays(2).getCurrentBusinessDate(), equalTo(new LocalDate(2009, 12, 28))); } @Test public void moveByDays_will_also_return_28_dec_2009_as_two_business_days_later() { assertThat( dateCalculator.moveByDays(2).getCurrentBusinessDate(), equalTo(new LocalDate(2009, 12, 28))); } @Test public void moveByBusinessDays_will_exclude_25_26_and_27_dec_when_computing_business_days() { assertThat( dateCalculator.moveByBusinessDays(5).getCurrentBusinessDate(), equalTo(new LocalDate(2009, 12, 31))); } @Test public void moveByDays_will_include_25_26_and_27_dec_when_computing_business_days() { assertThat( dateCalculator.moveByDays(5).getCurrentBusinessDate(), equalTo(new LocalDate(2009, 12, 28))); } } 

库默认工作周是从星期一到星期五,但您可以通过向DateCalculator的setWorkingWeek()提供自定义WorkingWeek来更改默认值。

如前两个示例所示,moveByDays()包括移动日期的周末,而moveByBusinessDays()则不包括周末。

该库还允许您使用java.util.Calendar而不是Joda Time的LocalDate。 该示例使用Joda Time库,因为它是在Java中处理日期时使用的首选库。

使用:

 public Calendar addBusinessDate(Calendar cal, int numBusinessDays) { int numNonBusinessDays = 0; for(int i = 0; i < numBusinessDays; i++) { cal.add(Calendar.DATE, 1); /* It's a Canadian/American custom to get the Monday (sometimes Friday) off when a holiday falls on a weekend. */ for(int j = 0; j < holidays; j++) { //holidays is list of dates if(cal.getTime() == (Date)holidays.get(j)) { numNonBusinessDays++; } } if(cal.get(Calendar.DAY_OF_WEEK) == 1 || cal.get(Calendar.DAY_OF_WEEK) == 7) { numNonBusinessDays++; } } if(numNonBusinessDays > 0) { cal.add(Calendar.DATE, numNonBusinessDays); } return cal; } 

您必须填写日期列表才能处理假期。 有像New Years这样的常见词,但感恩节在加拿大和美国之间有所不同。 还要注意假期可以在周末rest,所以周末变成3天的周末。

参考:

  • 日历
  • 日历常量值

PS:如果您正在更新示例中的值,则实际上不需要返回Calendar实例。 但是如果要创建单独的Calendar实例,则有效:

 public Calendar addBusinessDate(Calendar cal, int numBusinessDays) { Calendar cal2 = Calendar.getInstance(); cal2.setTime(cal.getTime()); int numNonBusinessDays = 0; for(int i = 0; i < numBusinessDays; i++) { cal2.add(Calendar.DATE, 1); /* It's a Canadian/American custom to get the Monday (sometimes Friday) off when a holiday falls on a weekend. */ for(int j = 0; j < holidays; j++) { //holidays is list of dates if(cal2.getTime() == (Date)holidays.get(j)) { numNonBusinessDays++; } } if(cal2.get(Calendar.DAY_OF_WEEK) == 1 || cal2.get(Calendar.DAY_OF_WEEK) == 7) { numNonBusinessDays++; } } if(numNonBusinessDays > 0) { cal2.add(Calendar.DATE, numNonBusinessDays); } return cal2; } 

以下是查找日期计算的修改版本。

 public Calendar algorithm2(int businessDays){ Calendar cal2 = Calendar.getInstance(); Calendar cal = Calendar.getInstance(); int totalDays= businessDays/5*7; int remainder = businessDays % 5; cal2.add(cal2.DATE, totalDays); switch(cal.get(Calendar.DAY_OF_WEEK)){ case 1: break; case 2: break; case 3: if(remainder >3) cal2.add(cal2.DATE,2); break; case 4: if(remainder >2) cal2.add(cal2.DATE,2); break; case 5: if(remainder >1) cal2.add(cal2.DATE,2); break; case 6: if(remainder >1) cal2.add(cal2.DATE,2); break; case 7: if(remainder >1) cal2.add(cal2.DATE,1); break; } cal2.add(cal2.DATE, remainder); return cal2; } 
 public static Date addBusinessDays(Date date, int days) { DateTime result = new DateTime(date); result = isWeekEnd(result) ? getPreviousBusinessDate(result) : result; for (int i = 0; i < days; i++) { if (isWeekEnd(result)) { i--; } result = result.plusDays(1); } return result.toDate(); } private static boolean isWeekEnd(DateTime dateTime) { int dayOfWeek = dateTime.getDayOfWeek(); return dayOfWeek == DateTimeConstants.SATURDAY || dayOfWeek == DateTimeConstants.SUNDAY; } private static DateTime getPreviousBusinessDate(DateTime result) { while (isWeekEnd(result)) { result = result.minusDays(1); } return result; } 

//也支持负数。

 private Calendar addBusinessDay(final Calendar cal, final Integer numBusinessDays) { if (cal == null || numBusinessDays == null || numBusinessDays.intValue() == 0) { return cal; } final int numDays = Math.abs(numBusinessDays.intValue()); final int dateAddition = numBusinessDays.intValue() < 0 ? -1 : 1;//if numBusinessDays is negative int businessDayCount = 0; while (businessDayCount < numDays) { cal.add(Calendar.DATE, dateAddition); //check weekend if (cal.get(Calendar.DAY_OF_WEEK) == Calendar.SATURDAY || cal.get(Calendar.DAY_OF_WEEK) == Calendar.SUNDAY) { continue;//adds another day } //check holiday if (isHoliday(cal))//implement isHoliday yourself { continue;//adds another day } businessDayCount++; } return cal; } 

这会有用吗? 当然,这不是处理假期。

public static Date addBusinessDays(Date baseDate,int numberOfDays){

  if(baseDate == null){ baseDate = new Date(); } Calendar baseDateCal = Calendar.getInstance(); baseDateCal.setTime(baseDate); for(int i = 0; i < numberOfDays; i++){ baseDateCal.add(Calendar.DATE,1); if(baseDateCal.get(Calendar.DAY_OF_WEEK) == Calendar.SATURDAY){ baseDateCal.add(Calendar.DATE,2); } } return baseDateCal.getTime(); } 

TL;博士

向前走。

 myLocalDate.with( org.threeten.extra.Temporals.nextWorkingDay() ) 

向后走。

 myLocalDate.with( org.threeten.extra.Temporals.previousWorkingDay() ) 

使用java.time

问题和其他答案使用麻烦的旧日期时间类,现在是旧的,由java.time类取代。

另外,请参阅我对类似问题的回答 。

TemporalAdjuster

在java.time中, TemporalAdjuster接口提供了操作日期时间值的类。 使用不可变对象 ,将创建一个基于原始值的新实例。

nextWorkingDay

ThreeTen-Extra项目扩展了具有附加function的java.time。 这包括一个跳过周六和周日的nextWorkingDay调整器。 因此,我们可以循环,一次增加一天的日期,并跳过任何周末。

LocalDate类表示没有时间且没有时区的仅日期值。

 LocalDate start = LocalDate.now( ZoneId.of( "America/Montreal" ) ) ; int businessDaysToAdd = 13 ; // … ensure that: ( businessDaysToAdd >= 0 ) int daysLeft = businessDaysToAdd ; LocalDate localDate = start ; while ( daysLeft > 0 ) { localDate = localDate.with( Temporals.nextWorkingDay() ); daysLeft = ( daysLeft - 1 ) ; // Decrement as we go. } return localDate ; 

假期

假期是完全不同的事情。 显然没有简单的解决方案。 您必须提供您的荣誉假期列表,或获得您同意的列表。

一旦你有这样的列表,我建议编写你自己的TemporalAdjuster实现,类似于nextWorkingDay


关于java.time

java.time框架内置于Java 8及更高版本中。 这些类取代了麻烦的旧遗留日期时间类,如java.util.DateCalendarSimpleDateFormat

现在处于维护模式的Joda-Time项目建议迁移到java.time类。

要了解更多信息,请参阅Oracle教程 。 并搜索Stack Overflow以获取许多示例和解释。 规范是JSR 310 。

从哪里获取java.time类?

  • Java SE 8SE 9及更高版本
    • 内置。
    • 带有捆绑实现的标准Java API的一部分。
    • Java 9增加了一些小function和修复。
  • Java SE 6SE 7
    • 许多java.timefunction都被反向移植到ThreeTen-Backport中的 Java 6和7。
  • Android的
    • ThreeTenABP项目特别适用于Android的ThreeTen-Backport (如上所述)。
    • 请参见如何使用ThreeTenABP ….

ThreeTen-Extra项目使用其他类扩展了java.time。 该项目是未来可能添加到java.time的试验场。 您可以在这里找到一些有用的课程,如IntervalYearWeekYearQuarter等。

此算法计算给定日期的下一个营业日期(工作日从我国家的星期一到星期五) ,您可以调整它以迭代您需要添加的天数。

 public Calendar nextBusinessDate(Calendar cal) { List holidays = ******** // Here get list of holidays from DB or some other service... GregorianCalendar calCp = new GregorianCalendar(); calCp.setTime(cal.getTime()); calCp.add(Calendar.DAY_OF_MONTH, 1); boolean isSaturday = (calCp.get(Calendar.DAY_OF_WEEK) == Calendar.SATURDAY); boolean isSunday = (calCp.get(Calendar.DAY_OF_WEEK) == Calendar.SUNDAY); boolean isHoliday = holidays.contains(calCp); while (isSaturday || isSunday || isHoliday) { if (isSaturday) { calCp.add(Calendar.DAY_OF_MONTH, +2); // is saturday, make it monday } else { if (isSunday) { calCp.add(Calendar.DAY_OF_MONTH, +1); // is sunday, make it monday } else { if (isHoliday) { calCp.add(Calendar.DAY_OF_MONTH, +1); // is holiday, make it next day } } } calCp = new GregorianCalendar(); calCp.setTime(cal.getTime()); isSaturday = (calCp.get(Calendar.DAY_OF_WEEK) == Calendar.SATURDAY); isSunday = (calCp.get(Calendar.DAY_OF_WEEK) == Calendar.SUNDAY); isHoliday = holidays.contains(calCp); } // end while return calCp; } 

O(1)版本可以工作并支持不同的周末模式和负面日期:

 import java.util.Calendar; import java.util.Date; import java.util.HashMap; import java.util.Map; public class DateUtil { //Weekend patterns public static final int WEEKEND_SAT_SUN = 0; public static final int WEEKEND_FRI_SAT = 1; public static final int WEEKEND_THU_FRI = 2; public static final int WEEKEND_FRI_SUN = 3; public static final int WEEKEND_FRI = 4; public static final int WEEKEND_SAT = 5; public static final int WEEKEND_SUN = 6; //Weekend pattern by country //@see https://en.wikipedia.org/wiki/Workweek_and_weekend public static Map weekendPatternByCountry = new HashMap<>(); static { weekendPatternByCountry.put("CO",WEEKEND_SUN); //Colombia weekendPatternByCountry.put("GQ",WEEKEND_SUN); //Equatorial Guinea weekendPatternByCountry.put("IN",WEEKEND_SUN); //India weekendPatternByCountry.put("MX",WEEKEND_SUN); //Mexico weekendPatternByCountry.put("KP",WEEKEND_SUN); //North Korea weekendPatternByCountry.put("UG",WEEKEND_SUN); //Uganda weekendPatternByCountry.put("BN",WEEKEND_FRI_SUN); //Brunei Darussalam weekendPatternByCountry.put("DJ",WEEKEND_FRI); //Djibouti weekendPatternByCountry.put("IR",WEEKEND_FRI); //Iran weekendPatternByCountry.put("AF",WEEKEND_THU_FRI); //Afghanistan weekendPatternByCountry.put("NP",WEEKEND_SAT); //Nepal weekendPatternByCountry.put("DZ",WEEKEND_FRI_SAT); //Algeria weekendPatternByCountry.put("BH",WEEKEND_FRI_SAT); //Bahrain weekendPatternByCountry.put("BD",WEEKEND_FRI_SAT); //Bangladesh weekendPatternByCountry.put("EG",WEEKEND_FRI_SAT); //Egypt weekendPatternByCountry.put("IQ",WEEKEND_FRI_SAT); //Iraq weekendPatternByCountry.put("IL",WEEKEND_FRI_SAT); //Israel weekendPatternByCountry.put("JO",WEEKEND_FRI_SAT); //Jordan weekendPatternByCountry.put("KW",WEEKEND_FRI_SAT); //Kuwait weekendPatternByCountry.put("LY",WEEKEND_FRI_SAT); //Libya weekendPatternByCountry.put("MV",WEEKEND_FRI_SAT); //Maldives weekendPatternByCountry.put("MR",WEEKEND_FRI_SAT); //Mauritania weekendPatternByCountry.put("MY",WEEKEND_FRI_SAT); //Malaysia weekendPatternByCountry.put("OM",WEEKEND_FRI_SAT); //Oman weekendPatternByCountry.put("PS",WEEKEND_FRI_SAT); //Palestine weekendPatternByCountry.put("QA",WEEKEND_FRI_SAT); //Qatar weekendPatternByCountry.put("SA",WEEKEND_FRI_SAT); //Saudi Arabia weekendPatternByCountry.put("SD",WEEKEND_FRI_SAT); //Sudan weekendPatternByCountry.put("SY",WEEKEND_FRI_SAT); //Syria weekendPatternByCountry.put("AE",WEEKEND_FRI_SAT); //United Arab Emirates weekendPatternByCountry.put("YE",WEEKEND_FRI_SAT); //Yemen } //Adjustment vectors - precomputed adjustment static int[][][] adjVector = new int[][][]{ {//WEEKEND_SAT_SUN //Positive number of days {1,0,-1,-2,-3,1,1}, {0,0}, {0,0,0,0,0,2,1}, //Negative number of days {-1,3,2,1,0,-1,-1}, {0,0}, {-1,1,1,1,1,1,0} }, {//WEEKEND_FRI_SAT //Positive number of days {0,-1,-2,-3,1,1,1}, {0,0}, {0,0,0,0,2,1,0}, //Negative number of days {3,2,1,0,-1,-1,-1}, {0,0}, {1,1,1,1,1,0,-1} }, {//WEEKEND_THU_FRI //Positive number of days {-1,-2,-3,1,1,1,0}, {0,0}, {0,0,0,2,1,0,0}, //Negative number of days {2,1,0,-1,-1,-1,3}, {0,0}, {1,1,1,1,0,-1,1} }, {//WEEKEND_FRI_SUN //Positive number of days {0,-1,-2,-3,-4,-4,0}, {1,0}, {0,0,0,0,0,-1,1}, //Negative number of days {4,3,2,1,0,0,4}, {0,-1}, {1,1,1,1,1,0,2} }, {//WEEKEND_FRI //Positive number of days {-1,-2,-3,-4,1,1,0}, {0}, {0,0,0,0,1,0,0}, //Negative number of days {3,2,1,0,-1,-1,4}, {0}, {1,1,1,1,1,0,1} }, {//WEEKEND_SAT //Positive number of days {0,-1,-2,-3,-4,1,1}, {0}, {0,0,0,0,0,1,0}, //Negative number of days {4,3,2,1,0,-1,-1}, {0}, {1,1,1,1,1,1,0} }, {//WEEKEND_SUN //Positive number of days {1,0,-1,-2,-3,-4,1}, {0}, {0,0,0,0,0,0,1}, //Negative number of days {-1,4,3,2,1,0,-1}, {0}, {0,1,1,1,1,1,1} } }; //O(1) algorithm to add business days. public static Date addBusinessDays(Date day, int days,int weekendPattern){ Calendar ret = Calendar.getInstance(); if(day != null) { ret.setTime(day); } if(days != 0) { int startDayofWeek = ret.get(Calendar.DAY_OF_WEEK)-1; //Zero based to use the vectors bellow. int idx = days > 0 ? 0 : 3; int howManyWeekendDays = 0; int[][] adjV = adjVector[weekendPattern]; int numWeekendDaysInOneWeek = adjV[idx+1].length; for(int i = 0; i < numWeekendDaysInOneWeek;i++){ int adjustmentA = adjV[idx][startDayofWeek]; //pattern shift int adjustmentB = adjV[idx+1][i]; //day shift howManyWeekendDays += (days-adjustmentA-adjustmentB)/(7-numWeekendDaysInOneWeek); } int adjustmentC = adjV[idx+2][startDayofWeek]; //f(0) adjustment howManyWeekendDays += adjustmentC; ret.add(Calendar.DATE,days + howManyWeekendDays); //TODO: Extend to support holidays using recursion // int numHolidays = getNumHolidaysInInterval(day,ret.getTime()); // if(numHolidays > 0) return addBusinessDays(ret.getTime,numHolidays); } return ret.getTime(); } public static Date addBusinessDays(Date day, int days,String country){ Integer weekpat = weekendPatternByCountry.get(country); return weekpat != null ? addBusinessDays(day,days,weekpat) : addBusinessDays(day,days,WEEKEND_SAT_SUN); } } 

这是我提出的方法:

  private Date addLaborDays(Integer days, Date date){ Collection holidaysList = getHolidays(); Calendar cal = Calendar.getInstance(); cal.setTime(date); cal.add(Calendar.DATE, 1); Date dateTemp = cal.getTime(); if(days == 1) return dateTemp; if(holidaysList.contains(dateTemp) || DateUtil.isWeekend(dateTemp)){ return addLaborDays(days, dateTemp); } else { return addLaborDays(days-1, dateTemp); } } 

方法getHolidays()查询自定义假日数据库表,如果dateTemp是星期六或星期日,则方法DateUtil.isWeekend(dateTemp)返回true。

 /* To Calculate 10 business days ahead of today's date */ public class DueDate { /** * @param args */ public static void main(String[] args) { // TODO Auto-generated method stub DueDate d = new DueDate(); String dueDate = d.getDueDate(10); System.out.println("due Date " + dueDate); } public String getDueDate(int bday){ Calendar cal = new GregorianCalendar(); SimpleDateFormat fdate = new SimpleDateFormat("MM/dd/yyyy"); while(bday > 0){ cal.add(Calendar.DAY_OF_MONTH, 1); if(noWeekendsorHolidays(cal)){ bday--; } } return fdate.format(cal.getTime()); } public boolean noWeekendsorHolidays(Calendar cal){ int day = cal.get(Calendar.DAY_OF_WEEK); if(day == 1 || day == 7){ return false; } return true; } } 

这个适用于我,简短而简单:

 public static Date getBusinessDay(final Date date, final int businessDaysFromDate) { final int max = 60; if (date == null) { return getBusinessDay(new Date(), businessDaysFromDate); } else if (date != null && (businessDaysFromDate < 0 || businessDaysFromDate > max)) { return getBusinessDay(date, 0); } else { final Calendar baseDateCal = Calendar.getInstance(); baseDateCal.setTime(date); for (int i = 1; i <= businessDaysFromDate; i++) { baseDateCal.add(Calendar.DATE, 1); while (baseDateCal.get(Calendar.DAY_OF_WEEK) == Calendar.SATURDAY || baseDateCal.get(Calendar.DAY_OF_WEEK) == Calendar.SUNDAY) { baseDateCal.add(Calendar.DATE, 1); } } return baseDateCal.getTime(); } 

}

将当前日期的两个工作日添加到:

  Date today = new Date(); Calendar cal1 = Calendar.getInstance(); cal1.setTime(today); switch(cal1.get(Calendar.DAY_OF_WEEK)){ case 1: cal1.add(Calendar.DATE, 2); break; case 2: cal1.add(Calendar.DATE, 2); break; case 3: cal1.add(Calendar.DATE, 2); break; case 4: cal1.add(Calendar.DATE, 2); break; case 5: cal1.add(Calendar.DATE, 4); break; case 6: cal1.add(Calendar.DATE, 4); break; case 7: cal1.add(Calendar.DATE, 3); break; } // You may also set the time to meet your purpose: cal1.set(Calendar.HOUR_OF_DAY, 23); cal1.set(Calendar.MINUTE, 59); cal1.set(Calendar.SECOND, 59); cal1.set(Calendar.MILLISECOND, 00); Date twoWeekdaysAhead = cal1.getTime();