Pregunta sobre calendar, java, date – calcular días hábiles incluyendo días festivos

6

Necesito calcular los días hábiles entre dos fechas. Ej: tenemos vacaciones (en USA) el 4 de julio. así que si mis fechas son date1 = 07/03/2012 date2 = 07/06/2012

no de días hábiles entre semana, estas fechas deben ser 1, ya que el 4 de julio es feriado.

Tengo un método a continuación para calcular los días hábiles, que solo cuentan los fines de semana, pero no los días festivos. ¿Hay alguna forma de calcular las vacaciones también ... por favor ayudenme en esto?

  public static int getWorkingDaysBetweenTwoDates(Date startDate, Date endDate) {  
    Calendar startCal;  
    Calendar endCal;  
    startCal = Calendar.getInstance();  
    startCal.setTime(startDate);  
    endCal = Calendar.getInstance();  
    endCal.setTime(endDate);  
    int workDays = 0;  

    //Return 0 if start and end are the same  
    if (startCal.getTimeInMillis() == endCal.getTimeInMillis()) {  
        return 0;  
    }  

    if (startCal.getTimeInMillis() > endCal.getTimeInMillis()) {  
        startCal.setTime(endDate);  
        endCal.setTime(startDate);  
    }  

    do {  
        startCal.add(Calendar.DAY_OF_MONTH, 1);  
        if (startCal.get(Calendar.DAY_OF_WEEK) != Calendar.SATURDAY   
       && startCal.get(Calendar.DAY_OF_WEEK) != Calendar.SUNDAY) {  
            ++workDays;  
        }  
    } while (startCal.getTimeInMillis() < endCal.getTimeInMillis());  

    return workDays;  
}
gracias por su respuesta Digamos que si tengo una lista que contiene todos los días festivos, ¿me pueden sugerir cómo usar esa lista o cómo verificar las fechas de esa lista en la condición? ran
En primer lugar, necesitará una lista de todos los días festivos en un año porque no hay clases de Java (es decir,Locale clase específica) proporciona esta funcionalidad. Luego, tendrá que encontrar cuántos de esta lista se encuentran entre las fechas especificadas, lo cual es bastante sencillo. Luego, puede eliminar tantos días del resultado de su código anterior. Surender Thakran
Duplicado de la preguntaFecha api para la gestión de días en un año? Pero este tiene mejores respuestas. Basil Bourque
Debe realizar un seguimiento del conocimiento de qué días son festivos manualmente, AFAIK no hay una función integrada para eso. Además, ¿quién usa do-while en java estos días? TS-

Tu respuesta

5   la respuesta
6

como mencionó.

ArrayList<Integer> holidays = ...

Solo agrega una condición a tuif condición en tudo-while:

do {
          startCal.add(Calendar.DAY_OF_MONTH, 1);
          if (startCal.get(Calendar.DAY_OF_WEEK) != Calendar.SATURDAY
          && startCal.get(Calendar.DAY_OF_WEEK) != Calendar.SUNDAY
          && !holidays.contains((Integer) startCal.get(Calendar.DAY_OF_YEAR))) {
              ++workDays;
          }
} while (startCal.getTimeInMillis() < endCal.getTimeInMillis());

Para simplificar, asumíholiday contiene fechas en el formato idéntico aCalendar.DAY_OF_YEAR.

Saludos, contentos de estar de servicio. SimplyPanda
Vale la pena señalar que los dos ejemplos aquí calcularán 1 día por la diferencia de 1 milisecons o más. Use una comparación de día y año y año en el bucle. Eddie
muchas gracias ... no sé cómo me perdí esta simple lógica. pero aquí, en lugar de Calendar.DAY_OF_YEAR, lo estoy comparando con el Calendar.getTime () que devuelve la fecha completa. está funcionando bien ahora ran
2

pero hice algunas búsquedas y encontré este hilo de desbordamiento de pila que tiene algunos enlaces a servicios web que pueden devolverte las fechas de vacaciones, lo que puede ayudarte a llegar a donde necesitan ser:Servicio web nacional de vacaciones.

La respuesta principal en ese hilo enlaza a este servicio web:http://www.holidaywebservice.com/

No estoy seguro si el uso de un servicio web para este tipo de cosas es excesivo o no, pero seguramente hay una mejor manera. Pido disculpas, no soy el programador más experimentado, así que no puedo ayudarlo tanto como quisiera.

No es realmente una exageración. Necesitas obtener la información dealgun lado más, ya que siempre está sujeto a cambios. djechlin
3

