Zeit und Datum aus Unix-Zeit, schlanker Code gesucht;

#2669194
Lesenswert?

So (uint32_t sec ist die Sekunden seit 1.Januar FIRSTYEAR, FIRSTDAY 
selbiger Wochentag):
1
#define FIRSTYEAR       1970
2
#define FIRSTDAY        4                       // 0 = Sunday
3

4
struct time {
5
  uint8_t  second;
6
  uint8_t  minute;
7
  uint8_t  hour;
8
  uint8_t  day;
9
  uint8_t  month;
10
  uint16_t year;
11
  uint8_t  wday;
12
};
13

14
/* Definitions */
15
const uint8_t DayOfMonth[] PROGMEM = { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
16

17
#define getMonthLen(a)  pgm_read_byte(&(DayOfMonth[(a)]))
18

19
void gettime( uint32_t sec, struct time *t )
20
{
21
    uint16_t day;
22
    uint8_t  year;
23
    uint16_t dayofyear;
24
    uint8_t  leap400;
25
    uint8_t  month;
26

27
    t->second = sec % 60;
28
    sec      /= 60;
29
    t->minute = sec % 60;
30
    sec      /= 60;
31
    t->hour   = sec % 24;
32
    day       = sec / 24;
33
    t->wday = (day + FIRSTDAY) % 7;             // weekday
34

35
    year = FIRSTYEAR % 100;                     // 0..99
36
    leap400 = 4 - ((FIRSTYEAR - 1) / 100 & 3);  // 4, 3, 2, 1
37

38
    for(;;)
39
    {
40
        dayofyear = 365;
41
        if( (year & 3) == 0 )
42
        {
43
            dayofyear = 366;                    // leap year
44
            if( year == 0 || year == 100 || year == 200 ) // 100 year exception
45
                if( --leap400 )                 // 400 year exception
46
                    dayofyear = 365;
47
        }
48
        if( day < dayofyear )
49
            break;
50
        day -= dayofyear;
51
        year++;                                 // 00..136 / 99..235
52
    }
53
    t->year = year + (int)(FIRSTYEAR / 100) * 100;     // + century
54

55
    if( dayofyear & 1 && day > 58 )             // no leap year and after 28.2.
56
        day++;                                  // skip 29.2.
57

58
    for( month = 1; day >= getMonthLen(month-1); month++ )
59
        day -= getMonthLen(month-1);
60

61
    t->month = month;                           // 1..12
62
    t->day   = day + 1;                         // 1..31
63
}
Gast #2673877
Lesenswert?

Erst mal danke für den Code, beim Compilieren mit dem MSPGCC werden aber 
folgende Fehlermeldungen ausgespuckt (wgen der Zeile 79 bei der 
Übernahme in meinen Code) :

[Zeile 79] const uint8_t DayOfMonth[] PROGMEM = { 31, 29, 31, 30, 31, 
30, 31, 31, 30, 31, 30, 31 };
[Zeile 80] #define getMonthLen(a)  (pgm_read_byte(&(DayOfMonth[(a)])))

mod_time01.c:79: syntax error before "PROGMEM"
mod_time01.c:79: warning: excess elements in scalar initializer
mod_time01.c:79: warning: (near initialization for `PROGMEM')
mod_time01.c:79: warning: excess elements in scalar initializer
mod_time01.c:79: warning: (near initialization for `PROGMEM')
mod_time01.c:79: warning: excess elements in scalar initializer
mod_time01.c:79: warning: (near initialization for `PROGMEM')
mod_time01.c:79: warning: excess elements in scalar initializer
mod_time01.c:79: warning: (near initialization for `PROGMEM')
mod_time01.c:79: warning: excess elements in scalar initializer
mod_time01.c:79: warning: (near initialization for `PROGMEM')
mod_time01.c:79: warning: excess elements in scalar initializer
mod_time01.c:79: warning: (near initialization for `PROGMEM')
mod_time01.c:79: warning: excess elements in scalar initializer
mod_time01.c:79: warning: (near initialization for `PROGMEM')
mod_time01.c:79: warning: excess elements in scalar initializer
mod_time01.c:79: warning: (near initialization for `PROGMEM')
mod_time01.c:79: warning: excess elements in scalar initializer
mod_time01.c:79: warning: (near initialization for `PROGMEM')
mod_time01.c:79: warning: excess elements in scalar initializer
mod_time01.c:79: warning: (near initialization for `PROGMEM')
mod_time01.c:79: warning: excess elements in scalar initializer
mod_time01.c:79: warning: (near initialization for `PROGMEM')
mod_time01.c:79: warning: data definition has no type or storage class
Gast #2673895
Lesenswert?

Entferne PROGMEM.
Entferne pgm_read_byte(& und natürlich die schließende Klammer

Die Begriffe sorgen beim AVR dafür, dass die Tabellen im Flash 
abgespeichert werden, Stichwort Harvard-Struktur.

Ohne Begriffe funktioniert es auch, es kann sein, dass die Daten dann im 
RAM abgelegt werden (weiß nicht wie das der MSPGCC macht).
Gast #2673898
Lesenswert?

Ok, jetzt habe ich "PROGMEM" weggelassen, dann wird der Code compiliert, 
aber beim Linken wird noch dieser Fehler angezeigt :

mod_time01.o: In function `gettime':
mod_time01.c:(.text+0x24a): undefined reference to `pgm_read_byte'
mod_time01.c:(.text+0x254): undefined reference to `pgm_read_byte'
c:\mspgcc\bin\make.exe: *** [main_F24x_SIM900_test01.elf] Error 1

Wahrscheinlich ist "pgm_read_byte" beim AVR auch irgendwo definiert ?

P.S. Wozu ist "PROGMEM" beim AVR gut ?
Persönliche Seite #2673900
Lesenswert?

Floh schrieb:
> Entferne pgm_read_byte(& und natürlich die schließende Klammer

anfaenger schrieb:
> P.S. Wozu ist "PROGMEM" beim AVR gut ?

Augen auf?
Floh schrieb:
> Die Begriffe sorgen beim AVR dafür, dass die Tabellen im Flash
> abgespeichert werden, Stichwort Harvard-Struktur.
>
> Ohne Begriffe funktioniert es auch, es kann sein, dass die Daten dann im
> RAM abgelegt werden (weiß nicht wie das der MSPGCC macht).

Google kaputt?
http://www.nongnu.org/avr-libc/user-manual/group__avr__pgmspace.html
#2673911
Lesenswert?

anfaenger schrieb:
> @Floh und Bernhard : Danke, unsere Posts haben sich überschnitten jetzt
> schluckt der Compiler den Code.
> Mal sehen, ob auch das korrekte Datum berechnet wird.

sollte schon...ich kann das Sourcefile, aus dem der code ist auch auf 
Unix übersetzen, und da kommt das richtige raus... (natürlich nicht bei 
negativen Zahlen, Unix setzt negative time_t Zeiten in vor-1970 um, mein 
Code arbeitet mit unsigned und geht deshalb weiter als bis 2038...)
Gast #2673952
Lesenswert?

Echt klasse !
Damit hat sich auch das NTP-Problem aus diesem Thread erledigt : 
Beitrag "Zeit von ntp-Server abrufen;"

Für die Unix-Zeit 1336550777 liefert der Code von Bernhard den korrekten 
UTC Datum/Zeit-Wert 20120509 08:06:17 (JJJJMMTT HH:MM:SS)

Ich war schon ziemlich genervt, weil die Zeiten eines ntp-Servers ja 
prinzipiell im UTC-Format übermittelt werden sollten, mir dieser Link 
http://www.aritso.net/aritso-tools/timestampconverter/ aus dem 
Unix-Zeitwert aber immer UTC+1 (=MEZ) berechnet hat (auch wenn UTC 
vorgegeben war)
Das Ergebnis lautet z.B. für die oben verwendete Unix-Zeit
"Der Timestamp 1336550777 entspricht dem 09.05.2012 um 09:06:17 Uhr. 
(gilt für UTC 0)"

THX !

P.S. @Simon K. : Kein Problem, mir war schon klar, dass Du das mit der 
Überschneidung nicht wissen konntest.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren