2
0
mirror of https://github.com/boostorg/build.git synced 2026-02-14 12:42:11 +00:00

Corrected Boost Jam's Windows FILETIME to POSIX time_t conversion. New implementation lifted shamelessly from the CPython implementation. The old implementation did not work correctly in all cases depending on the user's regional (timezone & daylight saving time) settings as well as the TZ environment variable (affects some C runtime library routines). It also used the double type to represent some interim values during its calculation - sometimes causing off-by-one rounding errors.

[SVN r79494]
This commit is contained in:
Jurko Gospodnetić
2012-07-14 11:42:58 +00:00
parent 743cc7ed4b
commit 8e716991c8

View File

@@ -688,35 +688,29 @@ static double filetime_seconds( FILETIME const t )
/*
* filetime_dt() - Windows FILETIME --> POSIX time_t conversion
*
* What should be a simple conversion, turns out to be horribly complicated by
* the defficiencies of MSVC and the Win32 API.
* Lifted shamelessly from the CPython implementation.
*/
static time_t filetime_dt( FILETIME const t_utc )
static time_t filetime_dt( FILETIME const ft )
{
static int calc_time_diff = 1;
static double time_diff;
if ( calc_time_diff )
{
struct tm t0_;
FILETIME f0_local;
FILETIME f0_;
SYSTEMTIME s0_;
GetSystemTime( &s0_ );
t0_.tm_year = s0_.wYear - 1900;
t0_.tm_mon = s0_.wMonth - 1;
t0_.tm_wday = s0_.wDayOfWeek;
t0_.tm_mday = s0_.wDay;
t0_.tm_hour = s0_.wHour;
t0_.tm_min = s0_.wMinute;
t0_.tm_sec = s0_.wSecond;
t0_.tm_isdst = 0;
SystemTimeToFileTime( &s0_, &f0_local );
LocalFileTimeToFileTime( &f0_local, &f0_ );
time_diff = filetime_seconds( f0_ ) - (double)mktime( &t0_ );
calc_time_diff = 0;
}
return ceil( filetime_seconds( t_utc ) - time_diff );
/* Seconds between 1.1.1601 and 1.1.1970 */
static __int64 const secs_between_epochs = 11644473600;
/* We can not simply cast and dereference a FILETIME, since it might not be
* aligned properly. __int64 type variables are expected to be aligned to an
* 8 byte boundary while FILETIME structures may be aligned to any 4 byte
* boundary. Using an incorrectly aligned __int64 variable may cause a
* performance penalty on some platforms or even exceptions on others
* (documented on MSDN).
*/
__int64 in;
memcpy( &in, &ft, sizeof( in ) );
/* FILETIME resolution: 100ns. */
/* For resolutions finer than 1 second use the following:
* nsec = (int)( in % 10000000 ) * 100;
*/
return (time_t)( ( in / 10000000 ) - secs_between_epochs );
}