Calendar clase - aquí están mis dos centavos usando la nueva API de fecha y hora de Java.

Tienes que obtener las fechas de los días festivos de algún lugar, no hay una biblioteca estándar de Java para ello. De todos modos, eso sería demasiado localizado, ya que las vacaciones dependen en gran medida de su país y región. (excepto los días festivos más conocidos, como Navidad o Semana Santa).
Podría obtenerlos de una API de vacaciones, por ejemplo. En el código de abajo los he codificado como unList deLocalDates.

Java 9
LocalDate startDate = LocalDate.of(2012, 3, 7);
LocalDate endDate = LocalDate.of(2012, 6, 7);

// I've hardcoded the holidays as LocalDates and put them in a List
final List<LocalDate> holidays = Arrays.asList(
    LocalDate.of(2018, 7, 4)
);

List<LocalDate> allDates =

    // Java 9 provides a method to return a stream with dates from the
    // startdate to the given end date. Note that the end date itself is
    // NOT included.
    startDate.datesUntil(endDate)

        // Retain all business days. Use static imports from
        // java.time.DayOfWeek.*
        .filter(t -> Stream.of(MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY)
            .anyMatch(t.getDayOfWeek()::equals))

        // Retain only dates not present in our holidays list
        .filter(t -> !holidays.contains(t))

         // Collect them into a List. If you only need to know the number of
         // dates, you can also use .count()
        .collect(Collectors.toList());
Java 8

El métodoLocalDate.datesUntil no está disponible en Java 8, por lo que debe obtener una transmisión de todas las fechas entre esas dos fechas de una manera diferente. Primero debemos contar el número total de días entre el uso de laChronoUnit.DAYS.between método.

long numOfDaysBetween = ChronoUnit.DAYS.between(startDate, endDate);

Luego, debemos generar una secuencia de enteros exactamente mientras el número de días entre la fecha de inicio y finalización, y luego crearLocalDates de ella, a partir de la fecha de inicio.

IntStream.iterate(0, i -> i + 1)
    .limit(numOfDaysBetween)
    .mapToObj(startDate::plusDays)

Ahora tenemos unStream<LocalDate>, y luego puedes usar la parte restante del código de Java 9.

6
Nager.Fecha

API JSON deNager.Fecha proyecto. Es compatible con Estados Unidos, Canadá y Europa. Los datos disponibles para cada año pueden guardar la información en su propia base de datos.

Ejemplo

//https://github.com/FasterXML/jackson-databind/
ObjectMapper mapper = new ObjectMapper();
MyValue value = mapper.readValue(new URL("http://date.nager.at/api/v1/get/US/2017"), PublicHoliday[].class);

PublicHoliday.class

public class PublicHoliday
{
    public String date;
    public String localName;
    public String name;
    public String countryCode;
    public Boolean fixed;
    public Boolean countyOfficialHoliday;
    public Boolean countyAdministrationHoliday;
    public Boolean global;
    public String[] counties;
    public int launchYear;
}

Ejemplo de datos JSON recuperados.

