2009-11-07 29 views
17

Lo que quiero hacer es convertir un tiempo de época (segundos desde la medianoche del 1/1/1970) al tiempo "real" (m/d/yh: m: s)Conversión del tiempo de época a "fecha/hora" real

hasta ahora, tengo el siguiente algoritmo, lo que a mí se siente un poco feo:

void DateTime::splitTicks(time_t time) { 
    seconds = time % 60; 
    time /= 60; 
    minutes = time % 60; 
    time /= 60; 
    hours = time % 24; 
    time /= 24; 

    year = DateTime::reduceDaysToYear(time); 
    month = DateTime::reduceDaysToMonths(time,year); 
    day = int(time); 
} 

int DateTime::reduceDaysToYear(time_t &days) { 
    int year; 
    for (year=1970;days>daysInYear(year);year++) { 
     days -= daysInYear(year); 
    } 
    return year; 
} 

int DateTime::reduceDaysToMonths(time_t &days,int year) { 
    int month; 
    for (month=0;days>daysInMonth(month,year);month++) 
     days -= daysInMonth(month,year); 
    return month; 
} 

se puede asumir que los miembros seconds, minutes, hours, month, day y year toda existen.

Usando los bucles for para modificar el tiempo original se siente un poco apagado, y me preguntaba si hay una solución "mejor" para esto.

+1

OK, entonces sé que está buscando una solución de procedimiento ... pero si aún no lo ha visto, visite http://www.epochconverter.com. Es una forma muy útil de verificar tu trabajo :) – Tom

+0

¿Qué hay de malo con solo llamar a esta funcionalidad expuesta por 'time.h', p. por [gmtime] (http: //www.cplusplus.com/reference/clibrary/ctime/gmtime /) si GMT en lugar de una zona horaria específica es lo que buscas? –

+0

No tiene nada de malo, ni siquiera sabía que existía. ¡Gracias! Pero, todavía estoy interesado en saber cómo mi implementación podría ser mejor. –

Respuesta

17

Tenga cuidado con los años bisiestos en sus días Función InMthth.

Si desea un rendimiento muy alto, puede calcular previamente el par para obtener el mes + año en un solo paso, y luego calcular el día/hora/min/seg.

Una buena solución es la de la gmtime source code:

/* 
* gmtime - convert the calendar time into broken down time 
*/ 
/* $Header: gmtime.c,v 1.4 91/04/22 13:20:27 ceriel Exp $ */ 

#include  <time.h> 
#include  <limits.h> 
#include  "loc_time.h" 

struct tm * 
gmtime(register const time_t *timer) 
{ 
     static struct tm br_time; 
     register struct tm *timep = &br_time; 
     time_t time = *timer; 
     register unsigned long dayclock, dayno; 
     int year = EPOCH_YR; 

     dayclock = (unsigned long)time % SECS_DAY; 
     dayno = (unsigned long)time/SECS_DAY; 

     timep->tm_sec = dayclock % 60; 
     timep->tm_min = (dayclock % 3600)/60; 
     timep->tm_hour = dayclock/3600; 
     timep->tm_wday = (dayno + 4) % 7;  /* day 0 was a thursday */ 
     while (dayno >= YEARSIZE(year)) { 
       dayno -= YEARSIZE(year); 
       year++; 
     } 
     timep->tm_year = year - YEAR0; 
     timep->tm_yday = dayno; 
     timep->tm_mon = 0; 
     while (dayno >= _ytab[LEAPYEAR(year)][timep->tm_mon]) { 
       dayno -= _ytab[LEAPYEAR(year)][timep->tm_mon]; 
       timep->tm_mon++; 
     } 
     timep->tm_mday = dayno + 1; 
     timep->tm_isdst = 0; 

     return timep; 
} 
+0

Aquí hay un enlace actualizado a la fuente completa: http: //www.cise .ufl.edu/~ cop4600/cgi-bin/lxr/http/source.cgi/lib/ansi/gmtime.c –

11

La biblioteca estándar proporciona funciones para hacer esto. gmtime() o localtime() convertirá un time_t (segundos desde la época) en una estructura tm. strftime() puede usarse para convertir una struct tm en una cadena en función del formato que especifique.

ver: cálculos http://www.cplusplus.com/reference/clibrary/ctime/

fecha/hora puede ser complicado. Es mucho mejor que uses una solución existente en lugar de intentar hacer la tuya, a menos que tengas una buena razón.

+3

Esto comenzó como tarea hace un tiempo, pero ahora estoy interesado en hacerlo mejor. Normalmente, elegiría la solución de la biblioteca, pero 1) No sabía en qué momento se integraron las funciones y 2) deseo perfeccionar mi implementación. –

0

Si su tipo de hora original es time_t, tiene que usar funciones de time.h, es decir, gmtime, etc. para obtener un código portátil. Los estándares de C/C++ no especifican el formato interno (o incluso el tipo exacto) para time_t, por lo que no puede convertir o manipular directamente los valores de time_t.

Todo lo que se sabe es que time_t es "tipo aritmético", pero los resultados de las operaciones aritméticas no están especificados; ni siquiera puede sumar/restar de manera confiable. En la práctica, muchos sistemas usan el tipo entero para time_t con formato interno de segundos desde epoch, pero esto no se aplica por estándares.

En resumen, use gmtime (y la funcionalidad time.h en general).

2

Una manera fácil (aunque diferente que el formato que quería):

std::time_t result = std::time(nullptr); 
std::cout << std::asctime(std::localtime(&result)); 

Salida: Mié Sep 21 10:27:52 2011

en cuenta que el resultado devuelto se concatena automáticamente "\ n" .. puede eliminarla usando:

std::string::size_type i = res.find("\n"); 
if (i != std::string::npos) 
    res.erase(i, res.length()); 

Tomado de: http://en.cppreference.com/w/cpp/chrono/c/time

Cuestiones relacionadas