Jahreszahlen einer Zeitperiode

Diese Seite verwendet Cookies. Durch die Nutzung unserer Seite erklären Sie sich damit einverstanden, dass wir Cookies setzen. Weitere Informationen

  • Jahreszahlen einer Zeitperiode

    Hallo zusammen,

    nach langer Zeit habe ich mal wieder ein Problem für das mir so recht nichts einfällt, und so hoffe ich das Ihr mir ein Denkanstöße geben könnt.
    Beim Titel ist mir nichts besseres eingefallen, darum hier im Detail die Problemstellung:

    Der User bestimmt eine End Zeit, z.B. 31.03.2024. Daraus ergibt sich sich die Zeitspanne von: Aktuelles Datum (Date()) bis 31.03.2024.
    Ich möchte nun für diese Zeitspanne die Anzahl der Arbeitstage berechnen --> Gesamte Tage (Brutto) - Wochenenden - Feiertage - Urlaub = Netto Tage.

    Was ich bis jetzt habe sind die Brutto Tage, sprich alle Tage der Spanne und diese Tage ohne die Wochenenden.

    Ich habe im Web folgende API gefunden um die deutschen Feiertage für ein Jahr und Bundesland abzufragen:

    feiertage-api.de/api/?jahr=2022&nur_land=NW

    Nun zu meinem Problem/der Frage:

    Da ich über die API die Jahre nur einzeln abfragen kann, benötige ich die Jahreszahl(en) für die vom User gewählte Zeitspanne.
    Im o.g. Beispiel, benötige ich also z.B. ein Array mit ["2022","2023","2024"] um dann über dieses Array zu iterieren und mit Hilfe der API die Feiertage in ein anderes Array zu speichern.

    Wie könnte ich aus einer Zeitspanne von zwei Datumsangaben die Jahreszahlen in ein Array bekommen?

    Danke schon mal für Eure Ideen.

    VG Ralf
  • ralfb schrieb:

    Wie könnte ich aus einer Zeitspanne von zwei Datumsangaben die Jahreszahlen in ein Array bekommen?
    Vielleicht sehe ich die Sache ja zu simple, aber warum nicht in einer Zählschleife von Startjahr bis Endjahr iterieren (inklusive) und in jedem Durchlauf ein entsprechendes Element zu einem Array hinzufügen?

    Arbeitest Du für die Tagesdifferenz mit NSCalender bzw. NSDateComponents?

    Mattes
    Diese Seite bleibt aus technischen Gründen unbedruckt.
  • Hallo @MyMattes

    ich habe für die Berechnung der Arbeitstage in diversen Foren und Artikeln gestöbert und folgendes für mich adaptiert:

    C-Quellcode

    1. extension Calendar {
    2. static let iso8601 = Calendar(identifier: .iso8601)
    3. }
    4. extension Date {
    5. var isDateInWeekend: Bool {
    6. return Calendar.iso8601.isDateInWeekend(self)
    7. }
    8. var tomorrow: Date {
    9. return Calendar.iso8601.date(byAdding: .day, value: 1, to: noon)!
    10. }
    11. var noon: Date {
    12. return Calendar.iso8601.date(bySettingHour: 12, minute: 0, second: 0, of: self)!
    13. }
    14. }
    15. // Functions
    16. func countWorkingDays(from start: Date, to end: Date) -> Int {
    17. guard start < end else { return (0) }
    18. var weekendDays = 0
    19. var workingDays = 0
    20. var date = start.noon
    21. repeat {
    22. if date.isDateInWeekend {
    23. weekendDays += 1
    24. } else {
    25. workingDays += 1
    26. }
    27. date = date.tomorrow
    28. } while date < end
    29. return workingDays
    30. }
    Alles anzeigen
    Über die Funktion "countWorkingDays" bekomme ich dann die Anzahl der Tage außer Wochenende zurück geliefert indem ich zwei Date() Werte mitgebe.
    Ich muss zugeben ich habe noch nicht sehr viel mit NSCalender/NSDate gearbeitet und mir fehlt der Ansatz wie ich hier bei den zwei Date Werten nur die Jahreszahlen "extrahieren" kann.

    Hast Du ggf. ein Code Schnipsel der mir das verdeutlicht?
    Ich werde auf jeden Fall mal mit NSDateComponents etwas im Playground "spielen" ;)

    VG Ralf
  • ralfb schrieb:

    Ich muss zugeben ich habe noch nicht sehr viel mit NSCalender/NSDate gearbeitet und mir fehlt der Ansatz wie ich hier bei den zwei Date Werten nur die Jahreszahlen "extrahieren" kann.
    Schau mal hier in den Objective-C-Code ... damit sollte das Prinzip auch für Swift klar sein: Du definierst, welche Datumskomponenten Dich interessieren und kannst dann auf das entsprechende Property von NSDateComponents zugreifen, z. B. components.year:

    Quellcode

    1. NSCalendar *calendar = [NSCalendar currentCalendar];
    2. NSCalendarUnit calendarUnits = NSCalendarUnitYear;
    3. NSDateComponents *components = [calendar components:calendarUnits fromDate:date];

    Mattes

    P.S.: Haben bei Dir Start- und Enddatum Zeitkomponenten? Wenn ja, da stolpert Dein Algorithmus m. E. an einem Endzeitpunkt am Nachmittag: Von heute 17:00 bis morgen 17:00 sind es 2 Tage, da Du nur die Anfangszeit auf Mittag setzte ... ausser ich übersehe gerade etwas. Entweder - wenn die Uhrzeit keine Rolle spielt - diese in beiden Datumswerten konstant setzen oder einfach beibehalten.
    Diese Seite bleibt aus technischen Gründen unbedruckt.

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von MyMattes () aus folgendem Grund: Postscriptum zur Differenzberechnung ergänzt.

  • Ich habe bei Stackoverflow etwas gefunden was für mich funktioniert, gebe aber offen zu das ich den Code nicht zu 100% verstanden habe ?( was natürlich schlecht ist.
    Habe das mal in Playground getestet, hier der Code:

    C-Quellcode

    1. extension DateFormatter {
    2. func years<R: RandomAccessCollection>(_ range: R) -> [String] where R.Iterator.Element == Int {
    3. setLocalizedDateFormatFromTemplate("yyyy")
    4. var comps = DateComponents(month: 1, day: 1)
    5. var res = [String]()
    6. for y in range {
    7. comps.year = y
    8. if let date = calendar.date(from: comps) {
    9. res.append(string(from: date))
    10. }
    11. }
    12. return res
    13. }
    14. }
    15. let period = TimeInterval(60 * 60 * 24 * 365) // one Year
    16. let retirementDate: Date = Date(timeIntervalSinceNow: period * 2)
    17. let startYearComponents = Calendar.current.dateComponents([.year], from: Date())
    18. let endYearComponents = Calendar.current.dateComponents([.year], from: retirementDate)
    19. let startYear = startYearComponents.year ?? 0
    20. let endYear = endYearComponents.year ?? 0
    21. let df = DateFormatter()
    22. print(df.years(Int(startYear)...Int(endYear)))
    Alles anzeigen

    Hier die Ausgabe:

    ["2022", "2023", "2024"]

    Es ist ja genau das was ich mir vorgestellt habe, allerdings kommt es mir sehr komplex vor was die Lösung angeht.

    Wie ist Eure Spezialisten Meinung zu dem o.g. Code ?

    VG Ralf
  • ralfb schrieb:

    Wie ist Eure Spezialisten Meinung zu dem o.g. Code ?
    Für Deine Fragestellung unnötig und komplex und unnötig komplex. Das Hauptproblem ist aber (wie Du sagst) "das ich den Code nicht zu 100% verstanden habe" :) Damit sollte er für Dich keine Option sein - ich würde nie (nie!) Code verwenden, den ich nicht verstehe.

    Hier mal mein Beispiel als Playground, mit dem üblichen Disclaimer: Ich kann - noch - kein Swift und es gibt bestimmt viel elegantere Methoden, das Array zu füllen ... und auch sonst lasse ich mich gerne korrigieren!

    Quellcode

    1. import Cocoa
    2. let formatter = DateFormatter()
    3. formatter.dateFormat = "dd.MM.yyyy"
    4. let startDate = formatter.date(from: "01.03.2018")
    5. let startDateYearComponent = Calendar.current.dateComponents([.year], from:startDate!)
    6. let startYear = startDateYearComponent.year ?? 0
    7. let endDate = formatter.date(from: "18.10.2021")
    8. let endDateYearComponent = Calendar.current.dateComponents([.year], from:endDate!)
    9. let endYear = endDateYearComponent.year ?? 0
    10. var results: [Int] = []
    11. for year in startYear...endYear {
    12. results.append(year)
    13. }
    14. print(results)
    Alles anzeigen
    Den DateFormatter verwende ich nur, um einfach Initialwerte der beiden Daten zu setzen.

    Mattes
    Diese Seite bleibt aus technischen Gründen unbedruckt.
  • Hallo @MyMattes


    MyMattes schrieb:

    Damit sollte er für Dich keine Option sein - ich würde nie (nie!) Code verwenden, den ich nicht verstehe.
    Ja, da hast Du zu 100% Recht!!

    Danke für Dein Beispiel, es funktioniert einwandfrei und ist so einfach das ich mich ja schon fast ein bisschen schäme :rolleyes: das ich da nicht selbst drauf gekommen bin ...
    Irgendwie habe ich da mal wieder VIEL ZU KOMPLIZIERT gedacht .. mit Hilfe von DateComponents hat man ja einen Zahlenbereich - unabhängig von einer Date() Komplexität mit der man ganz "normal" arbeiten kann.

    VG Ralf
  • Quellcode

    1. extension ClosedRange where Bound == Date {
    2. func years(using calendar: Calendar) -> ClosedRange<Int> {
    3. let start = calendar.component(.year, from: lowerBound)
    4. let end = calendar.component(.year, from: upperBound)
    5. return start ... end
    6. }
    7. }
    Aufruf:

    Quellcode

    1. let formatter = DateFormatter()
    2. formatter.dateFormat = "dd.MM.yyyy"
    3. let startDate = formatter.date(from: "01.03.2018")!
    4. let endDate = formatter.date(from: "18.10.2021")!
    5. let range = startDate...endDate
    6. print(range.years(using: .current))
    Ließe sich im Prinzip auch irgendwo anders aufhängen (`Calendar.years(from:to:)`… oder halt bei `Date`)
  • Thallius schrieb:

    ganz blöde Frage aber hast schon irgendwas mal durch lesen gelernt oder hat du einfach nur lauter Code aus dem Internet zusammen gestochert von dem du überhaupt keine Ahnung hast was er tut?
    Da ich weiß das es keine blöden Fragen gibt, nehme ich Deine Frage also auch ernst und versuche diese zu beantworten.

    Kurz zu meinem Hintergrund ... ich bin weder Entwickler noch strebe ich an einer zu werden. Mich interessiert das Thema "IOS Apps"
    weil es spannend und interessant ist und ich mag diese Herausforderungen, die ich versuche mir mit einfachen und mehr oder weniger praktischen Apps "für den Hausgebrauch", selber zu stellen.

    Ja, ich habe einiges gelesen, habe Udemy Kuss gesehen und mich mich mit zahlreichen Menschen, die eine Leidenschaft für das Thema besitzen und anderen Menschen gerne helfen, unterhalten und ausgetauscht.
    Dieser Austausch alleine ist für mich als Hobby/Freizeitbeschäftigung enorm wertvoll!

    Ja, und ich habe auch vieles an Code "aus dem Internet zusammen gestochert" und versucht es zu verstehen, für mich in meine Aufgabe zu adaptieren und daraus zu lernen.
    Einiges habe ich bestimmt auch nicht verstanden, aber für mich ist "der Weg das Ziel".

    Ich hoffe es beantwortet Deine Frage und ich hoffe auch das ich trotz mangelnder Kenntnisse in diesem Forum weiterhin meine Fragen stellen kann.

    VG Ralf
  • Hallo,

    habe Deine Fragestellung gerade gelesen und wenn ich mich nicht täusche, wird diese unter nachfolgender URL Datumrechner ebenfalls erörtert. Zuerst in Form eines Beispiels und weiter u. folgt die Studie hierzu.

    ralfb schrieb:

    Thallius schrieb:

    ganz blöde Frage aber hast schon irgendwas mal durch lesen gelernt oder hat du einfach nur lauter Code aus dem Internet zusammen gestochert von dem du überhaupt keine Ahnung hast was er tut?


    Ich hoffe es beantwortet Deine Frage und ich hoffe auch das ich trotz mangelnder Kenntnisse in diesem Forum weiterhin meine Fragen stellen kann.

    VG Ralf
    Ralf, Thallius hat Dich bestimmt nicht angreifen oder Deine Kenntnisse in Frage stellen wollen.

    Selbstverständlich kannst Du Dich, unabhängig von Deinem Kenntnisstand, mit Deinen Fragen an die Leute hier im Forum wenden.

    Manchmal ist man(n) etwas müde und formuliert die ein oder andere Frage/Antwort unpräzise.

    Aber nicht verzagen, es ist noch kein Meister vom Himmel gefallen oder kleine Schritte führen auch zum Ziel.

    Ein gutes Buch für die Einführung zu nutzen ist bestimmt nicht verkehrt.

    Also Kopf hoch und nicht aufgeben.

    VG

    Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von OSXDev ()