[
  {
    "date": "2017-01-01",
    "localName": "New Year's Day",
    "name": "New Year's Day",
    "countryCode": "US",
    "fixed": true,
    "countyOfficialHoliday": true,
    "countyAdministrationHoliday": true,
    "global": true,
    "counties": null,
    "launchYear": null
  },
  {
    "date": "2017-01-16",
    "localName": "Martin Luther King, Jr. Day",
    "name": "Martin Luther King, Jr. Day",
    "countryCode": "US",
    "fixed": true,
    "countyOfficialHoliday": true,
    "countyAdministrationHoliday": true,
    "global": true,
    "counties": null,
    "launchYear": null
  },
  {
    "date": "2017-01-20",
    "localName": "Inauguration Day",
    "name": "Inauguration Day",
    "countryCode": "US",
    "fixed": true,
    "countyOfficialHoliday": true,
    "countyAdministrationHoliday": true,
    "global": false,
    "counties": [
      "US-DC",
      "US-LA",
      "US-MD",
      "US-VA"
    ],
    "launchYear": null
  },
  {
    "date": "2017-02-20",
    "localName": "Washington's Birthday",
    "name": "Presidents' Day",
    "countryCode": "US",
    "fixed": true,
    "countyOfficialHoliday": true,
    "countyAdministrationHoliday": true,
    "global": true,
    "counties": null,
    "launchYear": null
  },
  {
    "date": "2017-05-29",
    "localName": "Memorial Day",
    "name": "Memorial Day",
    "countryCode": "US",
    "fixed": true,
    "countyOfficialHoliday": true,
    "countyAdministrationHoliday": true,
    "global": true,
    "counties": null,
    "launchYear": null
  },
  {
    "date": "2017-07-04",
    "localName": "Independence Day",
    "name": "Independence Day",
    "countryCode": "US",
    "fixed": true,
    "countyOfficialHoliday": true,
    "countyAdministrationHoliday": true,
    "global": true,
    "counties": null,
    "launchYear": null
  },
  {
    "date": "2017-09-04",
    "localName": "Labor Day",
    "name": "Labor Day",
    "countryCode": "US",
    "fixed": true,
    "countyOfficialHoliday": true,
    "countyAdministrationHoliday": true,
    "global": true,
    "counties": null,
    "launchYear": null
  },
  {
    "date": "2017-09-09",
    "localName": "Columbus Day",
    "name": "Columbus Day",
    "countryCode": "US",
    "fixed": true,
    "countyOfficialHoliday": true,
    "countyAdministrationHoliday": true,
    "global": false,
    "counties": [
      "US-AL",
      "US-AZ",
      "US-CO",
      "US-CT",
      "US-DC",
      "US-GA",
      "US-ID",
      "US-IL",
      "US-IN",
      "US-IA",
      "US-KS",
      "US-KY",
      "US-LA",
      "US-ME",
      "US-MD",
      "US-MA",
      "US-MS",
      "US-MO",
      "US-MT",
      "US-NE",
      "US-NH",
      "US-NJ",
      "US-NM",
      "US-NY",
      "US-NC",
      "US-OH",
      "US-OK",
      "US-PA",
      "US-RI",
      "US-SC",
      "US-TN",
      "US-UT",
      "US-VA",
      "US-WV"
    ],
    "launchYear": null
  },
  {
    "date": "2017-11-10",
    "localName": "Veterans Day",
    "name": "Veterans Day",
    "countryCode": "US",
    "fixed": false,
    "countyOfficialHoliday": true,
    "countyAdministrationHoliday": true,
    "global": true,
    "counties": null,
    "launchYear": null
  },
  {
    "date": "2017-12-23",
    "localName": "Thanksgiving Day",
    "name": "Thanksgiving Day",
    "countryCode": "US",
    "fixed": true,
    "countyOfficialHoliday": true,
    "countyAdministrationHoliday": true,
    "global": true,
    "counties": null,
    "launchYear": 1863
  },
  {
    "date": "2017-12-25",
    "localName": "Christmas Day",
    "name": "Christmas Day",
    "countryCode": "US",
    "fixed": true,
    "countyOfficialHoliday": true,
    "countyAdministrationHoliday": true,
    "global": true,
    "counties": null,
    "launchYear": null
  }
]
Debe seguir las Convenciones de nomenclatura de Java: los nombres de las variables siempre comienzan con minúsculas. MC Emperor
0

réstamos de laASI QUE enviar):

public static int totalBusinessDaysBetween(LocalDate start, LocalDate end) {
    Objects.requireNonNull(start, "Start date must not be null");
    Objects.requireNonNull(end, "End date must not be null");
    long daysBetweenWithoutWeekends = calculateNumberOfDaysBetweenMinusWeekends(start, end);
    final Set<LocalDate> holidayForYearRange = getUSFederalHolidayForYearRange(start.getYear(), end.getYear());
    for (LocalDate localDate : holidayForYearRange) {
        if (localDate.isAfter(start) && localDate.isBefore(end)) {
            daysBetweenWithoutWeekends--;
        }
    }
    return (int) daysBetweenWithoutWeekends;
}

Y:

private static long calculateNumberOfDaysBetweenMinusWeekends(LocalDate start, LocalDate end) {

    final DayOfWeek startW = start.getDayOfWeek();
    final DayOfWeek endW = end.getDayOfWeek();

    final long days = ChronoUnit.DAYS.between(start, end);
    final long daysWithoutWeekends = days - 2 * ((days + startW.getValue()) / 7);

    //adjust for starting and ending on a Sunday:
    return daysWithoutWeekends + (startW == DayOfWeek.SUNDAY ? 1 : 0) + (endW == DayOfWeek.SUNDAY ? 1 : 0);
}

Pongo algo más completo juntos.aquí.

Gracias por la respuesta. James Dunnam

Preguntas relacionadas