Pregunta

Esto parece como algo que nadie debería tener que hacer, pero estoy trabajando en un módulo del núcleo de un sistema embebido (OpenWRT) en la que parece que time.h hace incluyen la timespec y time_t tipos y las funciones clock_gettime y gmtime, pero lo hace no incluir localtime, ctime, time, o, de manera crítica, el tipo tm.

Cuando intento del puntero de retorno desde gmtime a mi propia estructura, aparece un error de segmentación.

Así que supongo que estaría contenido para resolver el problema de dos maneras-it'd ser grande para encontrar la manera de obtener acceso a ese tipo de falta, o, alternativamente, cómo rodar mi propio método para descomponer un UNIX marca de tiempo.

¿Fue útil?

Solución

Esto debe ser preciso (rellena una imitación reducida de un struct tm, mi year utiliza era común en lugar de una época 1900 DC):

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

Mis disculpas por todos los números mágicos. * 367 meses / 12 es un buen truco para generar la secuencia de 30/31 días del calendario. El cálculo trabaja con años que se inician en marzo hasta la corrección al final, lo que facilita las cosas porque entonces el día de salto cae al final de un "año".

Otros consejos

En el espacio de usuario glibc va a hacer un montón de trabajo en relación con el manejo de la parte "local" de la representación del tiempo. Dentro del núcleo no está disponible. Probablemente usted no debe tratar de molestar con esto dentro de su módulo, si es necesario hacerlo en el espacio de usuario.

A time_t es el número de segundos desde ene 1, 1970 UTC de modo que en descomposición en el mes, día y año no es tan difícil siempre y cuando se desea que el resultado en UTC. Hay una de fuente disponible buscando en Google "fuente gmtime". La mayoría de sistemas embebidos dejar de lado el procesamiento, hora local, ya que es un poco más difícil debido a la dependencia de la configuración de zona horaria y el medio ambiente.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top