I have a date value, which I\'m told is 8 bytes, a single \"long\" (aka int64) value, and converted to hex:
60f347d15798c901
How can I convert
(Thanks to thomasrutter's post, which gave me the Windows filetime epoch):
The given date appears to be a Windows 64-bit little-endian file date-time, 60 f3 47 d1 57 98 c9 01, which is equivalent to the quadword 01c99857d147f360 which as an integer is 128801567297500000
This is "the number of 100-nanosecond intervals that have elapsed since 12:00 midnight, January 1, 1601 A.D. (C.E.) Coordinated Universal Time (UTC)"
After conversion, it gives Thu, 26 February 2009 21:18:49 UTC
Sample code:
'0', '1'=>'1', '2'=>'2', '3'=>'3', '4'=>'4',
'5'=>'5', '6'=>'6', '7'=>'7', '8'=>'8', '9'=>'9',
'a'=>'a', 'b'=>'b', 'c'=>'c', 'd'=>'d', 'e'=>'e', 'f'=>'f',
'A'=>'a', 'B'=>'b', 'C'=>'c', 'D'=>'d', 'E'=>'e', 'F'=>'f'
);
$t = '';
$len = strlen($str);
for ($i=0; $i<$len; ++$i) {
$ch = $str[$i];
if (isset($hex[$ch]))
$t .= $hex[$ch];
}
return $t;
}
// swap little-endian to big-endian
function flip_endian($str) {
// make sure #digits is even
if ( strlen($str) & 1 )
$str = '0' . $str;
$t = '';
for ($i = strlen($str)-2; $i >= 0; $i-=2)
$t .= substr($str, $i, 2);
return $t;
}
// convert hex string to BC-int
function hex_to_bcint($str) {
$hex = array(
'0'=>'0', '1'=>'1', '2'=>'2', '3'=>'3', '4'=>'4',
'5'=>'5', '6'=>'6', '7'=>'7', '8'=>'8', '9'=>'9',
'a'=>'10', 'b'=>'11', 'c'=>'12', 'd'=>'13', 'e'=>'14', 'f'=>'15',
'A'=>'10', 'B'=>'11', 'C'=>'12', 'D'=>'13', 'E'=>'14', 'F'=>'15'
);
$bci = '0';
$len = strlen($str);
for ($i=0; $i<$len; ++$i) {
$bci = bcmul($bci, '16');
$ch = $str[$i];
if (isset($hex[$ch]))
$bci = bcadd($bci, $hex[$ch]);
}
return $bci;
}
// WARNING! range clipping
// Windows date time has range from 29000 BC to 29000 AD
// Unix time only has range from 1901 AD to 2038 AD
// WARNING! loss of accuracy
// Windows date time has accuracy to 0.0000001s
// Unix time only has accuracy to 1.0s
function win64_to_unix($bci) {
// Unix epoch as a Windows file date-time value
$magicnum = '116444735995904000';
$t = bcsub($bci, $magicnum); // Cast to Unix epoch
$t = bcdiv($t, '10000000', 0); // Convert from ticks to seconds
return $t;
}
// get input
$dtval = isset($_GET["dt"]) ? strval($_GET["dt"]) : "0";
$dtval = hexstring($dtval); // strip non-hex chars
// convert to quadword
$dtval = substr($dtval, 0, 16); // clip overlength string
$dtval = str_pad($dtval, 16, '0'); // pad underlength string
$quad = flip_endian($dtval);
// convert to int
$win64_datetime = hex_to_bcint($quad);
// convert to Unix timestamp value
$unix_datetime = win64_to_unix($win64_datetime);
?>
Windows datetime test code
Result:
Quad:
Int:
Unix timestamp:
Date: