Java Holen Sie sich alle Arbeitstage in einem Jahr im Format JJJJMMTT

8

Meine sonntägliche Herausforderung besteht darin, Arbeitstage in einem bestimmten Jahr in eine CSV-Datei usw. zu integrieren.

Ich habe folgenden Code und das Problem, mit dem ich konfrontiert bin, ist: wie man Daten in einem bestimmten Format druckt, dh JJJJMMTT, da der Code derzeit so etwas wie Sa 19 Jan 00:00:00 CET 2019 druckt.

Auch wenn ich Wochenenden ausschließen kann und generell, wenn es eine bessere Möglichkeit gibt, einen viel kürzeren Code in Java 8 zu schreiben.

import java.io.*;
import java.util.*;
import java.text.SimpleDateFormat;

public class DatesInYear
{

    public static SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMdd");

    public static void main (String[] args) throws java.lang.Exception
    {

        Date dt = new Date();
        System.out.println(dt);

        List<Date> dates = printDates("20190101","20191231");


        Collections.reverse(dates);
        System.out.println(dates.size());
        for(Date date:dates)
        {
            SimpleDateFormat format1 = new SimpleDateFormat("yyyyMMdd");
            System.out.println(format1.format(date));

        }
    }
    public static List<Date> printDates(String fromDate, String toDate)
    {
        ArrayList<Date> dates = new ArrayList<Date>();

        try {

            Calendar fromCal = Calendar.getInstance();
            fromCal.setTime(dateFormat .parse(fromDate));

            Calendar toCal = Calendar.getInstance();
            toCal.setTime(dateFormat .parse(toDate));

            while(!fromCal.after(toCal))
            {
                dates.add(fromCal.getTime());
                fromCal.add(Calendar.DATE, 1);
            }


        } catch (Exception e) {
            System.out.println(e);
        }
        return dates;
    }
}
JavaMan
quelle
1
System.out.println(date)Verwenden Sie nicht nur das dateFormat, was Sie bereits erstellt haben, um es so zu formatieren, wie Sie es benötigen.
Thilo
2
String date1 = format1.format(date);dann machst du nichts mit date1. Aber Sie sind auf dem richtigen Weg.
Federico klez Culloca
1
Calendarkann auch verwendet werden, um den Wochentag zu überprüfen.
Thilo
1
Was ist Ihre Java-Version? 8 oder 9+?
ernest_k
1
Ich benutze Java 8
JavaMan

Antworten:

3

Hier sind 2 etwas andere Ansichten zu Ihrem Problem:

import java.time.LocalDate;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.IntStream;

public class DatesInYear {

    public static void main(final String[] args) throws Exception {

        listWorkingDays(2020).forEach(System.out::println);
    }

    private static List<LocalDate> listWorkingDays(final int year) {

        IntStream
            .rangeClosed(1,      LocalDate.ofYearDay(year + 1, 1).minusDays(1).getDayOfYear())
            .mapToObj   (day  -> LocalDate.ofYearDay(year, day))
            .filter     (date -> date.getDayOfWeek().getValue() <= 5)
            .forEach    (System.out::println);

        return IntStream
            .rangeClosed(1,      LocalDate.ofYearDay(year + 1, 1).minusDays(1).getDayOfYear())
            .mapToObj   (day  -> LocalDate.ofYearDay(year, day))
            .filter     (date -> date.getDayOfWeek().getValue() <= 5)
            .collect    (Collectors.toList());
    }
}
Dave der Däne
quelle
Danke Dave, das sieht wirklich elegant aus. Ich stelle gerade ein paar Unit-Tests zusammen, sehe aber wirklich interessant aus. Prost
JavaMan
Was ist der Zweck des ersten IntStream? Die Daten werden zweimal angezeigt. Oder warum lassen Sie nicht nur den ersten IntStreamund ändern den Rückgabetyp in ungültig? Ich bin nur Neugierig.
Sebastian I.
Wie ich bereits erwähnte, sind es nur zwei, die das Problem lösen: einer druckt, einer kehrt zurück. JavaMan kann auswählen, was er will. :-)
Dave The Dane
Ich mag es nicht, dass diese neuen Redewendungen im Allgemeinen ineffizient sind. LocalDate.ofYearDay erstellt jedes Mal eine neue Instanz , wenn github.com/frohoff/jdk8u-jdk/blob/… diesen Code in eine häufig verwendete Methode einfügt am effizientesten.
Leo
7

