Время UNIX в FILETIME
Кто-нибудь может придумать каким непостижимым образом конвертировать UNIXtime в виндовый FILETIME и запейсать это в файл средствами PHP? Должно получится большое целое (8 байт).
Описание FILETIME ТУТ
Ну так добавляй к timestamp-у разницу и все.
вот в гугле наріл конвертацию наоборот
// FILETIME is a 64-bit unsigned integer representing
// the number of 100-nanosecond intervals since January 1, 1601
// UNIX timestamp is number of seconds since January 1, 1970
// 116444736000000000 = 10000000 * 60 * 60 * 24 * 365 * 369 + 89 leap days
if ($round) {
return round(($FILETIME - 116444736000000000) / 10000000);
}
return ($FILETIME - 116444736000000000) / 10000000;
}
http://coding.derkeiler.com/Archive/PHP/alt.php/2006-09/msg00307.html
Есть большое целое число. Десятичное. 8 байт. Как его записать в файл? Чой-то не получается. Пишет какую-то ахинею. Точнее просто строку. А мне нужно 8 байт (64 бита) именно целое число.
string base_convert(129300670900000000, 10, 16) = 1cb5e466e36d500
Так вот как мне записать в файл это число - 0x1cb5e466e36d500, чтобы оно было числом в 8 байт, а не строкой в 15 символов?
fprintf-ом попробуй
Чота меня уже колбасит через эту беду...
<?
$fp = fopen('tets.tst','w');
$a="30313233343536373839";
$start=0;
$char=0;
while($char!==FALSE) {
$char = substr($a,$start,2);
$start += 2;
fprintf($fp,"%c",intval($char,16));
}
fclose($fp);
?>
`--> php tets.php
`--> cat tets.tst
0123456789%
$win_time = bcmul ( bcadd ( $time, 11644473600 ), 10000000 );
/* В получаемое через base_convert hex-строку добавляем недостающие нули */
$win_time = sprintf("%016s", base_convert( $win_time, 10, 16 ));
/* Шинкуем строку на разряды, развертаем массив и пишем побайтно в файло */
foreach ( array_reverse ( str_split($win_time, 2)) as $key => $val ) {
fprintf ( $ndx, "%c", intval($val, 16) );
}
Great Thanks! :)
UPD. Да, для тех, кто будет маяться этой же бедой, замечаю: это 64-битное слово читается и записывается от младшего к старшему разряду! Поэтому при сплите строки на байты я предварительно реверсю массив.
$s = pack('L', $int);
file_put_contents('bin.dat', $s);
Это для 32-битного integer. pack() с 64-битными не работает, но можно битовыми операциями записать число в два приёма (этот код не проверял, система 32-битная):
$s = pack('L', $int & 0xFFFFFFFF).pack('L', ($int & 0xFFFFFFFF00000000) >> 32);
file_put_contents('bin.dat', $s);
Работа с бинарными данными, кстати, слабое место всех скриптовых языков и вроде даже С#.
Это порядок записи бит числа (bin- & little-endinan) - Интеловский little-endian.
'L', кстати, запишет число в порядке именно для конкретной машины, на которой собрали PHP. Для int64 надо поменять оба pack()а местами.
Тут есть ещё, очевидно, большой пробел в знаниях. Ведь шестнадцатиричное целое в 64 бита физически разбить невозможно, поэтому нужна правильная последовательность движений. Изначально я пытался десятичное на байты покоцать и записать их. Это заведомо ложный путь, ибо шестнадцатеричное целое - совсем не то означает, что набор байтов в десятичной записи.
UPD. Кстати, Proger_XP что говорит это [COLOR=#0000bb]$int [/COLOR][COLOR=#007700]= [/COLOR][COLOR=#0000bb]123[/COLOR];???
С битовыми сдвигами всё понятно.
И никаких операций с ним произвести не получится..
разве что разбить строку на 4(8) байт для 32х и 64 разрадніх систем соответсвенно.
И никаких операций с ним произвести не получится..
разве что разбить строку на 4(8) байт для 32х и 64 разрадніх систем соответсвенно.
Ну дык я так и сделал: 8х8 нашинковал. Записать нормально не получалось. Ты посоветовал как сделать - получилось )))) Они ж в win потому и затеяли структуру с Low|Hight по 32, потому что система-то тоже 32 бита только имеет, и чтобы работать со всей этой бедой, только строка(массив символов) имеется, либо ничего. для того они структуры и придумали. По дельфийски они зовутся record и в любом случае имеют адрес и любым размером означаются pointer'ом. Вобщем, в win с этим делом всё проще.
У меня нет ни одной системы с PHP под 64 бита, так что проверить не могу, но записывать в файл/куда угодно можно любое число хоть на восьмибитной системе, если делать это по-байтово, например, так:
for ($i = 0; $i < 8; ++$i) {
$bitInt .= chr( $int & (0xFF << $i) >> $i );
}
Эффект, по идее, будет тот же самый, что и с двумя pack() выше. Может, именно из-за авто-перевода во float получается мусор.
Просто пример числа.
И никаких операций с ним произвести не получится..
это не совсем так
$i++;
print($i."\n");
print(gettype($i));
P.S. Опередили :)
Всё же little-endian.
$i++;
print($i."\n");
print(gettype($i));
P.S. Опередили :)
ну да.. не правильно выразился, не синтерпритирует как целое число
2mfender угу не получилось потому что число всегда знаковое, так что шинковать не по 8х8 надо было.
вобщем, вариант со строкой, как по мне двольно красивый и лакончиный вышел(именно как реализовал его mfender)
так что не вижу смысла мудрить дальше.
У меня нет ни одной системы с PHP под 64 бита, так что проверить не могу, но записывать в файл/куда угодно можно любое число хоть на восьмибитной системе, если делать это по-байтово, например, так:
for ($i = 0; $i < 8; ++$i) {
$bitInt .= chr( $int & (0xFF << $i) >> $i );
}
Эффект, по идее, будет тот же самый, что и с двумя pack() выше. Может, именно из-за авто-перевода во float получается мусор.
Просто пример числа.
Боюсь со сдвигами тоже не выйдет, так как $int будет float
Можно применить хитрость, для получения первых 32 бит просто typecast'ить в (int), тогда всё лишнее отбросится, а для 32..64 бит - вычитать 2^32 и снова typecast'ить. Хотя это тоже самое, что сдвиги, так что тоже должно работать.