Справочник функций

Ваш аккаунт

Войти через: 
Забыли пароль?
Регистрация
Информацию о новых материалах можно получать и без регистрации:

Почтовая рассылка

Подписчиков: -1
Последний выпуск: 19.06.2015

Время UNIX в FILETIME

8
27 сентября 2010 года
mfender
3.5K / / 15.06.2005
Чой-то я туплю после вчерашнего :eek:
Кто-нибудь может придумать каким непостижимым образом конвертировать UNIXtime в виндовый FILETIME и запейсать это в файл средствами PHP? Должно получится большое целое (8 байт).

Описание FILETIME ТУТ
274
27 сентября 2010 года
Lone Wolf
1.3K / / 26.11.2006
как я понял это тоже timestamp, только с 16** какого-то там года.
Ну так добавляй к timestamp-у разницу и все.
вот в гугле наріл конвертацию наоборот
 
Код:
function FILETIMEtoUNIXtime($FILETIME, $round=true) {
// 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
27 сентября 2010 года
mfender
3.5K / / 15.06.2005
Ну это всё хорошо. Установили, что в win это будет как bcmul ( bcadd ( $unix_time, 11644473600 ), 10000000 )
Есть большое целое число. Десятичное. 8 байт. Как его записать в файл? Чой-то не получается. Пишет какую-то ахинею. Точнее просто строку. А мне нужно 8 байт (64 бита) именно целое число.
274
27 сентября 2010 года
Lone Wolf
1.3K / / 26.11.2006
так в чем проблема? в конвертировании или именно в представлении большого числа?
8
27 сентября 2010 года
mfender
3.5K / / 15.06.2005
Проблема в том, что допустим, мы получили сейчас decimal filetime 129300670900000000
string base_convert(129300670900000000, 10, 16) = 1cb5e466e36d500

Так вот как мне записать в файл это число - 0x1cb5e466e36d500, чтобы оно было числом в 8 байт, а не строкой в 15 символов?
274
27 сентября 2010 года
Lone Wolf
1.3K / / 26.11.2006
а чем пишешь?
fprintf-ом попробуй
8
28 сентября 2010 года
mfender
3.5K / / 15.06.2005
Вот и беда в этом. Как записывать в файл? Пусть даже побайтно. У меня получается записать строку, но никак не слово шестнадцатиричное. Одним словом, если у меня есть 0x0A, то я и хочу видеть байт с 0x0A, а не два байта типа 0x3131, или как-то там ещё. Уже всяко пытался: и sprintf'ом и pack'ом. Всё одно - пишет строку, зараза!

Чота меня уже колбасит через эту беду...
274
28 сентября 2010 года
Lone Wolf
1.3K / / 26.11.2006
Что-то типа такого?
Код:
`--> cat tets.php            
<?
 $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%
8
28 сентября 2010 года
mfender
3.5K / / 15.06.2005
Во, блин! Утро вечера мудренее, что называется! :D
 
Код:
/* Получаем FILETIME из разницы между ним и UNIXTIME */
    $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) );
    }
В результате в файл пишется 801C6901D25ECB01, что вполне соответствует правильному представлению FILETIME, и означает 5:57:17 28.09.2010 по-человечески ))))))

Great Thanks! :)

UPD. Да, для тех, кто будет маяться этой же бедой, замечаю: это 64-битное слово читается и записывается от младшего к старшему разряду! Поэтому при сплите строки на байты я предварительно реверсю массив.
253
28 сентября 2010 года
Proger_XP
1.5K / / 07.08.2004
Да вы чего, можно ведь pack() использовать - не надо шаманить со строкаи/массивами.
 
Код:
$int = 123;
$s = pack('L', $int);
file_put_contents('bin.dat', $s);

Это для 32-битного integer. pack() с 64-битными не работает, но можно битовыми операциями записать число в два приёма (этот код не проверял, система 32-битная):
 
Код:
$int = 123;
$s = pack('L', $int & 0xFFFFFFFF).pack('L', ($int & 0xFFFFFFFF00000000) >> 32);
file_put_contents('bin.dat', $s);

Работа с бинарными данными, кстати, слабое место всех скриптовых языков и вроде даже С#.

Цитата:
это 64-битное слово читается и записывается от младшего к старшему разряду


Это порядок записи бит числа (bin- & little-endinan) - Интеловский little-endian.
'L', кстати, запишет число в порядке именно для конкретной машины, на которой собрали PHP. Для int64 надо поменять оба pack()а местами.

8
28 сентября 2010 года
mfender
3.5K / / 15.06.2005
Пробывал я pack() с L. Нихрена не получилось. Тоже думал, что если слово разбить по 32 бита, то запишет нормально. А получается какая-то ахинея. Delphi для Win - проблем нет. А вот PHP - целая история, затянувшаяся почти на сутки.

Тут есть ещё, очевидно, большой пробел в знаниях. Ведь шестнадцатиричное целое в 64 бита физически разбить невозможно, поэтому нужна правильная последовательность движений. Изначально я пытался десятичное на байты покоцать и записать их. Это заведомо ложный путь, ибо шестнадцатеричное целое - совсем не то означает, что набор байтов в десятичной записи.

UPD. Кстати, Proger_XP что говорит это [COLOR=#0000bb]$int [/COLOR][COLOR=#007700]= [/COLOR][COLOR=#0000bb]123[/COLOR];???
С битовыми сдвигами всё понятно.
274
28 сентября 2010 года
Lone Wolf
1.3K / / 26.11.2006
тут проблема в том, что пхп не сможет представить 64хбитное число как число - для него єто всегда будет строка.
И никаких операций с ним произвести не получится..
разве что разбить строку на 4(8) байт для 32х и 64 разрадніх систем соответсвенно.
8
28 сентября 2010 года
mfender
3.5K / / 15.06.2005
Цитата: Lone Wolf
тут проблема в том, что пхп не сможет представить 64хбитное число как число - для него єто всегда будет строка.
И никаких операций с ним произвести не получится..
разве что разбить строку на 4(8) байт для 32х и 64 разрадніх систем соответсвенно.


Ну дык я так и сделал: 8х8 нашинковал. Записать нормально не получалось. Ты посоветовал как сделать - получилось )))) Они ж в win потому и затеяли структуру с Low|Hight по 32, потому что система-то тоже 32 бита только имеет, и чтобы работать со всей этой бедой, только строка(массив символов) имеется, либо ничего. для того они структуры и придумали. По дельфийски они зовутся record и в любом случае имеют адрес и любым размером означаются pointer'ом. Вобщем, в win с этим делом всё проще.

253
28 сентября 2010 года
Proger_XP
1.5K / / 07.08.2004
Насколько я понимаю работу чисел в PHP, оно всегда поддерживает 32-битные signed int (но не unsigned), а 64 - если платформа соответствующая. Если число выходит за рамки этого, то оно переводится в float, но никак не в строку:
Цитата:
If PHP encounters a number beyond the bounds of the integer type, it will be interpreted as a float instead. Also, an operation which results in a number beyond the bounds of the integer type will return a float instead.



У меня нет ни одной системы с PHP под 64 бита, так что проверить не могу, но записывать в файл/куда угодно можно любое число хоть на восьмибитной системе, если делать это по-байтово, например, так:

 
Код:
$bitInt = '';
for ($i = 0; $i < 8; ++$i) {
  $bitInt .= chr( $int & (0xFF << $i) >> $i );
}


Эффект, по идее, будет тот же самый, что и с двумя pack() выше. Может, именно из-за авто-перевода во float получается мусор.

Цитата:
Кстати, Proger_XP что говорит это $int = 123;?


Просто пример числа.

14
28 сентября 2010 года
Phodopus
3.3K / / 19.06.2008
Цитата: Lone Wolf
тут проблема в том, что пхп не сможет представить 64хбитное число как число - для него єто всегда будет строка.
И никаких операций с ним произвести не получится..


это не совсем так

 
Код:
$i = 16000000000;
    $i++;
    print($i."\n");
    print(gettype($i));

P.S. Опередили :)
10
28 сентября 2010 года
Freeman
3.2K / / 06.03.2004
Цитата: Proger_XP
Интеловский big-endian.


Всё же little-endian.

274
28 сентября 2010 года
Lone Wolf
1.3K / / 26.11.2006
Цитата: Phodopus
это не совсем так
 
Код:
$i = 16000000000;
    $i++;
    print($i."\n");
    print(gettype($i));

P.S. Опередили :)



ну да.. не правильно выразился, не синтерпритирует как целое число

2mfender угу не получилось потому что число всегда знаковое, так что шинковать не по 8х8 надо было.
вобщем, вариант со строкой, как по мне двольно красивый и лакончиный вышел(именно как реализовал его mfender)
так что не вижу смысла мудрить дальше.

253
28 сентября 2010 года
Proger_XP
1.5K / / 07.08.2004
Цитата: Freeman
Всё же little-endian.


А, точно, ошибся в имени. В общем, см. вики.

274
28 сентября 2010 года
Lone Wolf
1.3K / / 26.11.2006
Цитата: Proger_XP
Насколько я понимаю работу чисел в PHP, оно всегда поддерживает 32-битные signed int (но не unsigned), а 64 - если платформа соответствующая. Если число выходит за рамки этого, то оно переводится в float, но никак не в строку:


У меня нет ни одной системы с PHP под 64 бита, так что проверить не могу, но записывать в файл/куда угодно можно любое число хоть на восьмибитной системе, если делать это по-байтово, например, так:
 
Код:
$bitInt = '';
for ($i = 0; $i < 8; ++$i) {
  $bitInt .= chr( $int & (0xFF << $i) >> $i );
}


Эффект, по идее, будет тот же самый, что и с двумя pack() выше. Может, именно из-за авто-перевода во float получается мусор.


Просто пример числа.



Боюсь со сдвигами тоже не выйдет, так как $int будет float

253
28 сентября 2010 года
Proger_XP
1.5K / / 07.08.2004
Цитата: Lone Wolf
Боюсь со сдвигами тоже не выйдет, так как $int будет float


Можно применить хитрость, для получения первых 32 бит просто typecast'ить в (int), тогда всё лишнее отбросится, а для 32..64 бит - вычитать 2^32 и снова typecast'ить. Хотя это тоже самое, что сдвиги, так что тоже должно работать.

Реклама на сайте | Обмен ссылками | Ссылки | Экспорт (RSS) | Контакты
Добавить статью | Добавить исходник | Добавить хостинг-провайдера | Добавить сайт в каталог