Kalenderwoche berechnen

Hier könnt Ihr gute, von Euch geschriebene Codes posten. Sie müssen auf jeden Fall funktionieren und sollten möglichst effizient, elegant und beispielhaft oder einfach nur cool sein.
RalfP
Beiträge: 23
Registriert: 17.03.2014 22:32

Kalenderwoche berechnen

Beitrag von RalfP »

Weil ich hier im Forum nichts passendes gefunden habe, habe ich mal eine kleine Procedure geschrieben, die die Kalenderwoche zu einem gegebenen Datum berechnen kann. Dabei habe ich den Code möglichst kurz und effizient gehalten. Die ausführlichen Kommentare sollten es aber einfach machen die Berechnung nachzuvollziehen.
.

Code: Alles auswählen

EnableExplicit
  
Procedure.b WeekOfYear(Datum.l)  
  ; * Berechnung der Kalenderwoche zu einem gegebenen Datum. 
  ; * Das Datum muss zwischen dem 01.01.1970 und 31.12.2037 liegen.
  ; * Die Berechnung erfolgt nach DIN 1355/ISO 8601, d.h. der erste Tag der Woche ist Montag und 
  ; * die erste Kalenderwoche im Jahr ist die Woche, in die mindestens vier Tage des neuen Jahres fallen.
  ; * Wenn nicht mehr als drei Tage vom Jahr in der letzten Woche liegen,
  ; * zählen diese Woche zur ersten Kalenderwoche des Folgejahres.
  Protected DoW = DayOfWeek(Datum)
  Protected Tag.w = Day(Datum)
  Protected KalWo.b
  ; Die Nummern für jeden Wochentag um einen Tag verschieben 
  ; weil der Montag nach DIN der erste Wochentag ist.
  If DoW = 0 : DoW = 7 : EndIf : DoW - 1  ; Mo = 0 ... So = 6
  ; Die Tage der angebrochenen Woche auffüllen und den Wert 
  ; danach durch 7 teilen um die aktuelle Woche zu bestimmen.
  ; Der Umschaltpunkt für die neue Woche ist dann immer der Montag. 
  KalWo = (DayOfYear(Datum) - DoW + 6) / 7 
  ; Wenn der 1.1. des gegebenen Jahres auf einen Di., Mi. oder Do. fällt muss
  ; eine Woche addiert werden weil diese Woche dann als erste Woche gilt.
  ; (Wenn der 1.1. ein Mo. ist gilt diese Woche natürlich auch als erste Woche. Dann wurde
  ; diese Woche aber schon bei der Integerdivision in der Zeile zuvor berücksichtigt.)
  Select DayOfWeek(Date(Year(Datum), 1, 1, 0, 0, 0)) 
    Case 2, 3, 4
      KalWo + 1
  EndSelect
  ; Wenn das gegebene Datum im Dezember liegt fällt es nur bei den folgenden
  ; Tag- Wochentagkombinationen in die erste Kalenderwoche des Folgejahres.
  ; 29. And Mo
  ; 30. And (Mo Or Di)
  ; 31. And (Mo Or Di Or Mi)
  If Month(Datum) = 12
    If (Tag = 29 And DoW = 0) Or (Tag = 30 And DoW < 2) Or (Tag = 31 And DoW < 3)
      KalWo = 1
    EndIf  
  EndIf
  ProcedureReturn KalWo
EndProcedure

Debug "Kalenderwoche: " + Str(WeekOfYear(Date(2020, 12, 28, 0, 0, 0)))
.
Benutzeravatar
Sicro
Beiträge: 955
Registriert: 11.08.2005 19:08
Kontaktdaten:

Re: Kalenderwoche berechnen

Beitrag von Sicro »

Cool :)

Noch nicht ganz fehlerfrei:

Code: Alles auswählen

Debug WeekOfYear(Date(2012, 1, 1, 0, 0, 0)) ; Ergibt 0 anstatt 52
Debug WeekOfYear(Date(2016, 1, 1, 0, 0, 0)) ; Ergibt 0 anstatt 53
Zudem kannst du die Variablentypen weglassen: .b, .l, w. usw. Die brauchst du meistens nur bei Strukturen oder anderen speziellen Fällen.
Bild
Warum OpenSource eine Lizenz haben sollte :: PB-CodeArchiv-Rebirth :: Pleasant-Dark (Syntax-Farbschema) :: RegEx-Engine (kompiliert RegExes zu NFA/DFA)
Manjaro Xfce x64 (Hauptsystem) :: Windows 10 Home (VirtualBox) :: Neueste PureBasic-Version
RalfP
Beiträge: 23
Registriert: 17.03.2014 22:32

Re: Kalenderwoche berechnen

Beitrag von RalfP »

Der Fehler mit der '0' sollte jetzt nicht mehr auftreten. Danke für's Testen.

Den Hinweis auf den Wertbereich (die Angabe der Variablentypen) finde ich hier im Forum nicht nachteilig weil das mit zum Verständnis der Zeilen beiträgt. Wenn man aber schnell mal etwas ausprobieren will, ist es sehr bequem, dass PureBasic die richtigen Variablentypen automatisch zuweist.
.

Code: Alles auswählen

