2012-08-25 5 views
9

Estoy ejecutando el código siguiente.Comportamiento confuso de la función mktime(): aumentando tm_hour count por uno

int main() 
{ 
struct tm storage={0,0,0,0,0,0,0,0,0}; 
char *p = NULL; 
p = (char *)strptime("2012-08-25 12:23:12","%Y-%m-%d %H:%M:%S",&storage); 
char buff[1024]={0}; 
strftime(buff,1024,"%Y-%m-%d %H:%M:%S",&storage); 
cout << buff << endl; 
storage.tm_sec += 20; 
strftime(buff,1024,"%Y-%m-%d %H:%M:%S",&storage); 
cout << buff << endl; 
mktime(&storage); 
strftime(buff,1024,"%Y-%m-%d %H:%M:%S",&storage); 
cout << buff << endl; 
return 0; 
} 

si el programa anterior ejecutado, imprime '2012-08-25 13:23:32' en lugar de '2012-08-25 12:23:32'. Ayuda, por qué aumenta el valor de tm_hour. Esto funciona correctamente si pongo la fecha de entrada como '2012-02-25 12:23:32' en el programa, lo cual es confuso.

de salida ->

[[email protected] root]$ ./a.out 
2012-08-25 12:23:12 
2012-08-25 12:23:32 
2012-08-25 13:23:32 
[[email protected] root]$ 

Información Fecha en mi sistema, ->

[[email protected] root]$ date 
Sat Aug 25 08:28:26 EDT 2012 
+0

El código no indica que la hora va en aumento.Para hacerlo, muestre el resultado que vino de 'strptime' así como el resultado que vino de la llamada a' mktime'. Eso ayudará a precisar lo que está sucediendo realmente. –

+0

Lo siento, no puedo analizar eso. Tiene tres salidas en lugar de una, pero no indica de dónde vienen. Actualice el código de muestra para que coincida con la salida. –

Respuesta

11

Lo que sucede

La fecha que ha especificado tiene horario de verano en efecto, pero al llamar mktime, storage.tm_isdst es cero. mktime ve esto y piensa "hey, me dieron una fecha con una bandera de ahorro de luz diurna incorrecta, vamos a arreglarlo". Luego establece tm_isdst en 1 y cambia tm_hour.

Véase también this answer.

solucionarlo

  • uso timegm en lugar de mktime
  • establecer la zona horaria a UTC antes de llamar mktime (véase también el ejemplo de timegm):
    setenv("TZ", "", 1); 
    tzset(); 
    mktime();
  • utilizar un buen fecha- biblioteca de tiempo (como boost::locale::date_time/boost::date_time, pero lea la sección de Q &) en la página boost::locale::date_time antes de elegir uno)
+1

Gracias, me ayudó y me explicó mi duda. Ahora necesito ejecutar mi código en ambos tipos de sistema (DST encendido y apagado). p.ej. Si pongo tm_isdst = 1 en el código antes de llamar a mktime(), dará un resultado incorrecto en el sistema donde DST está desactivado (terminará disminuyendo tm_hour en uno). ¿Hay alguna otra forma de agregar segundos a una fecha determinada? (Puede ser "evitar el uso de mktime()" o "hacer un uso inteligente de mktime() que ignorará el indicador tm_isdst") –

+0

@DhirajNeve: Agregué un par de correcciones. Si necesita hacer más cosas relacionadas con la fecha/hora, creo que debería usar una buena biblioteca de fecha/hora en C++. – rve

+0

¿No es 'timegm' POSIX solamente? – stackptr

4

Vaya, ahí sólo hay manera de evitarlo. Debe ser un error en la implementación de tu sistema de mktime (3). mktime (3) no debe alterar el struct tm * que le haya sido transferido.

Sugeriría que se compruebe el valor de storage.tm_isdst. Intente configurarlo en 0 para asegurarse de que no se confunda con el horario de verano. Si eso no funciona, intente configurarlo en -1 para permitir que determine automáticamente el valor correcto.

mktime - convert broken-down time into time since the Epoch

un valor positivo o 0 para tm_isdst provoca mktime() para presumir inicialmente que el horario de verano, respectivamente, es o no es, en efecto, durante el tiempo especificado. Un valor negativo para tm_isdst hace que mktime() intente determinar si el horario de verano está vigente durante el tiempo especificado.


estaba equivocada mktime (3) no modificar struct tm *. Es el comportamiento correcto para normalizar el valor.

+0

De acuerdo con 'man mktime' (http://linux.die.net/man/3/mktime) puede (y lo hace) alterar' stuct tm'. Normaliza sus valores y completa los campos faltantes. – rve

+0

@rve parece que tienes razón. Me malinterpretaron la redacción. Pensé que se estaba normalizando para el propósito de establecer time_t. –

+0

Sí, la implementación es incorrecta ... –

Cuestiones relacionadas