How can I add business days to the current date in Java?

后端 未结 14 1357
Happy的楠姐
Happy的楠姐 2020-12-03 02:05

How can I add business days to the current date in Java?

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


        
14条回答
  •  -上瘾入骨i
    2020-12-03 02:40

    O(1) version that works and supports different weekend patterns and negative days:

    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);
    }
    }
    

提交回复
热议问题