Mercurial > libpst
view src/timeconv.c @ 46:b2a7f2e0926a
more fixes for 64 bit format
author | carl |
---|---|
date | Sat, 12 Jan 2008 15:20:53 -0800 |
parents | c508ee15dfca |
children | 7d5c637aaafb |
line wrap: on
line source
/*********************************************************************** * * Borrowed from WINE sources!! (http://www.winehq.com) * Converts a Win32 FILETIME structure to a UNIX time_t value */ /*** WARNING **** * This file is not to be incluided in a Visual C++ Project * It will make the whole project fail to compile * There are functions in libpst.c to handle the dates * Do not use this one */ #include <time.h> #include "common.h" #include "timeconv.h" char * fileTimeToAscii (const FILETIME *filetime) { time_t t1; t1 = fileTimeToUnixTime(filetime,0); return ctime(&t1); } struct tm * fileTimeToStructTM (const FILETIME *filetime) { time_t t1; t1 = fileTimeToUnixTime(filetime, 0); return gmtime(&t1); } /*********************************************************************** * DOSFS_FileTimeToUnixTime * * Convert a FILETIME format to Unix time. * If not NULL, 'remainder' contains the fractional part of the filetime, * in the range of [0..9999999] (even if time_t is negative). */ time_t fileTimeToUnixTime( const FILETIME *filetime, DWORD *remainder ) { /* Read the comment in the function DOSFS_UnixTimeToFileTime. */ #if USE_LONG_LONG long long int t = filetime->dwHighDateTime; t <<= 32; t += (UINT32)filetime->dwLowDateTime; t -= 116444736000000000LL; if (t < 0) { if (remainder) *remainder = 9999999 - (-t - 1) % 10000000; return -1 - ((-t - 1) / 10000000); } else { if (remainder) *remainder = t % 10000000; return t / 10000000; } #else /* ISO version */ UINT32 a0; /* 16 bit, low bits */ UINT32 a1; /* 16 bit, medium bits */ UINT32 a2; /* 32 bit, high bits */ UINT32 r; /* remainder of division */ unsigned int carry; /* carry bit for subtraction */ int negative; /* whether a represents a negative value */ /* Copy the time values to a2/a1/a0 */ a2 = (UINT32)filetime->dwHighDateTime; a1 = ((UINT32)filetime->dwLowDateTime ) >> 16; a0 = ((UINT32)filetime->dwLowDateTime ) & 0xffff; /* Subtract the time difference */ if (a0 >= 32768 ) a0 -= 32768 , carry = 0; else a0 += (1 << 16) - 32768 , carry = 1; if (a1 >= 54590 + carry) a1 -= 54590 + carry, carry = 0; else a1 += (1 << 16) - 54590 - carry, carry = 1; a2 -= 27111902 + carry; /* If a is negative, replace a by (-1-a) */ negative = (a2 >= ((UINT32)1) << 31); if (negative) { /* Set a to -a - 1 (a is a2/a1/a0) */ a0 = 0xffff - a0; a1 = 0xffff - a1; a2 = ~a2; } /* Divide a by 10000000 (a = a2/a1/a0), put the rest into r. Split the divisor into 10000 * 1000 which are both less than 0xffff. */ a1 += (a2 % 10000) << 16; a2 /= 10000; a0 += (a1 % 10000) << 16; a1 /= 10000; r = a0 % 10000; a0 /= 10000; a1 += (a2 % 1000) << 16; a2 /= 1000; a0 += (a1 % 1000) << 16; a1 /= 1000; r += (a0 % 1000) * 10000; a0 /= 1000; /* If a was negative, replace a by (-1-a) and r by (9999999 - r) */ if (negative) { /* Set a to -a - 1 (a is a2/a1/a0) */ a0 = 0xffff - a0; a1 = 0xffff - a1; a2 = ~a2; r = 9999999 - r; } if (remainder) *remainder = r; /* Do not replace this by << 32, it gives a compiler warning and it does not work. */ return ((((time_t)a2) << 16) << 16) + (a1 << 16) + a0; #endif }