• Hallo Leute,

    Ich brauchte einfach mal die Funktion die mir zu jedem beliebigen Datum ab dem Jahre 1 den Tag ausgibt. Ich wollte es hier nur einmal reinstellen falls es jemand Benötigt oda jemand Verbesserungsvorschläge machen will (gibt bestimmt welche)

    _DateToDay
    [autoit]

    MsgBox (0,"",_DateToDay (17,07,2011))

    [/autoit] [autoit][/autoit] [autoit]

    Func _DateToDay ($Day,$Month,$Year)
    ;Createt by Hendrik Norkowski (Jam00)
    ;$Day = DD $Month = MM $Year = YYYY
    Local $Tage = 1, $i, $1, $MonatsTage, $WDays
    $Tage += 365 * ($Year - 0001)
    $i = ($Year - Mod ($Year,4)) - 0001
    If Mod ($Year,4) = 0 And $Month < 03 Then
    $i -= 1
    EndIf
    For $1 = 4 To $i Step 4
    $Tage += 1
    Next
    $MonatsTage = StringSplit ("31|28|31|30|31|30|31|31|30|31|30|31","|")
    For $1 = 1 To $Month - 01
    $Tage += $MonatsTage[$1]
    Next
    $Tage += $Day - 01
    While $Tage > 7
    $Tage -= 7
    WEnd
    $WDays = StringSplit ("Montag|Dienstag|Mittwoch|Donnerstag|Freitag|Samstag|Sonntag","|")
    Return ($WDays[$Tage])
    EndFunc

    [/autoit]

    EDIT:
    Mir ist noch eine bessere Idee gekommen allerdings weiß ich nicht ob sie geht, werde ich noch ausprobieren

    mfg. Jam00

  • Hallo :)
    Ich habe auch einst eine solche funktion in C geschrieben.
    Und mir ist aufgefallen das du nicht Prüfst ob es die tage gibt.
    Hier ist mal mein C code vielleicht kannst du ja damit was anfangen, übrigens für leute die es nicht wissen
    vom 4.10.1582 bis zum 15.10.1582 gab es keine tage da 10 tage übersprungen worden sind.

    Datum überprüfen:

    Spoiler anzeigen
    [autoit]

    bool _exist_date(const int tt,const int mm,const int jjjj)
    {
    bool schaltjahr=false,monat_30_tage=true,richtiges_datum=false,wahre_monat=false,ausnahme_schalt=false;
    if(jjjj==1582 && mm==10 && tt>4 && tt<15)
    {
    return richtiges_datum;
    }

    if(jjjj % 100 == 0) /* wenn jahr durch 100 teilbar ist */
    {
    ausnahme_schalt=true; /* setze ausnahme_schalt=true(wahr) */
    /* da alle 100 Jahre kein schaltjahr ist */
    }
    if(ausnahme_schalt==true && jjjj % 400 == 0)/* wenn ausnahme_schalt==true(wahr) ist aber jahr durch 400 teilbar ist */
    {
    schaltjahr=true; /* Setze schaltjahr=true(wahr) */
    /* da aber alle 400 Jahre dennnoch ein schaltjahr ist */
    }
    if(jjjj % 4 ==0 && ausnahme_schalt==false)/* wenn das jahr durch 4 teilbar und ausnahme_schalt=false ist */
    {
    schaltjahr=true;/* setze schaltjahr=true(wahr) */
    /* da alle 4 jahre normaler weise ein schaltjahr ist außer es ist ein ausnahme jahr*/
    }

    if(mm<=12 && mm >=1)/* wenn monat unter 12 ist also die monate halt max. 12 monate */
    {
    wahre_monat=true;/* setze wahre_monat=true(wahr) */
    /* grund ist wenn es falsch ist bleibt der wert falsch(false) damit gehen die
    nächsten aktionen nicht ausgeführt werden und somit
    später richtiges_datum=false(falsch) ist */
    }

    if(wahre_monat==true && mm==1||mm==3||mm==5||mm==7||mm==8||mm==10||mm==12)
    /* wenn wahre_monat=true(wahr) ist und monat einer der monate: 1,3,5,7,8,10,12 (die monate mit 31 tagen*/
    {
    monat_30_tage=false;/* setze monat_30_tage=false(falsch) */
    /* wenn der monat also 31 tage hat wird die gerenze der tage auf 31 gesetzt
    wäre es dementsprechend nicht false(falsch) dann würde die max. tag anzahl auf 30 gesetzt
    werden bzw bleiben */
    }

    if(wahre_monat==true && monat_30_tage==true && mm == 2) /* wenn wahre_monat=true(wahr) und monat_30_tage=true(wahr) ist und der monat 2 ist */
    {
    if(schaltjahr==false && tt >= 29)/* wenn kein schaltjahr ist und die tage mehr als 29 sind setzte datum*/
    {
    richtiges_datum=false;/* richtiges_datum=false(falsch) da wenn kein schaltjahr keine 29 tage oder rüber gibt */
    }
    if(tt <= 28 && tt >=1)/* prüft ob tag ansonsten unter 28 ist wenn nicht richtiges_datum ist bereits auf true gesetzt */
    {
    richtiges_datum=true;/* richtiges_datum=true(wahr) da alle tage unter 28 immer korrekt sind */
    }
    if(schaltjahr==true && tt == 29)/* wenn es ein schaltjahr ist und tag=29 */
    {
    richtiges_datum=true;/* setze richtiges_datum=true(wahr) da alle kreterien überprüft wurden
    erst das jahr dann der monat und der tag stimt auch */
    }
    }
    if(mm != 2 && wahre_monat==true && monat_30_tage==true && tt <=30 && tt >=1)/* wenn wahre_monat=true(wagr) und monat_30_tage=true und der tag kleiner oder gleich 30 */
    {
    richtiges_datum=true; /* setze richtiges_datum=true */
    }
    if(wahre_monat==true && monat_30_tage==false && tt <=31 && tt >=1)/* wenn wahre_monat=true(wagr) und monat_30_tage=false und der tag kleiner oder gleich 31 */
    {
    richtiges_datum=true; /* setze richtiges_datum=true */
    }

    return richtiges_datum;
    }

    [/autoit]

    Datum Tag wiedergeben:

    Spoiler anzeigen
    [autoit]

    string _wochentag(const int tt,const int mm,const int jjjj)
    {
    // Maximal Tage werden der Monate zugeordnet. (Array)
    int monat[12];
    monat[0] = 31; /* Januar */
    monat[1] = 28; /* Februar */
    monat[2] = 31; /* März */
    monat[3] = 30; /* April */
    monat[4] = 31; /* Mai */
    monat[5] = 30; /* Juni */
    monat[6] = 31; /* Juli */
    monat[7] = 31; /* August */
    monat[8] = 30; /* September */
    monat[9] = 31; /* Oktober */
    monat[10] = 30; /* November */
    monat[11] = 31; /* Dezember */

    // Wochen Tage werden zugeordnet. (Array)
    string wochentage[7];
    wochentage[0] = "Samstag"; /* Samstag */
    wochentage[1] = "Sonntag"; /* Sonntag */
    wochentage[2] = "Montag"; /* Montag */
    wochentage[3] = "Dienstag"; /* Dienstag */
    wochentage[4] = "Mittwoch"; /* Mittwoch */
    wochentage[5] = "Donnerstag"; /* Donnerstag */
    wochentage[6] = "Freitag"; /* Freitag */

    // Weitere Variablen werden Deklariert.
    // Teilweise mit Zuweisung.
    int tag = (jjjj-1)*365+(tt-1); /* Tage werden errechnet. */
    int schaltjahr; /* Schaltjahr wird für spätere Zwecke Deklariert. */
    int i; /* i als Standard Zähler Variable. */


    // Rechnung.
    // Rechnung aus den weiten des Internets zusammen getragen.
    // Dieser Algorithmus ist getestet und Funktioniert!
    // Bitte nicht verändern!
    for(i=0;i<(mm-1);i++)/* i wird bestimmt um die Tage des Monat (Array) zu bestimmen. */
    {
    tag += monat[i]*1; /* Zuvor bestimmte Anzahl der Tage des Monats mit Tagen (Variable) Addieren. */
    }

    if(jjjj>1582 || jjjj==1582 && (mm>10 || mm==10 && tt >4)) tag -= 10; /* Kalenderreform: Sprung vom 04.10.1582 zum 15.10.1582. */
    schaltjahr = lround(jjjj/4); /* Schaltjahre werden bestimmt [ Funktion "Iround(float)" rundet auf die nächst kleinste und größte stelle auf]. */

    // Weitere Schaltjahr berechnung.
    // Da alle 4 Jahre ein Schaltjahr auftritt,
    // alle 100 Jahre nicht,
    // aber alle 400 Jahre wieder. Sprich:
    // 2000 -> ja ( durch 400 teilbar )
    // 2100 -> nein ( durch 100 teilbar )
    // 2104 -> ja ( durch 4 teilbar )
    if(jjjj%4==0 && mm == 2) schaltjahr--;
    if(jjjj>=1600)
    {
    schaltjahr -= lround((jjjj-1600) / 100);
    schaltjahr += lround((jjjj-1600) / 400);
    if(jjjj%100==0 && mm==2)
    {
    schaltjahr++;
    if(jjjj%400==0) schaltjahr--;
    }
    }
    tag +=schaltjahr; /* Zusammen Zählung der Schaltjahre und der Tage. */
    return wochentage[tag%7]; /* Entsprechender Wochentag wird zurückgegeben. */
    }

    [/autoit]

    Ich brauchte diese Funktionen mal weil mich jemand gefragt hat ob ich eine idee hätte wie man das Programmieren könnte ^^

  • Oh achso, das 15~~ 10 Tage Übersprungen wurden wusste ich nicht, müsste ich dann noch eingeben!

    Ui dein Code in C ist aber ne ganze ecke Länger als meiner!
    Dachte das zu Prüfen ist nicht so wichtig, weil man eig in der Lage sein sollte, ein Datum richtig einzugeben! Aber ich kann es wohl noch einbauen!

    mfg. Jam00

  • Oh achso, das 15~~ 10 Tage Übersprungen wurden wusste ich nicht, müsste ich dann noch eingeben!

    So einfach ist es dann leider doch nicht ganz.
    Es ist nicht einfach nur ein Sprung von 10 Tagen drin sondern es markiert die Grenze zwischen 2 verschiedenen Kalendersystemen. Dem Julianischen und dem Gregorianischen Kalender.
    Ab dem 14. Oktober 1582 entsprechen bei uns Datumsangaben dem gregorianische Kalender. Daten davor ( Minus die fehlenden 10 Tage) sind Angaben im Julianischen Kalender.
    Nun kann man nicht einfach nur die 10 Tage Unterschied zur Umrechnung beider Systeme heranziehen sondern man muss auch auf die unterschiedlichen Schaltagsregelungen Rücksicht nehmen (im gregorianischen Kalender sind z.B. Säkularjahre, außer die die durch 400 teilbar, sind keine Schaltjahre...).
    Daher gestaltet sich eine Wochentagsangabe vor dem 14. Oktober 1582 als ziemlich schwierig.

    Ein Ausweg:
    Die Datumsangaben sind ziemlich ungünstig für mathematische Berechnungen (vor allem in der Astronomie/Geodäsie wird dies benötigt).
    Wünschenswert wäre eine einfache Zahl welche alle Tage fortlaufend (ohne irgendwelche Schaltsprünge) darstellt.
    Dieses System ist das sogenannte Julianische Datum.
    Es wurde einfach festgelegt das der 1. Januar −4712 (12:00 Uhr) das julianische Datum 0 erhält und alle nachfolgenden Tage einfach fortlaufend gezählt werden (Heute ist z.B. der Tag 2455761).
    Wenn man nun eine Umrechnung vom Julianischen Kalender und vom Gregorianischen Kalender in das Julianische Datum hinbekommt werden die nachfolgenden Berechnungen deutlich einfacher.
    Die Umrechnungen zwischen den Kalendersystemen vereinfachen sich, Zeitdifferenzen zwischen 2 Daten entsprechen nur noch einer einfachen Subtraktion und die Wochentagsberechnung verkürzt sich auf eine einfache Modulo-Operation.
    Damit wird es dann möglich auch in Zeitangaben vor dem 1582 im julianischen Kalender korrekte Wochentage zu berechnen.
    Für die Datumsdifferenzen wird in den Date-Funktionen von AutoIt übrigens ein ähnliches System verwendet - nur der Nullpunkt ist ein anderer als beim julianischen Datum - der sogenannte Unix-Timestamp.

    Die Umrechnungen zwischen diesen 3 Systemen habe ich, welch Zufall ;-), schon einmal implementiert. Hier mal ein kleines Beispiel wie man sie verwenden kann:

    Kalendersystemumrechnungen
    [autoit]

    #include <Date.au3>
    #include <Math.au3>
    Global $a_Greg[3], $a_Julian[3]

    [/autoit] [autoit][/autoit] [autoit]

    ; Anfangsdaten im gregorianischen Kalender wählen:
    Global $a_StartGreg = DateDialog("Anfangsdatum")
    Global $a_EndGreg = DateDialog("Enddatum")

    [/autoit] [autoit][/autoit] [autoit]

    ; Umrechnung vom Gregorianischen Kalender in das julianische Datum:
    Global $JD_Start = Date_Gregorian2JD($a_StartGreg[0], $a_StartGreg[1], $a_StartGreg[2])
    Global $JD_End = Date_Gregorian2JD($a_EndGreg[0], $a_EndGreg[1], $a_EndGreg[2])

    [/autoit] [autoit][/autoit] [autoit][/autoit] [autoit]

    ; Gehe alle Tage zwischen Start und Ende durch und gib Verschiedene Datumsangaben dazu aus:
    ConsoleWrite(@CRLF & "Jul. Datum Greg.Kal. Jul.Kal. Wochentag" & @CRLF & "-----------------------------------------------------------" & @CRLF)
    For $i = $JD_Start To $JD_End
    Date_JD2Gregor($i, $a_Greg)
    Date_JD2Julian($i, $a_Julian)
    ConsoleWrite( $i & @TAB & @TAB & _
    $a_Greg[0] & "." & $a_Greg[1] & "." & $a_Greg[2] & @TAB & _
    $a_Julian[0] & "." & $a_Julian[1] & "." & $a_Julian[2] & @TAB & Date_JD2DayOfWeek($i) & @CRLF)
    Next

    [/autoit] [autoit][/autoit] [autoit][/autoit] [autoit][/autoit] [autoit][/autoit] [autoit][/autoit] [autoit]

    #region ################ Datumsfunktionen #############################################
    ; Julianischer Kalender in Julianisches Datum:
    Func Date_Julian2JD(Const $DD, Const $MM, Const $JJ)
    Local $M = adjusted_month_from_month($MM)
    Local $J = adjusted_year_from_year($JJ, $MM)
    Local $y4800 = $J + 4800
    Local $a = division($y4800, 100)
    Local $b = Mod($y4800, 100)
    Return 36525 * $a + 1461 * division($b, 4) + 365 * Mod($b, 4) + division((7 * ($M - 2)), 12) + 30 * $M + 1 * $DD + 1721027 - 1753200
    EndFunc ;==>Date_Julian2JD

    [/autoit] [autoit][/autoit] [autoit]

    ; Gregorianischer Kalender in Julianisches Datum:
    Func Date_Gregorian2JD(Const $DD, Const $MM, Const $JJ)
    Local $y4800 = $JJ + 4800
    Local $a = division($y4800, 100)
    Local $b = Mod($y4800 ,100)
    Return 146097 * division($a, 4) + 36524 * Mod($a , 4) + 1461 * division($b, 4) + 365 * Mod($b , 4) + division((7 * ($MM - 2)), 12) + 30 * $MM + 1 * $DD + 1721029 - 1753164
    EndFunc ;==>Date_Gregorian2JD

    [/autoit] [autoit][/autoit] [autoit][/autoit] [autoit]

    ; Julianisches Datum in Gregorianischen Kalender
    Func Date_JD2Gregor(Const $JD, ByRef $aGregRet)
    Local $a, $b, $c, $D, $e, $f, $g, $h, $k, $l, $t, $M, $J, $m_strich, $j_strich

    [/autoit] [autoit][/autoit] [autoit]

    $a = 1 * $JD + 32044
    $b = division($a, 146097)
    $c = Mod($a, 146097)
    $D = _Min(3, division($c, 36524))
    $e = $c - 36524 * $D
    $f = division($e, 1461)
    $g = Mod($e, 1461)
    $h = _Min(3, division($g, 365))
    $k = $g - 365 * $h
    $l = division((111 * $k + 41), 3395)
    $t = $k - 30 * $l - division((7 * $l + 7), 12) + 1
    $m_strich = $l + 3
    $j_strich = 400 * $b + 100 * $D + 4 * $f + 1 * $h - 4800
    $M = month_from_adjusted_month($m_strich)
    $J = year_from_adjusted_year($j_strich, $m_strich);

    [/autoit] [autoit][/autoit] [autoit]

    $aGregRet[0] = $t
    $aGregRet[1] = $M

    [/autoit] [autoit][/autoit] [autoit]

    If $J < 1 Then
    $aGregRet[2] = Abs($J - 1) * -1 ; = vor unserer Zeit
    Else
    $aGregRet[2] = $J
    EndIf
    EndFunc ;==>Date_JD2Gregor

    [/autoit] [autoit][/autoit] [autoit][/autoit] [autoit]

    ; Julianisches Datum in Julianischen Kalender:
    Func Date_JD2Julian(Const $JD, ByRef $aJulRet)
    Local $a, $b, $c, $D, $e, $f, $t, $m_strich, $j_strich, $M, $J

    [/autoit] [autoit][/autoit] [autoit]

    $a = 1 * $JD + 32082
    $b = division($a, 1461)
    $c = Mod($a, 1461)
    $D = _Min(3, division($c, 365))
    $e = $c - 365 * $D
    $f = division((111 * $e + 41), 3395)
    $t = $e - 30 * $f - division((7 * $f + 7), 12) + 1
    $m_strich = $f + 3
    $j_strich = 4 * $b + 1 * $D - 4800
    $M = month_from_adjusted_month($m_strich)
    $J = year_from_adjusted_year($j_strich, $m_strich)

    [/autoit] [autoit][/autoit] [autoit]

    $aJulRet[0] = $t ; Tag
    $aJulRet[1] = $M ; Monat

    [/autoit] [autoit][/autoit] [autoit]

    If $J < 1 Then ; Jahr
    $aJulRet[2] = Abs($J - 1) * -1 ; = vor unserer Zeit
    Else
    $aJulRet[2] = $J
    EndIf
    EndFunc ;==>Date_JD2Julian

    [/autoit] [autoit][/autoit] [autoit]

    ; Julianisches Datum in Modifiziertes Julianisches Datum:
    Func Date_JD2MJD(Const $JD)
    Return $JD - 2400000.5
    EndFunc ;==>Date_JD2MJD

    [/autoit] [autoit][/autoit] [autoit]

    ; Julianisches Datum in Wochentag:
    Func Date_JD2DayOfWeek(Const $JD)
    Local Static $a_Wochentage[7] = ["Montag", "Dienstag", "Mittwoch", "Donnerstag", "Freitag", "Samstag", "Sonntag"]
    Return $a_Wochentage[Mod(Round($JD), 7)]
    EndFunc
    #endregion ##########################################################

    [/autoit] [autoit][/autoit] [autoit][/autoit] [autoit][/autoit] [autoit][/autoit] [autoit]

    #region ############### Hilfsfunktionen #############################
    Func division(Const $zaehler, Const $nenner)
    Local $quotient = $zaehler / $nenner
    Local $rest = Mod($zaehler, $nenner)
    Return Round($quotient - ($rest / $nenner))
    EndFunc ;==>division

    [/autoit] [autoit][/autoit] [autoit]

    Func month_from_adjusted_month($m_strich)
    Return Mod(($m_strich + 11), 12) + 1
    EndFunc ;==>month_from_adjusted_month

    [/autoit] [autoit][/autoit] [autoit][/autoit] [autoit]

    Func year_from_adjusted_year($j_strich, $m_strich)
    Return $j_strich + division($m_strich, 13)
    EndFunc ;==>year_from_adjusted_year

    [/autoit] [autoit][/autoit] [autoit]

    Func adjusted_month_from_month($M)
    Return Mod((1 * $M + 9), 12) + 3
    EndFunc ;==>adjusted_month_from_month

    [/autoit] [autoit][/autoit] [autoit]

    Func adjusted_year_from_year($Y, $M)
    Return $Y - 1 + division((1 * $M + 7), 10)
    EndFunc ;==>adjusted_year_from_year

    [/autoit] [autoit][/autoit] [autoit]

    ; Funktion zum Wählen des Datums im gregorianischen Kalender
    Func DateDialog(Const $s_Text = "Datum wählen")
    Local $h_GUI = GUICreate($s_Text, 210, 190)
    Local $ctrl_Date = GUICtrlCreateMonthCal(_NowCalcDate() , 10, 10)
    GUISetState()
    Do
    Until GUIGetMsg() = -3
    Local $a_Ret = StringSplit(StringRegExpReplace(GUICtrlRead($ctrl_Date), '(\d{4})/(\d{2})/(\d{2})', '$3.$2.$1'), ".", 2)
    GUIDelete($h_GUI)
    Return $a_Ret
    EndFunc
    #endregion ##########################################################

    [/autoit]


    Noch eine kleine Frage: Die AutoIt-Funktionen _DateToDayOfWeek(), _DateToDayOfWeekISO() und _DateDayOfWeek() sind dir schon bekannt?

    2 Mal editiert, zuletzt von AspirinJunkie (18. Juli 2011 um 11:27)

  • Es ist nicht einfach nur ein Sprung von 10 Tagen drin sondern es markiert die Grenze zwischen 2 verschiedenen Kalendersystemen. Dem Julianischen und dem Gregorianischen Kalender.


    Das meinte ich :)

    MfG, campweb

  • Noch eine kleine Frage: Die AutoIt-Funktionen _DateToDayOfWeek(), _DateToDayOfWeekISO() und _DateDayOfWeek() sind dir schon bekannt?

    Das meinte ich bei mir mit

    aber ich finde es klasse wenn man so sachen selbst programmiert!

    großes lob!

    eben einfach dieses auch wenn schon da selbst versuchen eine funktion dafür zu schreiben
    Also weiterhin finde ich es toll das du es probert hast!

  • Entschuldige BuFF.
    Du hast natürlich vollkommen Recht.
    Dies ist bei meinem Beitrag untergegangen.
    Diese Berechnungen sind alles andere als trivial und durch die vielen Nebenbedingungen schwer zu überblicken.
    Das ganze selbst zu implementieren ist wirklich eine nicht zu verachtende Leistung.