Seit 2020 sollten Sie die java.time.*API wirklich nutzen .

Ich bin mir zwar sicher, dass es wahrscheinlich eine wirklich gute Möglichkeit gibt, die "Arbeitstage" zwischen den Daten zu verschieben, aber ich habe mich für die Brute-Force-Methode entschieden ...

LocalDate ld = LocalDate.of(2020, Month.JANUARY, 1);
LocalDate endDate = ld.plusYears(1);

// You don't "have" to put into a list, but I like to seperate my
// code responsbilities ;)
List<LocalDate> workDays = new ArrayList<>(365);
System.out.println(endDate);
while (ld.isBefore(endDate)) {
    // This would be a good place for a delegate to determine if we want the specific day
    // as it could then take into account public holidays
    if (ld.getDayOfWeek() == DayOfWeek.SATURDAY || ld.getDayOfWeek() == DayOfWeek.SUNDAY) {
        // NOOP
    } else {
        workDays.add(ld);
    }
    ld = ld.plusDays(1);
}

Dann können Sie einfach a verwenden, DateTimeFormatterum das LocalDatein ein gewünschtes Format zu formatieren, zum Beispiel ...

DateTimeFormatter format = DateTimeFormatter.ofPattern("yyyyMMdd");
List<String> formats = workDays.stream().map(value -> value.format(format)).collect(Collectors.toList());

for (String value : formats) {
    System.out.println(value);
}
MadProgrammer
quelle
@Eugene Also - es ist im Wesentlichen eine Kurzfassung von dem, was ich sowieso getan habe - schön zu wissen
MadProgrammer
irgendwie, ja, letztendlich schon LongStream.rangeClosed(0, steps).mapToObj( n -> this.plusMonths(months * n).plusDays(days * n));... Aber in Bezug auf Ihren Code ArrayListkönnte das die Größe 240einer groben Schätzung von haben 360 - 2 * 40. Wenn Sie ein if(condition) {NO-OP} else {OP}is haben, sollten Sie es aufif(!condition){OP}
Eugene
1
Ich verstehe.
Eugene
1
@Eugene Wie das Feedback allerdings 😉
MadProgrammer
7
    Set<DayOfWeek> weekend = EnumSet.of(DayOfWeek.SATURDAY, DayOfWeek.SUNDAY);
    LocalDate.of(2019, Month.JANUARY, 1)
             .datesUntil(LocalDate.of(2020, Month.DECEMBER, 31), Period.ofDays(1))
             .filter(x -> !weekend.contains(x.getDayOfWeek()))
             .forEachOrdered(System.out::println);
Eugene
quelle
2

Eine übersichtliche Möglichkeit, alle Wochentage in einem Datumsbereich mit Java 8 und der modernen Datums- / Uhrzeit-API anzuzeigen, ist wie folgt:

import java.time.DayOfWeek;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoUnit;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;

public class Main {
    public static void main(String[] args) {
        List<LocalDate> dates = getDates("2019-01-01", "2019-12-31");
        for (LocalDate date : dates) {
            System.out.println(DateTimeFormatter.BASIC_ISO_DATE.format(date));
        }
    }

    public static List<LocalDate> getDates(String fromDate, String toDate) {
        LocalDate startDate = LocalDate.parse(fromDate);
        LocalDate endDate = LocalDate.parse(toDate).plusDays(1);
        long range = ChronoUnit.DAYS.between(startDate, endDate);
        return Stream.iterate(startDate, date -> date.plusDays(1)).limit(range)
                .filter(d -> !(d.getDayOfWeek() == DayOfWeek.SATURDAY || d.getDayOfWeek() == DayOfWeek.SUNDAY))
                .collect(Collectors.toList());
    }
}

