Mittwoch, 28. Mai 2008

Datumsspielereien (Teil 3) / Date gadgets (Part 3)

Im dritten Posting geht es um diejenigen Feiertage, die in direkter Beziehung zu Heiligabend oder vielmehr dem 1. Weihnachtsfeiertag stehen.

Im Einzelnen handelt es sich hier um den Volkstrauertag, Buss- und Bettag, Totensonntag sowie den 1. - 4. Advent.

Der folgende Code greift auf die im Teil 1 beschriebene Funktion SetYear() zurück.

Ähnlich wie beim Osterfest und den daran gekoppelten Feiertagen verhält es sich mit den an dieser Stelle aufgeführten Terminen. Basis ist der letzte Sonntag vor dem 1. Weihnachtsfeiertag.

* korrigierte Version gemäss wOOdy's Vorschlag            
* CTOD() gegen die bessere DATE()-Funktion auszutauschen
FUNCTION GetVolkstrauertag as Date
LPARAMETERS Jahr as Integer
    Jahr = SetYear(Jahr)
    ld25 = DATE(Jahr,12,25)
    RETURN ld25 - DOW(ld25,2) - 35
ENDFUNC

FUNCTION GetBussUndBettag as Date
LPARAMETERS Jahr as Integer
    Jahr = SetYear(Jahr)
    RETURN GetTotensonntag(Jahr) - 4
ENDFUNC

FUNCTION GetTotensonntag as Date
LPARAMETERS Jahr as Integer
    Jahr = SetYear(Jahr)
    ld25 = DATE(Jahr,12,25)
    RETURN ld25 - DOW(ld25,2) - 28
ENDFUNC

FUNCTION GetErsterAdvent as Date
LPARAMETERS Jahr as Integer
    Jahr = SetYear(Jahr)
    ld25 = DATE(Jahr,12,25)
    RETURN ld25 - DOW(ld25,2) - 21
ENDFUNC

FUNCTION GetZweiterAdvent as Date
LPARAMETERS Jahr as Integer
    Jahr = SetYear(Jahr)
    ld25 = DATE(Jahr,12,25)
    RETURN ld25 - DOW(ld25,2) - 14
ENDFUNC

FUNCTION GetDritterAdvent as Date
LPARAMETERS Jahr as Integer
    Jahr = SetYear(Jahr)
    ld25 = DATE(Jahr,12,25)
    RETURN ld25 - DOW(ld25,2) - 7
ENDFUNC

FUNCTION GetVierterAdvent as Date
LPARAMETERS Jahr as Integer
    Jahr = SetYear(Jahr)
    ld25 = DATE(Jahr,12,25)
    RETURN ld25 - DOW(ld25,2)
ENDFUNC

Montag, 26. Mai 2008

Datumsspielereien (Teil 2) / Date gadgets (Part 2)

Im zweiten Posting der Datumspielereien geht es um die Berechnung von Weiberfastnacht, Rosenmontag, Fastnacht, Aschermittwoch, Karfreitag, Ostermontag, Christi Himmelfahrt, Pfingstsonntag, Pfingstmontag und Fronleichnam. Mit anderen Worten um sämtliche (mir bekannten) Ostern-abhängigen Feiertage.

Der folgende Code greift auf die im Teil 1 beschriebenen Funktionen GetOstersonntag() und SetYear() zurück.

Die zuvor genannten Feiertage liegen sozusagen in 'fester Entfernung' zum Osterfest.
Weiberfastnacht liegt genau 50 Tage vor dem Ostersonntag
Christi Himmelfahrt hingegen 39 Tage hinter dem Ostersonntag
Pfingsten wiederum liegt 49 Tage hinter dem Ostersonntag
Fronleichnam bringt es auf 60 Tage hinter dem Ostersonntag

FUNCTION GetWeiberFastnacht as Date
LPARAMETERS Jahr as Integer
    Jahr = SetYear(Jahr)
    RETURN GetOstersonntag(Jahr) - 50
ENDFUNC

FUNCTION GetRosenmontag as Date
LPARAMETERS Jahr as Integer
    Jahr = SetYear(Jahr)
    RETURN GetOstersonntag(Jahr) - 48
ENDFUNC

FUNCTION GetFastnacht as Date
LPARAMETERS Jahr as Integer
    Jahr = SetYear(Jahr)
    RETURN GetOstersonntag(Jahr) - 47
ENDFUNC

FUNCTION GetAschermittwoch as Date
LPARAMETERS Jahr as Integer
    Jahr = SetYear(Jahr)
    RETURN GetOstersonntag(Jahr) - 46
ENDFUNC

FUNCTION GetKarfreitag as Date
LPARAMETERS Jahr as Integer
    Jahr = SetYear(Jahr)
    RETURN GetOstersonntag(Jahr) - 2
ENDFUNC

FUNCTION GetOstermontag as Date
LPARAMETERS Jahr as Integer
    Jahr = SetYear(Jahr)
    RETURN GetOstersonntag(Jahr) + 1
ENDFUNC

FUNCTION GetChristiHimmelfahrt as Date
LPARAMETERS Jahr as Integer
    Jahr = SetYear(Jahr)
    RETURN GetOstersonntag(Jahr) + 39
ENDFUNC

FUNCTION GetPfingstsonntag as Date
LPARAMETERS Jahr as Integer
    Jahr = SetYear(Jahr)
    RETURN GetOstersonntag(Jahr) + 49
