Biblioteca de data java para calculo de dias

Boa tarde meus bons.
Pessoal surgiu uma demanda para eu fazer e não encontrei maneira eficiente para realizar a tarefa.
Eu preciso calcular os dias entre duas datas e excluir os finais de semana e os feriados, nesse caso somente os nacionais.
vou postar um código que fiz usando node.js e dessa maneira funciona.
para realizar o calculo das datas uso uma lib chamada moment-bussines-days

const moment = require('moment-business-days');

var now = new Date();

let holiDays = [
    "01-01-" + now.getFullYear(), // Confraternização Universal    
    "21-04-" + now.getFullYear(), // Tiradentes
    "22-04-" + now.getFullYear(), // Descobrimento do Brasil
    "01-05-" + now.getFullYear(), // Dia do Trabalho    
    "07-09-" + now.getFullYear(), // Independência do Brasil
    "12-10-" + now.getFullYear(), // Nsa. Sra. Aparecida
    "02-11-" + now.getFullYear(), // Finados,
    "15-11-" + now.getFullYear(), // Proclamação da Republica    
    "25-12-" + now.getFullYear(), // Natal
];

let workinghours = {
    0: null,
    1: ['09:00:00','18:00:00'],
    2: ['09:00:00','18:00:00'],
    3: ['09:00:00','18:00:00'],
    4: ['09:00:00','18:00:00'],
    5: ['09:00:00','18:00:00'],
    6: null
};

moment.updateLocale('pt-br', {
   holidays: holiDays,
   holidayFormat: 'DD/MM/YYYY',
   workingWeekdays: [1, 2, 3, 4, 5],
   workinghours: workinghours
});

var diff = moment('01/10/2019', 'DD/MM/YYYY').businessDiff(moment('04/11/2019','DD/MM/YYYY'));

console.log(diff + ' dia(s)');

Com essa lib eu consigo excluir os feriados nacionais e fica bem adequado para meu problema.

Vou posta o código feito em java:

package br.com.datas;

import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;

public class Weekends {	
	
	public static void main(String[] args) {
		
		Date dt1 = new Date();
		dt1.setDate(1);
		
		Date dt2 = new Date();
		dt2.setDate(4);
		dt2.setMonth(10);		
		
		long dias = days(dt1,dt2);
		
		System.out.println(new SimpleDateFormat("dd/MM/yyyy").format(dt1.getTime()));
		System.out.println(new SimpleDateFormat("dd/MM/yyyy").format(dt2.getTime()));
		System.out.println(dias);
		
	}
	
	private static long days(Date start, Date end){	    

	    Calendar c1 = Calendar.getInstance();
	    c1.setTime(start);
	    int w1 = c1.get(Calendar.DAY_OF_WEEK);
	    c1.add(Calendar.DAY_OF_WEEK, -w1);

	    Calendar c2 = Calendar.getInstance();
	    c2.setTime(end);
	    int w2 = c2.get(Calendar.DAY_OF_WEEK);
	    c2.add(Calendar.DAY_OF_WEEK, -w2);
	     
	    long days = (c2.getTimeInMillis()-c1.getTimeInMillis())/(1000*60*60*24);
	    long daysWithoutSunday = days-(days*2/7);

	    return daysWithoutSunday-w1+w2;
	}

}

com java com essa algorítimo também funciona, oque ele faz e calcular o intervalo entre as duas datas e excluir os dias de fim de semana, que no caso são dois dias.
Porém não vejo maneiro de adicionar o calculo dos feriados nacionais pois se um desses feriados ou futuros feriados municipais que irei adicionar no método, cair no fim de semana eu iria calcular errado pois estou tirando dois dias do resultado final, eu estava pensando de tirar dias de acordo com a quantidade de feriados, mas se o feriado cair aos fins de semana vou tirar um dia a mais sem necessidade.

Alguém sabe uma lib para java paracida com essa moment-bussines-days para java ou qualquer outra solução ?
Agradeço.

A API de datas do java, introduzida na versão 8, que é, basicamente, o jodatime, te dá todo suporte pra isso.

Infelizmente @darlan_machado não posso usar o java 8, mas resolvi de outra maneira.

Caso alguém tenha interesse, eu resolvi assim:

package br.com.datas;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

public class Weekends {	
	
	public static void main(String[] args) throws ParseException {		
		System.out.println(days2("01/04/2019", "30/04/2019",buildHolyDays()));		
	}	
	
	public static Integer days2(String startDate, String endDate) throws ParseException {		
		int workingDays = 0;
	    SimpleDateFormat sdf = new SimpleDateFormat("dd/MM/yyyy");
	    Calendar startdate = Calendar.getInstance();
	    startdate.setTime(sdf.parse(startDate));
	    Calendar enddate = Calendar.getInstance();
	    enddate.setTime(sdf.parse(endDate));
	    while (!startdate.after(enddate)) {
	        int day = startdate.get(Calendar.DAY_OF_WEEK);	       
	        if ((day != Calendar.SATURDAY) && (day != Calendar.SUNDAY)) 
	            workingDays++;        
	        startdate.add(Calendar.DATE, 1);
	    }
	    return workingDays;
	}
	
	public static Integer days2(String startDate, String endDate,Set<Date> holyDays) throws ParseException {		
		int workingDays = 0;
	    SimpleDateFormat sdf = new SimpleDateFormat("dd/MM/yyyy");	     
	    Calendar startdate = Calendar.getInstance();
	    startdate.setTime(sdf.parse(startDate));
	    Calendar enddate = Calendar.getInstance();
	    enddate.setTime(sdf.parse(endDate));
	    List<Date> rangeDates = getDatesBetween(startdate.getTime(),enddate.getTime());	    
	    for(Date d : rangeDates) {
	    	if(!isHolyDay(d, holyDays)) {	    		
		        int day = startdate.get(Calendar.DAY_OF_WEEK);	              
		        if ((day != Calendar.SATURDAY) && (day != Calendar.SUNDAY)) 
		            workingDays++;        
		        startdate.add(Calendar.DATE, 1);	    	        		
	    	}else
	    		startdate.add(Calendar.DATE, 1);
	    }      
	    return workingDays;
	}
	