Ausgabe:

20190101
20190102
20190103
20190104
20190107
20190108
...
...
...
20191226
20191227
20191230
20191231
Arvind Kumar Avinash
quelle
1
Sehr schön. Zwei Dinge, die ich ändern würde, sind das Speichern ChronoUnit.DAYS.between(startDate, endDate)in einer Variablen, anstatt jedes Mal neu zu berechnen. Auch für Java 9+ Code kann man .takeWhile(endDate::isAfter)anstelle von verwenden limit(). Sie können auch den Enum-Vergleich verwenden, anstatt die Namen von Wochentagen zu vergleichen:!(d -> d.getDayOfWeek() == DayOfWeek.SUNDAY || d.getDayOfWeek() == DayOfWeek.SUNDAY)
ernest_k
Danke, @ernest_k für das positive Feedback. Ihr Kommentar bedeutet mir sehr viel. Ich werde es verbessern, wie Sie vorgeschlagen haben.
Arvind Kumar Avinash
@ernest_k - Ich habe Ihren ersten Kommentar aufgenommen, aber den zweiten den Lesern überlassen, um sich selbst einzubeziehen, da OP erwähnt hat, dass er Java 8 verwendet. Mein Verständnis war auch, dass JVM optimieren würde, ChronoUnit.DAYS.between(startDate, endDate)anstatt jedes Mal neu zu berechnen. Ich brauche deine Hilfe, um zu verstehen, ob es nicht richtig war.
Arvind Kumar Avinash
Ich bin mir nicht sicher, d.getDayOfWeek().name().equals("SATURDAY")wann ich das tun soll, d.getDayOfWeek() == DayOfWeek.SATURDAYwas robuster wäre - IMHO
MadProgrammer
1
import java.time.DayOfWeek;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoUnit;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;
public class Main {
public static void main(String[] args) {
    List<LocalDate> dates = getDates("2019-01-01", "2019-12-31");
    for (LocalDate date : dates) {
        System.out.println(DateTimeFormatter.BASIC_ISO_DATE.format(date));
    }
}

public static List<LocalDate> getDates(String fromDate, String toDate) {
    LocalDate startDate = LocalDate.parse(fromDate);
    LocalDate endDate = LocalDate.parse(toDate).plusDays(1);
    long range = ChronoUnit.DAYS.between(startDate, endDate);
    return Stream.iterate(startDate, date -> date.plusDays(1)).limit(range)
            .filter(d -> !(d.getDayOfWeek() == DayOfWeek.SATURDAY || d.getDayOfWeek() == DayOfWeek.SUNDAY))
            .collect(Collectors.toList());
}

}}

Yasser Abdel-Maksoud
quelle
Der Code ist wunderschön. Möglicherweise möchten Sie eine Erklärung hinzufügen, warum und wie die Aufgabe ausgeführt wird.
Ole VV
-1

Versuche dies:

// Java 8 verwenden

 DateTimeFormatter oldPattern = DateTimeFormatter
        .ofPattern("yyyy-MM-dd HH:mm:ss");
    DateTimeFormatter newPattern = DateTimeFormatter.ofPattern("yyyy-MM-dd");

    LocalDateTime datetime = LocalDateTime.parse(input, oldPattern);
    output = datetime.format(newPattern);

    System.out.println("old format date: " + input);
    System.out.println("new format date : " + output);
Raghavendra
quelle
Netter Code, aber seine Beziehung zu der gestellten Frage entgleitet mir?
Ole VV
Ich habe hier nur meinen Code als Beispiel angegeben und er kann der Art und Weise folgen, wie ich sie verwendet habe. aber nur er muss ein neues Datumsformat aus meinem Code übernehmen.
Raghavendra