EnableExplicit
  
  
Procedure.b WeekOfYear(Datum.l)  
  ; * Berechnung der Kalenderwoche zu einem gegebenen Datum. 
  ; * Das Datum muss zwischen dem 01.01.1970 und 31.12.2037 liegen.
  ; * Die Berechnung erfolgt nach DIN 1355/ISO 8601, d.h. der erste Tag der Woche ist Montag und 
  ; * die erste Kalenderwoche im Jahr ist die Woche, in die mindestens vier Tage des neuen Jahres fallen.
  ; * Wenn nicht mehr als drei Tage vom Jahr in der letzten Woche liegen,
  ; * zählen diese Woche zur ersten Kalenderwoche des Folgejahres.
  Protected DoW = DayOfWeek(Datum)
  Protected Tag.w = Day(Datum)
  Protected KalWo.b
  ; Die Nummern für jeden Wochentag um einen Tag verschieben 
  ; weil der Montag nach DIN der erste Wochentag ist.
  If DoW = 0 : DoW = 7 : EndIf : DoW - 1  ; Mo = 0 ... So = 6
  ; Die Tage der angebrochenen Woche auffüllen und den Wert 
  ; danach durch 7 teilen um die aktuelle Woche zu bestimmen.
  ; Der Umschaltpunkt für die neue Woche ist dann immer der Montag. 
  KalWo = (DayOfYear(Datum) - DoW + 6) / 7 
  ; Wenn der 1.1. des gegebenen Jahres auf einen Di., Mi. oder Do. fällt muss
  ; eine Woche addiert werden, weil diese Woche dann als erste Woche gilt.
  ; (Wenn der 1.1. ein Mo. ist zählt diese Woche natürlich auch mit. Dann wurde
  ; diese Woche aber schon bei der Integerdivision in der Zeile zuvor berücksichtigt.)
  Select DayOfWeek(Date(Year(Datum), 1, 1, 0, 0, 0)) 
    Case 2, 3, 4
      KalWo + 1
  EndSelect
  ; Wenn der 1.1. auf einen Fr., Sa. oder So. fällt gilt diese Woche nicht als 
  ; erste Woche sondern als letzte Woche vom Vorjahr. Es muss also eine 52 oder 53
  ; zuruckgegeben werden. Die Variable 'KalWo' enthält bis jetzt aber noch eine '0'.
  ; Um herauszufinden ob die '0' dann durch eine 52 oder 53 ersetzt werden muss, wird die 
  ; Procedure jetzt noch einmal rekursiv mit dem Datum 31.12. vom Vorjahr aufgerufen. 
  If KalWo = 0
    ProcedureReturn WeekOfYear(Date(Year(Datum) - 1, 12, 31, 0, 0, 0))
  EndIf
  ; Wenn das gegebene Datum im Dezember liegt fällt es nur bei den folgenden
  ; Tag- Wochentagkombinationen in die erste Kalenderwoche des Folgejahres.
  ; 29. And Mo
  ; 30. And (Mo Or Di)
  ; 31. And (Mo Or Di Or Mi)
  If Month(Datum) = 12
    If (Tag = 29 And DoW = 0) Or (Tag = 30 And DoW < 2) Or (Tag = 31 And DoW < 3)
      KalWo = 1
    EndIf  
  EndIf
  ProcedureReturn KalWo
EndProcedure


Debug "Kalenderwoche: " + Str(WeekOfYear(Date(2012, 1, 1, 0, 0, 0)))

.
Benutzeravatar
Sicro
Beiträge: 955
Registriert: 11.08.2005 19:08
Kontaktdaten:

Re: Kalenderwoche berechnen

Beitrag von Sicro »

RalfP hat geschrieben: 05.05.2021 00:19 Den Hinweis auf den Wertbereich (die Angabe der Variablentypen) finde ich hier im Forum nicht nachteilig weil das mit zum Verständnis der Zeilen beiträgt.
Meistens wird der Variablentyp "Integer" (.i) verwendet, weil dieser immer der Schnellste ist, der der Prozessor verarbeiten kann:
  • Integer mit 32-Bit-Prozessor entspricht: Long (.l)
  • Integer mit 64-Bit-Prozessor entspricht: Quad (.q)
Andere Variablentypen sind wie gesagt nur in speziellen Fällen erforderlich:
  • Dezimalzahlen
  • Genaue Bestimmung der Speichergröße (wichtig z. B. für Strukturen)
  • Geringerer Speicherverbrauch ist wichtiger als höhere Geschwindigkeit
Ich will dir nur sagen, dass du normalerweise nicht so viel über den Variablentyp nachdenken musst, sondern meistens "Integer" verwenden kannst. Wenn der Code für dich jedoch mit präzisen Variabentypen verständlicher ist, ist alles gut :)
RalfP hat geschrieben: 05.05.2021 00:19 Wenn man aber schnell mal etwas ausprobieren will, ist es sehr bequem, dass PureBasic die richtigen Variablentypen automatisch zuweist.
PureBasic verwendet immer "Integer", wenn kein Variablentyp definiert wurde und dieser Typ wird auch außerhalb von "ausprobieren" meistens von Programmierern genutzt.
Bild
Warum OpenSource eine Lizenz haben sollte :: PB-CodeArchiv-Rebirth :: Pleasant-Dark (Syntax-Farbschema) :: RegEx-Engine (kompiliert RegExes zu NFA/DFA)
Manjaro Xfce x64 (Hauptsystem) :: Windows 10 Home (VirtualBox) :: Neueste PureBasic-Version
RalfP
Beiträge: 23
Registriert: 17.03.2014 22:32

Re: Kalenderwoche berechnen

Beitrag von RalfP »

Ok, wenn ich jetzt weiss, dass PureBasic vorzugsweise Integer verwendet, werde ich auf die Angabe der minimal nötigen Typen verzichten. Ich hatte nur etwas gegen das (weit verbreitete) Gottvertrauen darauf, dass eine Technik schon irgendwie funktionieren wird, ohne zu wissen wie und warum.
.
Antworten