2012-03-05 10 views
6

Leo en dos cadenas con un año, el día juliano (día del año), hora, minuto y una observación.¿Por qué mktime() cambia el día del año de mi tm struct?

me tire de las variables relevantes a cabo utilizando sscanf:

sscanf(tide_str1.c_str(), "%d %d %d %d %Lf", &y1, &j1, &h1, &m1, &obs1); 
sscanf(tide_str2.c_str(), "%d %d %d %d %Lf", &y2, &j2, &h2, &m2, &obs2); 

Para este conjunto de datos en particular, los valores son 2011 083 23 22 1.1

entonces crear y rellenar una estructura tm, y corro mktime , con cout pide a los días en el medio y que cambia de 083 a 364.

int y1=2011, j1=83, h1=23, m1=22; 
struct tm time_struct = {0, 0, 0, 0, 0, 0, 0, 0, 0}, *time_ptr = &time_struct; 
time_t tv_min; 
time_struct.tm_year = y1 - 1900; 
time_struct.tm_yday = j1; 
cout << time_struct.tm_yday << endl; 
time_struct.tm_hour = h1; 
time_struct.tm_min = m1; 
time_struct.tm_isdst = -1; 
cout << time_struct.tm_yday << endl; 
tv_min = mktime(time_ptr); 
cout << time_struct.tm_yday << endl; 

¿por qué? ¿Es porque tm_mday yy tm_mon están establecidos en 0? Intenté inicialmente no inicializarlo todo a cero, pero luego mktime devolvió -1. ¿Qué debería hacer diferente si solo sé el día del año y no el mes y el día del mes?

+0

El día del año es a veces incorrectamente * * se refiere como un "Día Juliano". De hecho, un número [Julian Day] (http://en.wikipedia.org/wiki/Julian_day) es el número de días desde el 1 de enero de 4713 aC; se usa en astronomía. –

+0

Sí, pero es tan ampliamente utilizado (incorrectamente) dentro de ciertas profesiones que, en la práctica, es correcto. Mientras todos en un campo usen la misma jerga ... la comunicación ocurre. – RuQu

Respuesta

13

mktime() está haciendo lo que se supone que debe hacer.

Citando el estándar C:

La función mktime convierte el tiempo descompuesto, expresado como hora local, en la estructura apuntada por timeptr en un valor de tiempo de calendario con el La misma codificación que la de los valores devueltos por la función time. Los valores originales de la tm_wday y tm_yday componentes de la estructura son ignorados, y los valores originales de los otros componentes no se restringen a los rangos indicados anteriormente. Al finalizar con éxito, los valores de la tm_wday y tm_yday componentes de la estructura se establecen apropiadamente, y los otros componentes están configurados para representar la tiempo de calendario especificado, pero con sus valores forzados a los rangos indicados anteriormente; el valor final de tm_mday no se establece hasta tm_mon y tm_year se determinan.

mktime() puede compute los valores de tm_mday y tm_yday de otros miembros; no está diseñado para calcular los valores de otros miembros de esos campos.

Lo que puede hacer, sin embargo, es inicializar un struct tm con valores fuera de rango. Por ejemplo, si quiere que tm_yday sea 200 (el día 200 del año), puede inicializar un struct tm que representa el día 200 de enero. mktime() lo normalizará a la fecha correcta, obteniendo un valor de time_t que luego puede alimentar a gmtime() o localtime().

Aquí está un ejemplo sencillo:

#include <iostream> 
#include <ctime> 

int main() 
{ 
    struct tm t = { 0 }; 
    t.tm_sec = t.tm_min = t.tm_hour = 0; // midnight 
    t.tm_mon = 0;      // January 
    t.tm_year = 2012 - 1900; 
    t.tm_isdst = -1;      // unknown 

    t.tm_mday = 200;      // January 200th? 

    time_t when = mktime(&t); 
    const struct tm *norm = localtime(&when); // Normalized time 

    std::cout << "month=" << norm->tm_mon << ", day=" << norm->tm_mday << "\n"; 
    std::cout << "The 200th day of 2012 starts " << asctime(norm); 
} 

La salida es:

month=6, day=18 
The 200th day of 2012 starts Wed Jul 18 00:00:00 2012 
+0

Probé su consejo y lo inicialicé así: struct tm time_struct = {0, 0, 0, 200, 200, 0, 200, 0, 0} y el resultado cuando lo devolví fue el día 77 cuando debería ser 83, que está más cerca que el 364 de antes pero aún apagado. – RuQu

+1

La norma no garantiza el orden de los miembros de 'struct tm', por lo que su inicialización no necesariamente funcionará. Debe inicializar o asignar todos los miembros por su nombre. Pero si se declaran en el orden habitual, estás inicializando 'tm_mday' y' tm_mon' en 200. No creo que quieras el 200º, o más bien el 201º, mes del año. (Y no olvide que 'struct tm' numera los meses 0 a 11, no 1 a 12.) –

+0

Para ser claro, si quiero el día 83, debería establecer el mes en 0, y el día del mes en 83? – RuQu

Cuestiones relacionadas