Pytanie w sprawie date, java, calendar – oblicz dni robocze, w tym święta

6

Muszę obliczyć dni robocze między dwiema datami. np .: mamy wakacje (w USA) 4 lipca. więc jeśli moje daty są date1 = 07/03/2012 date2 = 07/06/2012

nie dni roboczych b / w te daty powinny być 1 od 4 lipca to święto.

Mam poniższą metodę obliczania dni roboczych, które będą się liczyć tylko do końca tygodnia, ale nie do świąt. czy jest jakiś sposób na obliczenie wakacji również .... proszę mi pomóc w tym.

  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;  
}
Duplikat pytaniaData api do zarządzania poza dniami w roku? ale ten ma lepsze odpowiedzi. Basil Bourque
Przede wszystkim będziesz potrzebować listy wszystkich świąt w ciągu roku, ponieważ nie ma klasy java (tj.Locale konkretna klasa) zapewnia tę funkcjonalność. Następnie będziesz musiał sprawdzić, ile z tej listy znajduje się pomiędzy podanymi datami, co jest dość proste. Następnie możesz usunąć wiele dni z wyniku powyższego kodu. Surender Thakran
dzięki za odpowiedź. powiedzmy, że jeśli mam listę, która zawiera wszystkie święta, czy możesz zasugerować mi, jak korzystać z tej listy lub jak sprawdzić daty z listy w stanie. ran
Musisz śledzić wiedzę o tym, które dni są dniami świątecznymi, AFAIK nie ma do tego żadnej wbudowanej funkcji. Ponadto, kto obecnie używa ja-ja w Javie ?? TS-

Twoja odpowiedź

5   odpowiedzi
0

w jaki znalazłem, to korzystanie z matematyki (wypożyczanie zWIĘC słupek):

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

I:

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

Położyłem coś bardziej kompletnego razemtutaj.

Dziękuję za opinię. James Dunnam
3

Calendar klasa - oto moje dwa centy przy użyciu nowego API daty i czasu Java.

Musisz gdzieś dostać daty świąt, nie ma dla niej standardowej biblioteki Java. I tak byłoby to zbyt zlokalizowane, ponieważ wakacje w dużej mierze zależą od kraju i regionu. (z wyjątkiem powszechnie znanych świąt, takich jak Boże Narodzenie czy Wielkanoc).
Można je na przykład pobrać z wakacyjnego interfejsu API. W poniższym kodzie zapisałem je na stałeList zLocalDates.

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

MetodaLocalDate.datesUntil nie jest dostępny w Javie 8, więc musisz uzyskać strumień wszystkich dat między tymi dwoma datami w inny sposób. Najpierw musimy policzyć całkowitą liczbę dni pomiędzy użyciemChronoUnit.DAYS.between metoda.

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

Następnie musimy wygenerować sekwencję liczb całkowitych dokładnie tak długo, jak liczba dni między datą początkową i końcową, a następnie utworzyćLocalDates od niego, począwszy od daty rozpoczęcia.

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

Teraz mamyStream<LocalDate>, a następnie możesz użyć pozostałej części kodu Java 9.

6
Nager.Date

JSON API zNager.Date projekt. Obsługuje USA, Kanadę i Europę. Dane dostępne dla każdego roku można zapisać informacje we własnej bazie danych.

Przykład

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

Przykładowe pobrane dane JSON.

[
  {
    "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
  }
]
Powinieneś przestrzegać konwencji nazewnictwa Java: nazwy zmiennych zawsze zaczynają się od małych liter. MC Emperor
6

że masz listę zawierającą wszystkie święta, jak wspomniałeś.

ArrayList<Integer> holidays = ...

Po prostu dodaj warunek do swojegoif stan w twoimdo-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());

Dla uproszczenia założyłemholiday zawiera daty w formacie identycznym zCalendar.DAY_OF_YEAR.

dziękuję bardzo ... nie wiem, jak tęskniłem za tą prostą logiką. ale tutaj zamiast Calendar.DAY_OF_YEAR porównuję go z Calendar.getTime (), który zwraca pełną datę. teraz działa dobrze ran
Warto zauważyć, że oba przykłady tutaj obliczą 1 dzień za różnicę 1 milisekundy lub więcej. Zamiast tego użyj porównania day_of_year i year w pętli. Eddie
Pozdrawiam, cieszę się, że mogę służyć. SimplyPanda
2

ale szukałem cię i natknąłem się na wątek Stack Overflow, który zawiera linki do serwisów internetowych, które mogą zwracać daty wakacji dla ciebie, co może pomóc ci dotrzeć do miejsca muszą być:Serwis internetowy święta narodowego

Najlepsza odpowiedź w tym wątku prowadzi do tej usługi internetowej:http://www.holidaywebservice.com/

Nie jestem pewien, czy korzystanie z usługi internetowej dla tego typu rzeczy jest przesadne, czy nie, ale na pewno jest lepszy sposób. Przepraszam, nie jestem najbardziej doświadczonym programistą, więc nie mogę ci pomóc tak bardzo, jak bym chciał.

To naprawdę nie przesada. Musisz uzyskać informacje odgdzieś inaczej, ponieważ zawsze może ulec zmianie. djechlin

Powiązane pytania