Retrouver gettimeofday dans Windows
Windows n'offre pas la fonction gettimeofday si chère aux programmeurs ayant pris leurs habitudes avec les systèmes d'exploitation UNIX. En outre, Windows ne compte pas le temps à partir de la même date de référence que les systèmes UNIX. L'epoch utilisé par Windows est le premier janvier 1601 alors que sous les systèmes UNIX il s'agit plutôt du premier janvier 1970.
Il est toutefois possible de trouver sur MSDN une fonction, manquant lamentablement de commentaires, qui permet de convertir un time_t de la librairie standard du C défini en fonction de l'epoch UNIX en un FILETIME défini en fonction de l'epoch Windows. Le code de cette fonction est reproduit ci-dessous.
#include <windows.h>
#include <time.h>
void TimetToFileTime( time_t t, LPFILETIME pft )
{
LONGLONG ll = Int32x32To64(t, 10000000) + 116444736000000000;
pft->dwLowDateTime = (DWORD) ll;
pft->dwHighDateTime = ll >>32;
}
Quelques opérations arithmétiques révèlent bien vite la logique derrière cette fonction.
116444736000000000 / 10 = 11644473600000000 microsecondes 11644473600000000 / 1000 = 11644473600000 millisecondes 11644473600 / 1000 = 11644473600 secondes 11644473600 / 60 = 194074560 minutes 194074560 / 60 = 3234576.0 heures 3234576 / 24 = 134774.0 jours 134774 / 365 = 369.2 années
En effet, la différence entre les années 1970 et 1601 est bien de 369 ans et des poussières.
Implanter gettimeofday sous Windows consiste donc tout simplement à effectuer le chemin inverse de la fonction TimetToFileTime. C'est-à-dire que 369 ans doivent être retranchés à la valeur retournée par la fonction GetSystemTimeAsFileTime.
#include <windows.h>
int _gettimeofday(struct timeval* p, void* tz) {
ULARGE_INTEGER ul; // As specified on MSDN.
FILETIME ft;
// Returns a 64-bit value representing the number of
// 100-nanosecond intervals since January 1, 1601 (UTC).
GetSystemTimeAsFileTime(&ft);
// Fill ULARGE_INTEGER low and high parts.
ul.LowPart = ft.dwLowDateTime;
ul.HighPart = ft.dwHighDateTime;
// Convert to microseconds.
ul.QuadPart /= 10ULL;
// Remove Windows to UNIX Epoch delta.
ul.QuadPart -= 11644473600000000ULL;
// Modulo to retrieve the microseconds.
p->tv_usec = (long) (ul.QuadPart % 1000000LL);
// Divide to retrieve the seconds.
p->tv_sec = (long) (ul.QuadPart / 1000000LL);
return 0;
}
Quelques références utiles: