Question

Cela semble être quelque chose que personne ne devrait jamais avoir à faire, mais je travaille sur un module de noyau pour un système embarqué (OpenWRT) dans lequel il semble que time.h Finalité comprennent la timespec et time_t types et les fonctions de clock_gettime et gmtime, mais ne pas inclure localtime, ctime, time, ou, de façon critique, le type de tm.

Lorsque je tente de lancer le pointeur de retour de gmtime à mon propre struct, je reçois une erreur de segmentation.

Je suppose que je serais contente de résoudre le problème de deux façons-it'd être grand pour savoir comment obtenir l'accès à ce type manquant, ou encore, comment rouler ma propre méthode pour décomposer un unix horodatage.

Était-ce utile?

La solution

Ce doit être précis (remplit une imitation dénudation d'un struct tm, mon year utilise notre ère au lieu d'une époque 1900 CE):

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;
}

Mes excuses pour tous les numéros magiques. 367 * mois / 12 est une astuce pour générer la séquence 30/31 de jour du calendrier. Le calcul fonctionne avec les années qui commencent dans Mars jusqu'à la fixup à la fin, ce qui rend les choses faciles car alors le jour de saut tombe à la fin d'une « année ».

Autres conseils

Dans la glibc userspace fera beaucoup de travail en ce qui concerne la manipulation de la part de la représentation du temps « local ». Au sein du noyau ce n'est pas disponible. Probablement vous ne devriez pas essayer de se soucier de cela dans votre module, le cas échéant le faire dans l'espace utilisateur.

A time_t est le nombre de secondes écoulées depuis le 1 janvier 1970 UTC alors que décomposait en mois, le jour et l'année n'est pas difficile à condition que vous voulez que le résultat en UTC. Il y a un de source disponible par googler "source gmtime" . La plupart des systèmes embarqués quittent un traitement heure locale car il est un peu plus difficile en raison de la dépendance à l'égard du fuseau horaire et réglage de l'environnement.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top