Frage

Das ist wie etwas scheint niemand sollte jemals zu tun haben, aber ich arbeite an einem Kernel-Modul für ein eingebettetes System (OpenWRT), in dem es, dass time.h scheint hat gehören die timespec und time_t Typen und die clock_gettime und gmtime Funktionen, aber tut nicht ist localtime, ctime, time, oder, kritisch, die tm Art.

Wenn ich den Schleppzeiger von gmtime auf meine eigene Struktur zu werfen versuchen, erhalte ich eine segfault.

Also ich denke, ich zufrieden sein würde, das Problem entweder von zwei zu lösen Wege-it'd groß sein, um herauszufinden, wie der Zugang zu diesem fehlenden Typ zu erhalten, oder alternativ, wie meine eigene Methode rollen einen Unix zum Zerlegen Zeitstempel.

War es hilfreich?

Lösung

Dies sollte genau sein (füllt eine abgespeckte Imitation eines struct tm, mein year verwendet Common Era statt einer 1900 CE-Epoche):

struct xtm
{
    unsigned int year, mon, day, hour, min, sec;
};

#define YEAR_TO_DAYS(y) ((y)*365 + (y)/4 - (y)/100 + (y)/400)

void untime(unsigned long unixtime, struct xtm *tm)
{
    /* First take out the hour/minutes/seconds - this part is easy. */

    tm->sec = unixtime % 60;
    unixtime /= 60;

    tm->min = unixtime % 60;
    unixtime /= 60;

    tm->hour = unixtime % 24;
    unixtime /= 24;

    /* unixtime is now days since 01/01/1970 UTC
     * Rebaseline to the Common Era */

    unixtime += 719499;

    /* Roll forward looking for the year.  This could be done more efficiently
     * but this will do.  We have to start at 1969 because the year we calculate here
     * runs from March - so January and February 1970 will come out as 1969 here.
     */
    for (tm->year = 1969; unixtime > YEAR_TO_DAYS(tm->year + 1) + 30; tm->year++)
        ;

    /* OK we have our "year", so subtract off the days accounted for by full years. */
    unixtime -= YEAR_TO_DAYS(tm->year);

    /* unixtime is now number of days we are into the year (remembering that March 1
     * is the first day of the "year" still). */

    /* Roll forward looking for the month.  1 = March through to 12 = February. */
    for (tm->mon = 1; tm->mon < 12 && unixtime > 367*(tm->mon+1)/12; tm->mon++)
        ;

    /* Subtract off the days accounted for by full months */
    unixtime -= 367*tm->mon/12;

    /* unixtime is now number of days we are into the month */

    /* Adjust the month/year so that 1 = January, and years start where we
     * usually expect them to. */
    tm->mon += 2;
    if (tm->mon > 12)
    {
        tm->mon -= 12;
        tm->year++;
    }

    tm->day = unixtime;
}

Ich entschuldige mich für alle magischen Zahlen. 367 * Monat / 12 ist ein netter Trick der 30/31 Tag-Sequenz des Kalenders zu erzeugen. Die Berechnung arbeitet mit den Jahren, die im März bis zum fixup am Ende beginnen, die Dinge einfach macht, weil dann der Schalttag am Ende eines „Jahres“ fällt.

Andere Tipps

In User-Space glibc wird viel Arbeit in Bezug tut Darstellung den „lokalen“ Teil der Zeit zu handhaben. Im Kern ist dies nicht verfügbar ist. Wahrscheinlich versuchen Sie sollten nicht mit diesem in Ihrem Modul zu stören, wenn nötig tun es in User-Space.

A time_t ist die Anzahl der Sekunden seit dem 1. Januar 1970 UTC zersetzen, so dass in Monat, Tag und Jahr ist nicht so schwierig, vorausgesetzt, dass Sie das Ergebnis in UTC mögen. Es gibt eine Haufen Quelle verfügbar rel="nofollow durch Googeln "gmtime Quelle" . Die meisten Embedded-Systeme auslassen Ortszeit Verarbeitung, da es ein wenig schwieriger, aufgrund der Abhängigkeit von Zeitzone-Einstellung und die Umwelt ist.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top