Forum: Mikrocontroller und Digitale Elektronik Rechnen mit Datum (localtime,ctime etc) bei Mikros


von Christian J. (Gast)


Lesenswert?

Hallo,

einiges klappt schon aber anderes leider noch nicht.

Ich habe im 32 Bit Register eines STM32F103 die aktuelle Epoch Time und 
kann diese auch umrechnen in ein normales Zeitformat.

Zur Zeit rechne ich UTC in MEZ+1 derart um, dass ich 3600s drauf addiere 
und localtime die Arbeit machen lasse. Zieht gut 2kb extra an Code dazu 
aber 128kb habe ich ja sowieso.

Nun gibt es aber in der time.h Lib auch die Funktion tzset mit der man 
angeblich einstellen kann in welcher Zeitzone man sich befindet und wann 
die Sommerzeit beginnt. Schaut man im POSIX Stndard nach wird da vom 
Umgebungsvariablen gesprochen, die da gesetzt sind. Natürlich hat ein UC 
sowas nicht. tzset wird aber in time.h als LIB Funktion referenziert, 
leider ohne Parameter. Auch gmtime, ctime usw sind alle da, man kann 
sich aus der Epoch Time poroblemlos einen String bauen lassen.

Hat da jemand ne Idee, wie ich mir die Wurschtelei das manuell 
umzurechnen wann die Sommerzeit beginnt, samt Korrektur etc sparen kann?

1
 void RTC_IRQHandler(void)
2
{
3
   #define MEZ +1
4
5
   struct tm *ptr;      // Zeiger auf Zeit Strktur
6
   time_t value;        // 32 Bit Unixzeit
7
8
  if (RTC_GetITStatus(RTC_IT_SEC) != RESET)
9
  {
10
        /* Unixzeit aus RTC lesen */
11
        value = (time_t)RTC_GetCounter();
12
13
        /* UTC +1h dazu addieren */
14
        value = value + (MEZ*3600);
15
16
        /* In Normalzeit UTC hh:mm:ss umwandeln */
17
        ptr = localtime(&value);
18
19
        /* Zeit in eigenen Struct holen */
20
        memcpy((void*)&mytime,ptr,sizeof(struct tm));  // mytime <- localtime Buffer
21
22
        /* Prüfe auf Sommerzeit */
23
        if (IsSummertime())
24
        {
25
            /* Zeit nochmal umrechnen SZ = +1H */
26
            value = value + 3600;
27
            /* In Normalzeit UTC hh:mm:ss umwandeln */
28
            ptr = localtime(&value);
29
            memcpy((void*)&mytime,ptr,sizeof(struct tm));  // mytime <- localtime Buffer
30
            mytime.tm_isdst = true;
31
        }
32
33
        /* Jahr richtig schreiben */
34
        mytime.tm_year += 1900;
35
36
        /* Zeitflags setzen, Minute, Stunde */
37
        f_sekunde = true;
38
        if (mytime.tm_sec == 0)
39
            f_minute = true;
40
        if (mytime.tm_min == 0)
41
            f_stunde = true;
42
43
        /* Clear Interrupt pending bit */
44
        RTC_ClearITPendingBit(RTC_FLAG_SEC);
45
  }
46
}
1
/* Prueft, ob es gerade Sommerzeit ist
2
3
   SZ beginnt am letzten Sonntag im März um  2.00 Uhr -> 3.00 Uhr
4
   und endet am letzten Sonntag im Oktober 3.00 Uhr -> 2.00 Uhr
5
6
   Monate ohne Sommerzeit:  Jan, Feb, November, Dezember.
7
   Monate mit Sommerzeit :  April, Mai, Juni, Juli, August, September
8
   Monate zu prüfen: März und Oktober
9
10
 */
11
_Bool IsSummertime() {
12
13
    /* Monate in denen keine Sommerzeit ist */
14
    if ((mytime.tm_mon < Maerz) || (mytime.tm_mon > Oktober))
15
        return false;
16
17
    /* Monate in denen sicher Sommerzeit ist */
18
    if ((mytime.tm_mon > April) && (mytime.tm_mon < Oktober))
19
        return true;
20
21
    /* Nur Maerz und Oktober bleiben übrig, prüfen auf 3.ten Sonntag */
22
    if (mytime.tm_wday == 0) {
23
        /* Es ist Sonntag ... */
24
        if (31 - mytime.tm_mday < 8) {
25
             /* Sonntag liegt nahe dem Monatsende */
26
             if (mytime.tm_mon == Maerz)
27
                if (mytime.tm_hour >= 2);
28
                    return true;
29
30
             if (mytime.tm_mon == Oktober)
31
                if (mytime.tm_hour < 2);
32
                    return true;
33
        }
34
35
    }
36
37
    return false;
38
39
}

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

Ich wüsste nicht, dass es einfacher geht. Ich benutze für die 
WordClock mit WS2812 eine ähnliche Routine, welche Du für Deine 
Berechnungen offenbar als Vorlage genommen hast, denn die Ähnlichkeiten 
sind unverkennbar ;-)

Jedoch ist in Deiner Funktion ein Fehler:
1
if (31 - mytime.tm_mday < 8) {

Der letzte Sonntag im März ist immer im Bereich vom 25. bis 31. März, 
das sind die letzten 7 Tage.

Wenn der Sonntag auf den 24.03. fällt, ist wegen 31 - 24 = 7
1
if (31 - mytime.tm_mday < 8) {
der obige Ausdruck wahr, obwohl in diesem Fall der 31. März und nicht 
der 24. März der letzte Sonntag ist.

Schreibe besser:
1
if (mytime.tm_mday >= 25) {

Da sieht man auf den ersten Blick, dass es nur Tage zwischen dem 25. und 
31. März sein können und muss nicht erst rechnen.

EDIT:

Du hast noch einen weiteren Fehler drin: Du prüfst nur auf Sonntage im 
März. Was ist mit einem Montag, wie z.B. der 27.03. in diesem Jahr? 
Komischerweise hast Du da die if-Bedingungen umsortiert - offenbar um 
den Source zu vereinfachen. Dabei hast Du aber einiges "wegoptimiert", 
was hätte stehen bleiben müssen.

Hier das Original:
1
    uint_fast8_t    summertime = 0;
2
    ...
3
    // calculate summer time:
4
    if (mytm->tm_mon >= 3 && mytm->tm_mon <= 8)                             // april to september
5
    {
6
        summertime = 1;
7
    }
8
    else if (mytm->tm_mon == 2)                                             // march
9
    {
10
        if (mytm->tm_mday - mytm->tm_wday >= 25)                            // after or equal last sunday in march
11
        {
12
            if (mytm->tm_wday == 0)                                         // today last sunday?
13
            {
14
                if (mytm->tm_hour >= 2)                                     // after 02:00 we have summer time
15
                {
16
                    summertime = 1;
17
                }
18
            }
19
            else
20
            {
21
                summertime = 1;
22
            }
23
        }
24
    }
25
    else if (mytm->tm_mon == 9)                                             // it's october
26
    {
27
        summertime = 1;
28
29
        if (mytm->tm_mday - mytm->tm_wday >= 25)                            // it's after or equal last sunday in october...
30
        {
31
            if (mytm->tm_wday == 0)                                         // today last sunday?
32
            {
33
                if (mytm->tm_hour >= 3)                                     // after 03:00 we have winter time
34
                {
35
                    summertime = 0;
36
                }
37
            }
38
            else
39
            {
40
                summertime = 0;
41
            }
42
        }
43
    }
44
    ...

: Bearbeitet durch Moderator
von Christian J. (Gast)


Lesenswert?

Hi Frank,

danke für die Tips. Nee, ich habe nix abgeschaut, das ist alles bisher 
mein Werk und ähnlich ist es sicherlich irgendwo. Bin alle Monate 
durchgegangen, das >=24 hatte ich schon eingefügt, da der letzte Sonntag 
maximal 7 Tage entfernt sein kann.

Mit den ersten beiden ifs hole ich alles raus bis auf März und Ooktober.
Ok, habe da was vertauscht, hast recht, die ifs müssen verdreht werden.

Ganze easy kann man sich das auch machen, wenn man sich bis Ende 2039 
alle Epoch Times heraussuchen lässt, wo die Umstellung passiert. Ich 
vermute zwar, dass wir 2039 andere Sorgen haben (oder gar keine mehr, 
weil wir tot sind) aber so geht es auch.

2017: 1490580000 und 1509242400
2018: usw...

März und Oktober kann man aber gleich behandeln, beide 31 Tage, beide 
bis auf die Stunde der gleiche Tag der Umstellung.

Ich melde mich später nochmal...

Gruss,
Christian

von Christian J. (Gast)


Lesenswert?

PS: Ist doch etwas komplizierter, da man das nicht auf einen Zeitpunkt 
festmachen darf. Ich kann ja zwischendurch auch mal resetten auf dem 
Montag nach dem Umschalt Sonntag oder an dem Sonntag ist die Uhr aus und 
dann würde meine Rechnung keine Sommerzeit liefern in den Tagen danach. 
Muss noch etwas nachdenken. Ich möchte globale Entweder-Oder-Switch 
Flags vermeiden, eben wegen dem Reset.

Das ist bei Dir allerdings auch so!

Schaltest Du die Uhr erst im Oktober am Montag nach dem Wechsel ein 
bleibt Dein Flag auf Sommerzeit stehen.

Schätze mal einfacher ist es wirklich sich die Unix Zeiten aller Tage 
raus zu suchen und in eine Tabelle zu packen.

von Marc V. (Firma: Vescomp) (logarithmus)


Lesenswert?

Christian J. schrieb:
> März und Oktober kann man aber gleich behandeln, beide 31 Tage, beide
> bis auf die Stunde der gleiche Tag der Umstellung.

 Wie das ?

 Hier, das ist besser und schneller:
1
;*** 2015 => 2050 - März
2
.db  29, 27, 26, 25, 31, 29, 28, 27, 26, 31,  30, 29, 28, 26, 25, 31, 30, 28, 27, 26,  25, 30, 29, 28, 27, 25, 31, 30, 29, 27,  26, 25, 31, 29, 28, 27
3
4
;*** 2015 => 2050 - Oktober
5
.db  25, 30, 29, 28, 27, 25, 31, 30, 29, 27,  26, 25, 31, 29, 28, 27, 26, 31, 30, 29,  28, 26, 25, 31, 30, 28, 27, 26, 25, 30,  29, 28, 27, 25, 31, 30

: Bearbeitet durch User
von Christian J. (Gast)


Lesenswert?

Habe ich früher auch so gemacht, noch einfacher wie gesagt mit den Unix 
Zeiten, da reduziert es sich auf einen einzigen Vergleich :-)

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

Christian J. schrieb:
> Das ist bei Dir allerdings auch so!

Nein, da hast Du meinen Code zu flüchtig gelesen.

> Schaltest Du die Uhr erst im Oktober am Montag nach dem Wechsel ein
> bleibt Dein Flag auf Sommerzeit stehen.

Hier nochmal der Block ab Oktober:
1
    else if (mytm->tm_mon == 9)                                             // it's october
2
    {
3
        summertime = 1;
4
5
        if (mytm->tm_mday - mytm->tm_wday >= 25)                            // it's after or equal last sunday in october...
6
        {
7
            if (mytm->tm_wday == 0)                                         // today last sunday?
8
            {
9
                if (mytm->tm_hour >= 3)                                     // after 03:00 we have winter time
10
                {
11
                    summertime = 0;
12
                }
13
            }
14
            else
15
            {
16
                summertime = 0;
17
            }
18
        }
19
    }

Am Montag nach der Zeitumstellung wird der letzte else-Block 
durchlaufen: summertime = 0;

Vergleiche mal den Block für März mit dem Block für Oktober: Während ich 
im März das Flag bedingt setze, setze ich es im Oktober bei gleichen 
(bzw. ähnlichen) Bedingungen zurück, mache also genau das Gegenteil.

Beachte auch, dass ich immer den Wochentag bei der Berechnung mit 
einbeziehe:
1
if (mytm->tm_mday - mytm->tm_wday >= 25)

Bei Dir steht da immer nur:
1
if (mytm->tm_mday >= 25)    // nach Umstellung der Terme

Das ist zu kurz gedacht. Bei Dir ist alles ab dem 25. schon vorbei, egal 
ob der letzte Sonntag noch kommt oder bereits vorüber ist.

: Bearbeitet durch Moderator
von Christian J. (Gast)


Lesenswert?

Ok ;-)

Habe schon nen Knoten im Hirn wegen der vielen returns. Soll ja nicht 
heissen, ich hatte abgeschrieben. Obwohl die Subtraktionen ist gut, wäre 
ich jetzt nicht drauf gekommen. Hoffe ich habe es jetzt. Testen bin ich 
zu faul, das wäre ne Arbeit für Doofe da im Debugger alles per hand 
einzutragen. Werde aber Sonntag nachts mal aufstehen und schauen, ob das 
klappt.

PS: Es gibt diese Funktionen fertig in den StdLibs, aber leider wohl nur 
für PC's. Mit tzset erschlägt man das alles. Und localtime 
berücksichtigt das auch.
1
enum monat {Januar, Februar, Maerz, April, Mai, Juni, Juli, August,
2
            September, Oktober, November, Dezember};
3
4
enum Wochentag {Montag,Dienstag,Mittwoch,Donnertag,Freitag,Samstag,Sonntag};
5
6
_Bool IsSummertime()
7
{
8
9
    /* Monate in denen keine Sommerzeit ist */
10
    if ((mytime.tm_mon > Oktober) || (mytime.tm_mon < Maerz))
11
        return false;
12
13
    /* Monate in denen sicher Sommerzeit ist */
14
    if ((mytime.tm_mon > Maerz) && (mytime.tm_mon < Oktober))
15
        return true;
16
17
    /* Nur Maerz und Oktober bleiben übrig, prüfen auf letzten Sonntag */
18
    if (mytime.tm_mon == Maerz)
19
    {
20
        /* Sonntag muss nach oder auf dem 25.ten liegen */
21
        if ((mytime.tm_mday - mytime.tm_wday) >= 25)
22
        {
23
            if (mytime.tm_wday == Sonntag)
24
            {
25
                if (mytime.tm_hour >= 2)
26
                    return true;
27
28
                /* Vor 2 Uhr keine Sommerzeit */
29
                return false;
30
            }
31
            /* Alle Tage > Sonntag sind Sommerzeit */
32
            return true;
33
        }
34
        return false;
35
    }
36
37
    if (mytime.tm_mon == Oktober)
38
    {
39
        /* Sonntag muss nach oder auf dem 25.ten liegen */
40
        if ((mytime.tm_mday - mytime.tm_wday) >= 25)
41
        {
42
            if (mytime.tm_wday == Sonntag)
43
            {
44
                if (mytime.tm_hour >= 3)
45
                    return false;
46
47
                /* Vor 3 Uhr keine Normalzeit */
48
                return true;
49
            }
50
            /* Alle Tage nach Sonntag sind Normalzeit */
51
            return false;
52
        }
53
        /* Oktober ist eingangs SZ */
54
        return true;
55
    }
56
57
58
    return false;
59
60
}

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

Christian J. schrieb:
> enum Wochentag
> {Montag,Dienstag,Mittwoch,Donnertag,Freitag,Samstag,Sonntag};
> ...
>             if (mytime.tm_wday == Sonntag)

Das ist ebenso falsch. Laut Definition von tm_wday beginnt die Woche mit 
Sonntag, also Sonntag = 0, Montag = 1 usw.

Schreibe also:
1
enum Wochentag {Sonntag, Montag,Dienstag,Mittwoch,Donnertag,Freitag,Samstag};

Sonst kommt da absoluter Quark raus.

von Christian J. (Gast)


Lesenswert?

Tschuldigung....... :-( duckundwech

von Marc V. (Firma: Vescomp) (logarithmus)


Lesenswert?

Christian J. schrieb:
> Habe ich früher auch so gemacht, noch einfacher wie gesagt mit den Unix
> Zeiten, da reduziert es sich auf einen einzigen Vergleich :-)

 Schneler und einfacher als lesen aus der Tabelle ?

 SchaltTag = MonatsTabelle[year-2015]

 Ausserdem prüfst du das Ganze in _Bool IsSummertime(), da ist aber
 mehr als nur ein Vergleich drin.


 P.S.
 Und _Bool IsSummertime() wird bei dir immer aufgerufen, nicht nur in
 März und Oktober. Ich würde die Monatsabfrage vor dem Aufruf machen.

: Bearbeitet durch User
von Christian J. (Gast)


Lesenswert?

Ich glaube, die paar Takte spielen bei einem 72 Mhz Cortex keine Rolle 
und der Aufruf passiert nur jede Sekunde einmal. Für eine derarrt lahme 
Anwendung wie ich sie habe, die maximal alle paar Stunden überhaupt 
Leben zeigt ist das egal. Die SleepTime beträgt unendlich, aufwachen tut 
er nur wenn ein INT kommt.

von Marc V. (Firma: Vescomp) (logarithmus)


Lesenswert?

Christian J. schrieb:
> Ich glaube, die paar Takte spielen bei einem 72 Mhz Cortex keine Rolle
> und der Aufruf passiert nur jede Sekunde einmal. Für eine derarrt lahme
> Anwendung wie ich sie habe, die maximal alle paar Stunden überhaupt

 Du hast mit einfacher und schneller angefangen und gefragt:
Christian J. schrieb:
> Hat da jemand ne Idee, wie ich mir die Wurschtelei das manuell
> umzurechnen wann die Sommerzeit beginnt, samt Korrektur etc sparen kann?

 Und jetzt auf einmal ist die benötigte Zeit und Wurschtelei nicht mehr
 wichtig ?


 Und meine Frage steht immer noch:
Christian J. schrieb:
> März und Oktober kann man aber gleich behandeln, beide 31 Tage, beide
> bis auf die Stunde der gleiche Tag der Umstellung.

  Wie das ?

von Christian J. (Gast)


Lesenswert?

@Frank:

Vielleicht kannste das ja noch gebauchen, Berechnung der Sonnenaufgangs 
und Untergangszeit auf 5 Minuten genau. Klappt prima.
1
typedef struct
2
{
3
    uint8_t SAG_Std,        // Sonnenaufgang h
4
            SAG_Min,        // Sonnenaufgang min
5
            SUG_Std,        // Sonnenuntergang h
6
            SUG_Min;        // Sonnenuntergang min
7
8
    float   f_SAG,          // Sonnenaufgang float Wert zB 7,32 Uhr
9
            f_SUG,
10
            f_Tagdauer;
11
} sonnenstand_t;
12
13
////////////////////////////////////////////////////////////////////////////////////
14
/*
15
    Funktion:   CalcSonnenAufgang()
16
    Modul   :   rtc_user.c
17
    --------------------------------------------------------------------------------
18
    Beschreibung           : Berechnet den Sonnenaufgang und Untergang (auf 5 Minuten genau)
19
20
    Zeitgleichung:          WOZ - MOZ = -0.171*sin(0.0337 * T + 0.465) - 0.1299*sin(0.01787 * T - 0.168)
21
                            Deklination = 0.4095*sin(0.016906*(T-80.086))
22
                            Zeitdifferenz = 12*arccos((sin(h) - sin(B)*sin(Deklination)) / (cos(B)*cos(Deklination)))/pi;
23
                            Sonnenaufgang h=-50 Bogenminuten = -0.0145
24
25
                            Aufgang Ortszeit = 12 - Zeitdifferenz - Zeitgleichung
26
                            Untergang Ortszeit = 12 + Zeitdifferenz - Zeitgleichung
27
28
                            Aufgang = Aufgang Ortszeit - geographische Länge /15 + Zeitzone
29
                            Untergang = Untergang Ortszeit - geographische Länge /15 + Zeitzone
30
31
    aufgerufene Funktionen  : CalcDayOfYear(ptr);
32
                              IsSommerzeit();
33
    Eingabeparameter        : ptr           (Zeiger auf aktuelle Zeit für Sommerzeit)
34
                              sonne         (Zeiger auf Ergebnisstruktur
35
                              T             (Tag des Jahres)
36
    Rückgabe                : -
37
    veränderte Globals      : SAG_Std,SAG_Min, SUG_Std,SUG_Min
38
39
*/
40
////////////////////////////////////////////////////////////////////////////////////
41
42
43
uint8_t CalcSonnenAufgang(TM_RTC_Time_t *ptr,sonnenstand_t *sonne)
44
{
45
    #define hoehe   -0.0145     // Sonnenhöhe in RAD
46
    #define PI      3.141592654
47
48
    double  B,
49
            Deklination,        // Deklination der Sonne
50
            Zeitdiff,           // Zeitdifferenz
51
            DIFF_WOZ_MOZ,
52
            Aufgang_MOZ,        // Aufgang mittlere Ortzeit
53
            Untergang_MOZ,      // Aufgang mittlere Ortszeit
54
            Aufgang_WOZ,        // Aufgang wahre Ortszeit
55
            Untergang_WOZ;      // Untergang wahre Ortszeit
56
57
58
    uint16_t T;
59
    static  uint16_t oldvalue = 0;
60
61
    // Berechne des Tag des Jahres
62
    T = CalcDayOfYear(ptr);
63
64
    // Prüfen, ob Berechnungen für aktuellen Tag bereits vorliegen
65
    if (oldvalue == T)
66
         return 0;
67
    oldvalue = T;
68
69
    // Berechnungen
70
    B = PI *N_BREITE / 180;
71
    Deklination = 0.4095 * sin(0.016906 * (T-80.086));
72
    Zeitdiff = 12 * acos((sin(hoehe) - sin(B) * sin(Deklination)) / (cos(B) * cos(Deklination))) / PI;
73
    DIFF_WOZ_MOZ = -0.171 * sin(0.0337 * T + 0.465) - 0.1299 * sin(0.01787 * T - 0.168);    // WOZ-MOZ
74
75
    Aufgang_MOZ   = 12 - Zeitdiff - DIFF_WOZ_MOZ;
76
    Untergang_MOZ = 12 + Zeitdiff - DIFF_WOZ_MOZ;
77
78
    Aufgang_WOZ   = Aufgang_MOZ + (15 - O_LAENGE) * (double)4/60;
79
    Untergang_WOZ = Untergang_MOZ + (15 - O_LAENGE) * (double)4/60;
80
81
    // Sommerzeit berücksichtigen
82
    if (IsSommerzeit(ptr)) {
83
        Aufgang_WOZ = Aufgang_WOZ + 1;
84
        Untergang_WOZ = Untergang_WOZ + 1;
85
    }
86
87
    // globale double Werte setzen
88
    sonne->f_SAG = Aufgang_WOZ;
89
    sonne->f_SUG = Untergang_WOZ;
90
    sonne->f_Tagdauer = sonne->f_SUG - sonne->f_SAG;
91
92
    // Umrechnung in Stunden/Minuten
93
    sonne->SAG_Std = floor(Aufgang_WOZ);                    // Sonnenaufgang
94
    sonne->SAG_Min = (Aufgang_WOZ - (float)sonne->SAG_Std) * 60;
95
96
    sonne->SUG_Std = ceil(Untergang_WOZ)-1;             // Sonnenuntergang
97
    sonne->SUG_Min = (Untergang_WOZ - (double)sonne->SUG_Std) * 60;
98
99
    return 1;
100
}

von Jacko (Gast)


Lesenswert?

Selbst in der Zeitrechnung kommt Mist heraus, wenn man
amerikanische Maßeinheiten und Konventionen benutzt!

Mit feet/meter-Problemen wurden vielversprechende, teure
Sonden in den Marsboden gerammt.

Und mit tm_wday beginnt die Woche am Sonntag, womit du in
Europa keinen Blumentopf gewinnen kannst, weil da ISO-8601
den Montag als Wochenanfang vorgibt.

Ist doch auch logisch: Sag mal die Wochentage auf:
Selbst im hintersten Kentucky fängt dabei jeder mit
"Monday" an.

Make REASON great again!

von Marc V. (Firma: Vescomp) (logarithmus)


Lesenswert?

Jacko schrieb:
> Und mit tm_wday beginnt die Woche am Sonntag, womit du in
> Europa keinen Blumentopf gewinnen kannst, weil da ISO-8601
> den Montag als Wochenanfang vorgibt.

> Ist doch auch logisch: Sag mal die Wochentage auf:
> Selbst im hintersten Kentucky fängt dabei jeder mit
> "Monday" an.

 Hat doch eher mit der Bibel zu tun:
1
Am siebten Tag vollendete Gott das Werk, das er geschaffen hatte, und an diesem Tag ruhte er

: Bearbeitet durch User
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.