	private static Date dateWithoutHours(Date dt) {
		dt.setHours(0);
		dt.setMinutes(0);
		dt.setSeconds(0);
		return dt;	
	}	
	
	public static List<Date> getDatesBetween(Date startDate, Date endDate) {
	    List<Date> datesInRange = new ArrayList<>();
	    Calendar calendar = new GregorianCalendar();
	    calendar.setTime(startDate);	     
	    Calendar endCalendar = new GregorianCalendar();
	    endCalendar.setTime(endDate);	 
	    while (calendar.before(endCalendar) || calendar.equals(endCalendar)) {
	        Date result = calendar.getTime();
	        datesInRange.add(result);
	        calendar.add(Calendar.DATE, 1);	       
	    }
	    return datesInRange;
	}
	
	private static boolean isHolyDay(Date day, Set<Date> holyDays) {		
		for(Date currentHolyDay : holyDays) {
			currentHolyDay = dateWithoutHours(currentHolyDay);
			if(currentHolyDay.toString().equals(day.toString()))
				return true;				
		}				
		return false;		
	}
	
	private static Set<Date> buildHolyDays(){
		
		//january = 0
		
		Set<Date> holyDays = new HashSet<Date>();
		
		Calendar confraternizacaoUniversal = Calendar.getInstance();
		confraternizacaoUniversal.set(Calendar.DAY_OF_MONTH, 1);
		confraternizacaoUniversal.set(Calendar.MONTH, 0);
		confraternizacaoUniversal.set(Calendar.HOUR, 0);
		confraternizacaoUniversal.set(Calendar.MINUTE, 0);
		confraternizacaoUniversal.set(Calendar.SECOND, 0);
		
		Calendar paixaoDeCristo = Calendar.getInstance();
		paixaoDeCristo.set(Calendar.DAY_OF_MONTH, 19);
		paixaoDeCristo.set(Calendar.MONTH, 3);
		paixaoDeCristo.set(Calendar.HOUR, 0);
		paixaoDeCristo.set(Calendar.MINUTE, 0);
		paixaoDeCristo.set(Calendar.SECOND, 0);
		
		Calendar tiradentes = Calendar.getInstance();
		tiradentes.set(Calendar.DAY_OF_MONTH, 21);
		tiradentes.set(Calendar.MONTH, 3);
		tiradentes.set(Calendar.HOUR, 0);
		tiradentes.set(Calendar.MINUTE, 0);
		tiradentes.set(Calendar.SECOND, 0);		
		
		Calendar diaDoTrabalho = Calendar.getInstance();
		diaDoTrabalho.set(Calendar.DAY_OF_MONTH, 1);
		diaDoTrabalho.set(Calendar.MONTH, 4);
		diaDoTrabalho.set(Calendar.HOUR, 0);
		diaDoTrabalho.set(Calendar.MINUTE, 0);
		diaDoTrabalho.set(Calendar.SECOND, 0);
		
		Calendar independencia = Calendar.getInstance();
		independencia.set(Calendar.DAY_OF_MONTH, 7);
		independencia.set(Calendar.MONTH, 8);
		independencia.set(Calendar.HOUR, 0);
		independencia.set(Calendar.MINUTE, 0);
		independencia.set(Calendar.SECOND, 0);
		
		Calendar senhoraAparecida = Calendar.getInstance();
		senhoraAparecida.set(Calendar.DAY_OF_MONTH, 12);
		senhoraAparecida.set(Calendar.MONTH, 9);
		senhoraAparecida.set(Calendar.HOUR, 0);
		senhoraAparecida.set(Calendar.MINUTE, 0);
		senhoraAparecida.set(Calendar.SECOND, 0);
		
		Calendar finados = Calendar.getInstance();
		finados.set(Calendar.DAY_OF_MONTH, 2);
		finados.set(Calendar.MONTH, 10);
		finados.set(Calendar.HOUR, 0);
		finados.set(Calendar.MINUTE, 0);
		finados.set(Calendar.SECOND, 0);
		
		Calendar proclamacaoDaRepublica = Calendar.getInstance();
		proclamacaoDaRepublica.set(Calendar.DAY_OF_MONTH, 15);
		proclamacaoDaRepublica.set(Calendar.MONTH, 10);	
		proclamacaoDaRepublica.set(Calendar.HOUR, 0);
		proclamacaoDaRepublica.set(Calendar.MINUTE, 0);
		proclamacaoDaRepublica.set(Calendar.SECOND, 0);
		
		Calendar natal = Calendar.getInstance();
		natal.set(Calendar.DAY_OF_MONTH, 25);
		natal.set(Calendar.MONTH, 11);	
		natal.set(Calendar.HOUR, 0);
		natal.set(Calendar.MINUTE, 0);
		natal.set(Calendar.SECOND, 0);
		
		holyDays.add(confraternizacaoUniversal.getTime());
		holyDays.add(paixaoDeCristo.getTime());
		holyDays.add(tiradentes.getTime());		
		holyDays.add(diaDoTrabalho.getTime());
		holyDays.add(independencia.getTime());
		holyDays.add(senhoraAparecida.getTime());
		holyDays.add(finados.getTime());
		holyDays.add(proclamacaoDaRepublica.getTime());
		holyDays.add(natal.getTime());
		
		return holyDays;
	}

}
1 curtida