Seite 1 von 1
Kalender / Anahl der Arbeitstage für 5/6-Tage woche
Verfasst: Di, 06. Nov 2007 21:11
von kuhno
Hallo zusammen,
für eine Auswertung benötige ich die Anzahl der Arbeitstage und die Zahl der Wochenfeiertage im Monat.
Beispiel : November hat 30 Tage, 26 Arbeitstage bei 6-Tage-Woche und keinen allemeingültige Wochenfeiertag.
Im Moment behlfe ich mir, dass ich eine Tabelle mit diesen Daten per Hand eingebe. Nun möchte ich das gern automatich machen. In den Tools III habe ich nix darüber gefunden. Gibt es sowas oder muss ich mir darüber Gedanken und ein Programm machen?
Gruß
Manfred
Verfasst: Di, 06. Nov 2007 21:23
von Martin Altmann
Hallo Manfred,
Du wirst keine Möglichkeit haben, als das von Hand zu machen!
Natürlich kannst Du die Tage des Monats durch 7 teilen, die Zahl als Ganzzahl mit 6 multiplizieren, und dann hast Du schon mal die "ganzen" Wochen.
Effektiver wäre es sicherlich, die Anzahl der einzelnen Sonntage zu ermitteln und von der Zahl der Tage des Monats abzuziehen.
Damit hast Du jedoch die Feiertage nicht berücksichtigt.
Die musst Du selber pflegen!
Es gibt die festen Feiertage - die sind einfach!
Der Rest ist eigentlich immer bezogen auf Ostern - und der Termin ist variabel und in jedem Jahr anders. Dies muss man berechnen und dann davon ausgehend die variablen Feiertage berücksichtigen.
Problematisch wird es nur mit den "regionalen" Feiertagen, die nur in bestimmten Regionen gelten - da wirst Du also nicht umhin kommen, dies in einer Datei zu pflegen und anzupassen!
Viele Grüße,
Martin
Verfasst: Di, 06. Nov 2007 21:30
von Martin Altmann
Re: Kalender / Anahl der Arbeitstage für 5/6-Tage woche
Verfasst: Di, 06. Nov 2007 22:17
von AUGE_OHR
hi,
kuhno hat geschrieben:
Beispiel : November hat 30 Tage, 26 Arbeitstage bei 6-Tage-Woche und keinen allemeingültige Wochenfeiertag.
woher weiss das Programm das der November 30 Tage hat ?
ich fange jeweils mit dem 1st des Monats an und sehe mir an was für
ein Wochentag es ist.
Code: Alles auswählen
cMonat := STRZERO(nMonat,2)
dFDOM := CTOD( "01." + cMonat + "." + cJAHR ) // FistDayOfMonth
nDay := DOW( dFDOM )
damit kann ich schon mal die Tage bis zum nächsten Sonntag ausrechnen
nun zähle ich 1 Monat dazu - 1 Tag. (Jahrewechsel wenn Monat > 12)
Code: Alles auswählen
IF nMonat = 12
...
ENDIF
cMonat := STRZERO(nMonat+1,2)
dLDOM := CTOD( "01." + cMonat + "." + cJAHR ) // LastDayOfMonth
dLDOM := dLDOM -1
nDay := DOW( dLDOM )
nDPM := VAL(SUBSTR(DTOS(dLOM),7,2)) // DayPerMonth
Damit stehe ich also auf dem letzten Tag des Monat und brauche mir
auch keine Gedanken über Schaltjahre zu machen.
gruss by OHR
Jimmy
Verfasst: Mi, 07. Nov 2007 7:28
von Jan
Ich hab ein Clipperprogramm zur exakten Berechnung von Ostern. Wenn jemand den Code benötigte: Nachricht an mich.
Und wie Martin schon sagt: Ein guter Teil der religiösen Feiertage hängt an dieser Berechnung (wie Pfingsten = Ostern + 50 Tage). Aber Datumsberechnungen sind ja nun einmal eine große Stärke von Xbase++
Jan
Verfasst: Mi, 07. Nov 2007 7:50
von Koverhage
Jimmy,
wie viele Tage ein Monat hat ist doch relativ einfach zu ermitteln:
nTage := day(ctod("01.12.2007")-1)
Für die allgemein gültigen Feiertage, hier müsste man die speziellen der einzelnen Bundesländer noch hinzufügen und das jeweilige Bundesland als Parameter übergeben
static function ist_Feiertag(dPruefDat)
local pnJahr := year(dPruefDat)
local cJahr := str(pnJahr,4)
local nAktTag := day(dPruefDat)
local nAktMon := month(dPruefDat)
local lRetCode := .f.
* Ostern:
local ostern := ctod(oster_berech(pnJahr)+cJahr)
* Buß- und Bettag
local nBBTag := dow(ctod("24.12."+cJahr)) - 1
local dBBDatum := ctod("31.12."+cJahr) - 39 - nBBTag
do case
case nAktTag = 1 .and. nAktMon = 1 // Neujahr
lRetCode := .t.
case nAktTag = 6 .and. nAktMon = 1 // Heilige Drei Könige
lRetCode := .t.
case nAktTag = 1 .and. nAktMon = 5 // Maifeiertag
lRetCode := .t.
case nAktTag = 15 .and. nAktMon = 8 // Maria Himmelfahrt
lRetCode := .t.
case nAktTag = 3 .and. nAktMon = 10 // Tag der deutschen Einheit
lRetCode := .t.
case nAktTag = 1 .and. nAktMon = 11 // Allerheiligen
lRetCode := .t.
case nAktTag = 25 .and. nAktMon = 12 // 1. Weihnachtsfeiertag
lRetCode := .t.
case nAktTag = 26 .and. nAktMon = 12 // 2. Weihnachtsfeiertag
lRetCode := .t.
case ostern-2 = dPruefdat // Karfreitag
lRetCode := .t.
case ostern = dPruefdat // Ostersonntag
lRetCode := .t.
case ostern+1 = dPruefdat // Ostermontag
lRetCode := .t.
case ostern+49 = dPruefdat // Pfingstsonntag
lRetCode := .t.
case ostern+50 = dPruefdat // Pfingstmontag
lRetCode := .t.
case ostern+39 = dPruefdat // Himmelfahrt
lRetCode := .t.
case ostern+60 = dPruefdat // Fronleichnam
lRetCode := .t.
endcase
return lRetCode
Verfasst: Mi, 07. Nov 2007 8:20
von Jan
Ich hab gerade den Code für Ostern rausgesucht. Ist nicht viel, also pack ich das mal direkt hier rein.
Ostern (gültig erst ab 1582)
Code: Alles auswählen
FUNCTION feiertag(nJahr)
LOCAL nGold, nJahrhundert, nCorx, nCorz, nSonntag, nEpakte, nMond, nMonat := 0, nTag := 0
IF nJahr > 1582
* <<nGold>> ist die Goldene Nummer des Jahres im 19 Jahres Metonic Zyklus
nGold := nJahr % 19 + 1
* <<nJahrhundert>> Jahrhundert
nJahrhundert := INT (nJahr / 100) + 1
* Korrektur:
* <<nCorx>> ist die Anzahl der Jahre in denen Schaltjahre aufgehoben werden
* um mit der Sonne konform zu bleiben
nCorx = INT ((3 * nJahrhundert) / 4 - 12)
* <<nCorz>> ist eine spezielle Korrektur um Ostern mit dem Mondumlauf zu synchronisieren
nCorz = INT ((8 * nJahrhundert + 5) / 25 - 5)
* <<nSonntag>> Sonntag finden
nSonntag = INT ((5 * nJahr) / 4 - nCorx - 10)
* Epakte <<nEpakte>> finden (Erscheinen des Vollmondes spezifizieren)
nEpakte = INT ((11 * nGold + 20 + nCorz - nCorx) % 30)
IF nEpakte < 0
nEpakte += 30
ENDIF
IF ((nEpakte = 25) .AND. (nGold > 11)) .OR. (nEpakte = 24)
++nEpakte
ENDIF
* Vollmond finden - der <<nMond>>te des M„rz ist ein "kalendarischr" Vollmond
nMond = 44 - nEpakte
IF nMond < 21
nMond += 30
ENDIF
* Zum Sonntag
nMond = INT(nMond + 7 - ((nSonntag + nMond) % 7))
* Monat und Tag erhalten
IF nMond > 31
nMonat = 4
nTag = nMond - 31
ELSE
nMonat = 3
nTag = nMond
ENDIF
ENDIF
RETURN CTOD(RIGHT("00" + LTRIM(STR(INT(nTag))), 2) + "." + ;
RIGHT("00" + LTRIM(STR(nMonat)), 2) + "." + STR(nJahr, 4))
Buß- und Bettag:
Code: Alles auswählen
FUNCTION busstag(nAktjahr)
LOCAL busstag := CTOD("25.12." + ALLTRIM(STR(nAktjahr))), tag := 7
DO WHILE tag <> 1
busstag --
tag := DOW(busstag)
ENDDO
RETURN busstag - 35 - 4
Un der Muttertag. ist zwar sowieso ein Sonntag, aber wenn wir gerade mal dabei siend...
Code: Alles auswählen
FUNCTION muttertag(nAktjahr)
LOCAL muttertag := CTOD("30.04." + ALLTRIM(STR(nAktjahr))), tag := 7
DO WHILE tag <> 1
muttertag ++
tag := DOW(muttertag)
ENDDO
RETURN muttertag + 7
Und ein paar Feiertage:
Code: Alles auswählen
Epiphanis "06.01." // Hlg. 3 Könige
Quinquagesima DTOC(feiertag(aktjahr) - 50) // 50 Tage vor Ostern
Septuagesima DTOC(feiertag(aktjahr) - 63) // 9 Sonntage vor Ostern
Quadragesima DTOC(feiertag(aktjahr) - 40) // 40 Tage vor Ostern
Sexagesima DTOC(feiertag(aktjahr) - 56) // 8 Sonntage vor Ostern
Estomihi DTOC(feiertag(aktjahr) - 49) // 7 Sonntage vor Ostern
Invocavit DTOC(feiertag(aktjahr) - 42) // 6 Sonntage vor Ostern
Reminiscere DTOC(feiertag(aktjahr) - 35) // 5 Sonntage vor Ostern
Oculi DTOC(feiertag(aktjahr) - 28) // 4 Sonntage vor Ostern
Laetare DTOC(feiertag(aktjahr) - 21) // 3 Sonntage vor Ostern
Judica DTOC(feiertag(aktjahr) - 14) // 2 Sonntage vor Ostern
Palmsonntag/Palmarum DTOC(feiertag(aktjahr) - 7) // 1 Sonntag vor Ostern
Gründonnerstag DTOC(feiertag(aktjahr) - 4) // Donnerstag vor Ostern
Karfreitag DTOC(feiertag(aktjahr) - 3) // Freitag vor Ostern
Ostersonntag DTOC(feiertag(aktjahr))
Quasimodogeniti DTOC(feiertag(aktjahr) + 7) // 1 Sonntag nach Ostern
Misericordias Domini DTOC(feiertag(aktjahr) + 14) // 2 Sonntage nach Ostern
Jubilate DTOC(feiertag(aktjahr) + 21) // 3 Sonntage nach Ostern
Cantate DTOC(feiertag(aktjahr) + 28 ) // 4 Sonntage nach Ostern
Rogate DTOC(feiertag(aktjahr) + 35) // 5 Sonntage nach Ostern
Muttertag IIF(aktjahr >= 1907, ; // 2 Sonntag im Mai
DTOC(muttertag(aktjahr)), ;
" ab 1907")
Himmelfahrt DTOC(feiertag(aktjahr) + 39) // 40 Tage nach Ostern
Exaudi DTOC(feiertag(aktjahr) + 42) // 6 Sonntage nach Ostern
Pfingstsonntag DTOC(feiertag(aktjahr) + 49) // 50 Tage nach Ostern
Trinitatis DTOC(feiertag(aktjahr) + 56) // 1 Sonntag nach Pfingsten
Fronleichnam DTOC(feiertag(aktjahr) + 60) // 2 Donnerstage nach Pfingsten
Buß- und Bettag DTOC(busstag(aktjahr)) //
Totensonntag DTOC(busstag(aktjahr) + 4) // Sonntag nach Bußtag
Jan
Nachtrag: Hatte den Buß- und Bettag vergessen. Und dann auch noch den Muttertag.
Verfasst: Mi, 07. Nov 2007 16:13
von AUGE_OHR
hi,
Koverhage hat geschrieben:
wie viele Tage ein Monat hat ist doch relativ einfach zu ermitteln:
nTage := day(ctod("01.12.2007")-1)
sag ich doch +1 Monat -1 Tag.
Wo jetzt ja die berechnungen bekannt sind, wäre die Frage wie ihr
einen solchen Kalendar darstellt ?
gruss by OHR
Jimmy
Verfasst: Mi, 07. Nov 2007 20:24
von kuhno
Hallo zusammen,
danke für alle Vorschläge, aber da werde ich bei dem Vorschlag von Martin bleiben, zumal das ganze ja nur einmal im Jahr aktualisiert werden muss.
Gruß
Manfred
Re: Kalender / Anahl der Arbeitstage für 5/6-Tage woche
Verfasst: Do, 04. Feb 2016 14:32
von Wonderer
danke schon mal für die Vorarbeit mit diesem Thread, jetzt bin ich allerdings etwas verwundert ob mein Code auch wirklich so korrekt ist.
ohne Betrachtung der Feiertage habe ich folgendes:
Code: Alles auswählen
function getCountWorkdays( dDateFrom, dDateTo ) // Anzahl der Werktage bis ZielDatum
local aWeekdays := { "Montag","Dienstag","Mittwoch","Donnerstag","Freitag","Samstag","Sonntag" }, ;
nWeekdayNo := 1, ;
nWorkdays, ;
nRefDay := 5, ;
nDifDays, nDiv, nDivInt, ;
bDebug := .f.
// Position des Start-Datums in der Woche (Offset)
nWeekdayNo := AScan( aWeekdays, CDow( dDateFrom ) )
// Anzahl der Tage von-bis (inklusive Start-/Endtag)
nDifDays := dDateTo - dDateFrom + 1
// Offset einrechnen
nDifDays += (nWeekdayNo-1)
// Anzahl der Wochen ermitteln
nDiv := nDifDays / 7
nDivInt := int(nDiv)
// Werktage berechnen (Rechung mit 2Tagen pro Woche kein Werktag)
nWorkdays := nDifDays - (nWeekdayNo-1) - (nDivInt*2)
return nWorkdays
Jetzt habe ich dann noch die Gauß-Formel versucht analog eines VB-Codes zu schreiben.
Auch da bin ich mir jetzt nicht sicher ob das so stimmt (wegen dem Casten zu Ganzzahl).
Code: Alles auswählen
function getEasterSunday( nYear )
local a, b, c, d, e, f, dDateResult
if nYear==0
nYear := Year( Date() )
endif
a := int(nYear % 19)
b := int(nYear / 100)
c := (8 * b + 13) / 25 -2
d := int(b - (nYear / 400) - 2)
e := int((19 * int(nYear % 19) + int((15 - c + d) % 30)) % 30)
if e==28
if a>10
e:=27
endif
elseif e==29
e := 28
endif
f := int((d + 6 * e + 2 * int(nYear % 4) + 4 * int(nYear % 7) + 6) % 7)
dDateResult := CtoD( "1.3."+ltrim(str(nYear)) )
dDateResult += (e + f + 22 - 1)
return dDateResult
Anhand dieses Datums kann ich dann die restlichen Feiertage einbeziehen mit:
Code: Alles auswählen
if dDateFrom<=dHoliday .and. dDateTo>=dHoliday
nWorkdays--
endif
Quelle VB-GaußFormel:
https://msdn.microsoft.com/de-de/library/bb979477.aspx
Wie schon gesagt bin ich mir nicht sicher wegen dem Casten zu Int.
Ich nehme an ohne die Konvertierung bekomme ich nicht die gleichen Werte da im VB alles Datentyp Long ist?
Danke schon mal falls ihr dafür etwas Zeit habt...