ENDFUNC

FUNCTION GetPfingstmontag as Date
LPARAMETERS Jahr as Integer
    Jahr = SetYear(Jahr)
    RETURN GetOstersonntag(Jahr) + 50
ENDFUNC

FUNCTION GetFronleichnam as Date
LPARAMETERS Jahr as Integer
    Jahr = SetYear(Jahr)
    RETURN GetOstersonntag(Jahr) + 60
ENDFUNC

Montag, 19. Mai 2008

Datumsspielereien (Teil 1) / Date gadgets (Part 1)

Als ich mit dem Entwickeln von Software begann, hätte ich mir nicht träumen lassen, welche Algorithmen hinter der Berechnung eines speziellen Datums liegen können.

Natürlich war ich mir der beweglichen kirchlichen Feiertage bewußt, aber um das Warum machte ich mir keine Gedanken. Erst wenn wir uns näher mit diesen diversen Feiertagen befassen stellen wir fest, dass das Osterfest für die Berechnung des Fastnachtstermins ebenso ursächliche Wirkung zeigt wie für Christi Himmelfahrt und Pfingsten.

Mit diesem Posting beginne ich eine kleine Serie rund um Datumsberechnungen im Fux. Die Berechnung der Feiertage beruht hierbei auf den Daten der westlichen Kirchen.

Den Anfang macht natürlich das schon zuvor angesprochene Osterfest, im speziellen der Ostersonntag.

Die von Carl Friedrich Gauß erstmals im Jahre 1800 veröffentlichte Gaußsche Osterformel steht bereits in Pascal und Basic und sicherlich auch anderen Sprachen im WWW zum Herunterladen bereit. Der folgende Code stellt eine Möglichkeit der Umsetzung in Visual Foxpro dar.

FUNCTION GetOstersonntag as Date
LPARAMETERS Jahr as Integer
* Erster Sonntag nach dem Frühlingsvollmond                         
* Die u.a. Formel entspricht der von Gauss entwickelten Variante 
LOCAL a as Integer, b as Integer, c as Integer, d as Integer, e as Integer, f as Integer 
    Jahr = SetYear(Jahr) 
    a = MOD(Jahr,19) 
    b = INT(Jahr/ 100) 
    c = INT((8 * b + 13) / 25 - 2) 
    d = b - INT(Jahr/ 400) - 2 
    e = MOD(19 * MOD(Jahr,19) + MOD(15 - c + d,30),30) 
    DO CASE 
    CASE e = 28 AND a > 10
        e = 27 
    CASE e = 29
        e = 28 
    ENDCASE 
    f = MOD(d + 6 * e + 2 * MOD(Jahr,4) + 4 * MOD(Jahr,7) + 6,7) 
    * CTOD entsporgt = korrigierte wOOdy-Version (Thanx :-) )     
    * die '-1' lasse ich im Gedenken an das Original (d + e + 22) 
    * noch so stehen.                                             
    RETURN DATE(Jahr,3,1) + (e + f + 22) - 1
ENDFUNC

Die o.a. Funktion greift auf eine weitere Funktion mit dem Namen 'SetYear' zurück. Sie stellt sicher, dass bei ungültiger Parametrisierung mit einem gültigen Wert gearbeitet wird.

Hier nun diese zusätzliche Funktion, auf die im Übrigen auch die Codebeispiele in den folgenden Postings zurückgreifen werden.

FUNCTION SetYear as Integer
LPARAMETERS Jahr as Integer

    * korrigierte wOOdy-Version (again Thanx :-) )
    RETURN EVL(Jahr, YEAR(DATE()))
   
ENDFUNC

Montag, 5. Mai 2008

So bekommen wir einen Cursor in die Zwischenablage / How to get a cursor into clipboard

Um Textinformationen in die Zwischenablage zu kopieren wird üblicherweise die Systemvariable _CLIPTEXT genutzt.

cMyVar = [Hallo Welt]
_cliptext = cMyVar

Mit einer Tabelle (oder einem Cursor) funktioniert dies allerdings nicht.

Um eine Datenmenge, unabhängig davon ob sie als Tabelle oder als Cursor vorliegt, in die Zwischenablage zu bekommen könnte man nun meinen, dass mühevoll per Schleifenverarbeitung jedes einzelne Feld per TRANSFORM in einen String kopiert werden muss. Dem ist jedoch nicht so.

Visual Foxpro verfügt über ein Applikationobjekt, das auf die aktuelle VFP Ínstanz verweist. Ansprechbar ist es über die Systemvariable _VFP. Geben wir bspw. im Befehlsfenster _VFP. ein, so erhalten wir über Intellisense eine Übersicht der verfügbaren Eigenschaften und Methoden. Eine davon lautet DataToClip. Um nun unsere Daten in die Zwischenablage zu kopieren genügt der folgende Code:

* Felder getrennt durch Leerzeichen
_VFP.DataToClip([myCursor],RECCOUNT([myCursor]),1)

* Felder getrennt durch Tabulatoren
_VFP.DataToClip([myCursor],RECCOUNT([myCursor]),3)


Hierbei stehen in der ersten Zeile des in die Zwischenablage kopierten Textes die Feldnamen. Im Anschluss folgen mit je einer Zeile pro Datensatz die Feldinhalte.