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

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

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


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

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

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

}}


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

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
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.