Kalender / Anahl der Arbeitstage für 5/6-Tage woche

Sonstiges (nicht kategorisierbar)

Moderator: Moderatoren

Kalender / Anahl der Arbeitstage für 5/6-Tage woche

Beitragvon kuhno » Di, 06. Nov 2007 22:11

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
kuhno
UDF-Programmierer
UDF-Programmierer
 
Beiträge: 54
Registriert: Sa, 07. Jan 2006 18:30
Wohnort: Braunschweig

Beitragvon Martin Altmann » Di, 06. Nov 2007 22:23

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
:grommit:
Webseite mit XB2.NET und ausschließlich statischem Content in Form von HTML-Dateien: http://www.altem.de/
Webseite mit XB2.NET und ausschließlich dynamischem Content in Form von in-memory-HTML: http://meldungen.altem.de/

Mitglied der XUG Osnabrück
stellv. Vorsitzender des Deutschsprachige Xbase-Entwickler e. V.
Benutzeravatar
Martin Altmann
Foren-Administrator
Foren-Administrator
 
Beiträge: 13217
Registriert: Fr, 23. Sep 2005 4:58
Wohnort: Berlin

Beitragvon Martin Altmann » Di, 06. Nov 2007 22:30

Hier mal einige links:
Feiertag in Deutschland (auch bewegliche)
Berechnung Ostern

Viele Grüße,
Martin
:grommit:
Webseite mit XB2.NET und ausschließlich statischem Content in Form von HTML-Dateien: http://www.altem.de/
Webseite mit XB2.NET und ausschließlich dynamischem Content in Form von in-memory-HTML: http://meldungen.altem.de/

Mitglied der XUG Osnabrück
stellv. Vorsitzender des Deutschsprachige Xbase-Entwickler e. V.
Benutzeravatar
Martin Altmann
Foren-Administrator
Foren-Administrator
 
Beiträge: 13217
Registriert: Fr, 23. Sep 2005 4:58
Wohnort: Berlin

Re: Kalender / Anahl der Arbeitstage für 5/6-Tage woche

Beitragvon AUGE_OHR » Di, 06. Nov 2007 23:17

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
Benutzeravatar
AUGE_OHR
Marvin
Marvin
 
Beiträge: 10309
Registriert: Do, 16. Mär 2006 8:55
Wohnort: Hamburg

Beitragvon Jan » Mi, 07. Nov 2007 8:28

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
Benutzeravatar
Jan
Foren-Administrator
Foren-Administrator
 
Beiträge: 11887
Registriert: Fr, 23. Sep 2005 18:23
Wohnort: 49328 Melle

Beitragvon Koverhage » Mi, 07. Nov 2007 8:50

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
Benutzeravatar
Koverhage
Der Entwickler von "Deep Thought"
Der Entwickler von "Deep Thought"
 
Beiträge: 1908
Registriert: Fr, 23. Dez 2005 9:00
Wohnort: Aalen

Beitragvon Jan » Mi, 07. Nov 2007 9:20

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.
Benutzeravatar
Jan
Foren-Administrator
Foren-Administrator
 
Beiträge: 11887
Registriert: Fr, 23. Sep 2005 18:23
Wohnort: 49328 Melle

Beitragvon AUGE_OHR » Mi, 07. Nov 2007 17:13

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
Benutzeravatar
AUGE_OHR
Marvin
Marvin
 
Beiträge: 10309
Registriert: Do, 16. Mär 2006 8:55
Wohnort: Hamburg

Beitragvon kuhno » Mi, 07. Nov 2007 21:24

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
kuhno
UDF-Programmierer
UDF-Programmierer
 
Beiträge: 54
Registriert: Sa, 07. Jan 2006 18:30
Wohnort: Braunschweig

Re: Kalender / Anahl der Arbeitstage für 5/6-Tage woche

Beitragvon Wonderer » Do, 04. Feb 2016 15:32

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...
Wonderer
Rekursionen-Architekt
Rekursionen-Architekt
 
Beiträge: 107
Registriert: Do, 06. Jul 2006 13:24


Zurück zu Misc.

Wer ist online?

Mitglieder in diesem Forum: Google [Bot] und 1 Gast