Помогите мне перевести длинное значение, выраженное в шестнадцатеричном виде, обратно в дату / время

StackOverflow https://stackoverflow.com/questions/610603

Вопрос

У меня есть значение даты, которое, как мне говорят, составляет 8 байт, один " длинный " (также известное как int64) и преобразуется в шестнадцатеричное:

60f347d15798c901

Как я могу преобразовать это и такие значения, используя PHP, во время / дату?

Преобразование его в десятичное дает мне: 96 243 71 209 87 152 201 1

Немного больше информации: исходное значение - C # DateTime, и оно должно представлять время / дату 2 или 3 недели назад.

Это было полезно?

Решение

(Спасибо посту Томасруттера, который дал мне эпоху файлового времени Windows):

Похоже, что указанная дата является 64-битной датой в формате Windows. 60 f3 47 d1 57 98 c9 01, что эквивалентно четырех словам 01c99857d147f360 который как целое число 128801567297500000

Это "количество интервалов в 100 наносекунд". прошедшие с 12:00 до полуночи 1 января, 1601 г. н.э. (C.E.) Всемирное координированное время (UTC) "

После преобразования он дает Четверг, 26 февраля 2009 г., 21:18:49 UTC

Пример кода:

<?php

    // strip non-hex characters
    function hexstring($str) {
        $hex = array(
            '0'=>'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(

(Спасибо посту Томасруттера, который дал мне эпоху файлового времени Windows):

Похоже, что указанная дата является 64-битной датой в формате Windows. 60 f3 47 d1 57 98 c9 01, что эквивалентно четырех словам 01c99857d147f360 который как целое число 128801567297500000

Это "количество интервалов в 100 наносекунд". прошедшие с 12:00 до полуночи 1 января, 1601 г. н.э. (C.E.) Всемирное координированное время (UTC) "

После преобразования он дает Четверг, 26 февраля 2009 г., 21:18:49 UTC

Пример кода:

<*>GET["dt"]) ? strval(

(Спасибо посту Томасруттера, который дал мне эпоху файлового времени Windows):

Похоже, что указанная дата является 64-битной датой в формате Windows. 60 f3 47 d1 57 98 c9 01, что эквивалентно четырех словам 01c99857d147f360 который как целое число 128801567297500000

Это "количество интервалов в 100 наносекунд". прошедшие с 12:00 до полуночи 1 января, 1601 г. н.э. (C.E.) Всемирное координированное время (UTC) "

После преобразования он дает Четверг, 26 февраля 2009 г., 21:18:49 UTC

Пример кода:

<*>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); ?><html> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <title>Windows datetime test code</title> </head> <form method="get"> <label>Datetime value: <input name="dt" type="text" value="<?php echo $dtval; ?>"/></label> <input type="submit" /> </form> <hr /> Result: Quad: <?php echo $quad; ?><br /> Int: <?php echo $win64_datetime; ?><br /> Unix timestamp: <?php echo $unix_datetime; ?><br /> Date: <?php echo date("D, d F Y H:i:s e", $unix_datetime); ?><br /> <body> </body> </html>

Другие советы

Я нашел другую ссылку , которая может указывать на некоторые более важные Информация. В этом случае Windows использует дату и время, используемые в реестре. По-видимому, они также хранятся в виде 64-битных значений.

Это выглядит немного более полезным, поскольку в нем упоминается, что окончание в C? 01 является индикатором этого типа даты. Обратите внимание, что это младший порядок байтов (т. Е. Наиболее значимые байты справа), поэтому байты расположены в неправильном порядке байтов для hexdec (), не обращая их по 2 шестнадцатеричных цифры за раз (т. Е. Начинаются с самых правых 2 шестнадцатеричных цифр, затем следующие два и т. д.).

И, согласно этому источник ,

  

Один тик представляет сто наносекунд или одну десятую миллионную секунды. Значение этого свойства представляет число интервалов в 100 наносекунд, прошедших с 12:00:00 до полуночи 1 января 0001 года, которое представляет собой.

Что может сбить вас с толку, так это то, что, к сожалению, PHP не может обрабатывать 64-битные целые числа. Максимальное значение - 32 бита. Поплавки помогут, но это не мешает самому hexdec () справляться только с целыми числами. Так что это может быть сложно сделать эту математику; вам все еще может понадобиться разделить его на две части, а затем объединить их в число с плавающей точкой, приведя более значимое значение к числу с плавающей точкой и умножив его на 2 ^ 32, также приведенное к значению с плавающей точкой. Возможно, что PHP, созданный для 64-битного оборудования, может не иметь этого ограничения, но я точно не знаю.

Я полагаю, что вы можете преобразовать его в десятичное целое с помощью hexdec (). Это будет временная метка, с которой вы можете работать с помощью date ().

Значение, которое вы указали, составляет 36 шестнадцатеричных цифр, то есть 18 байтов. Это не , а Int64 преобразуется в шестнадцатеричное.

Вернитесь к тому, кто дал вам объяснение формата, и попросите их рассказать вам правду на этот раз:)

РЕДАКТИРОВАТЬ: Хорошо, следующий шаг: выяснить, что на самом деле означает это число. Клещи с 1970 года? Миллис с нашей эры 1? Знаете ли вы, что ваша строка примера должна представлять?

Если это тот же тип 64-битная шестнадцатеричная временная метка NTP, как описано здесь , тогда вы должны разделить шестнадцатеричную строку поровну на две части, то есть представить себе разделитель между первыми 8 шестнадцатеричными цифрами и другими 8.

Преобразуйте первую половину (первые 32 бита) в целое число с помощью hexdec (), и это число будет значением даты в формате отметки времени Unix (в секундах с 1 января 1970 года по Гринвичу), которое затем можно использовать в дате () и т. д.

Вторая часть - это дробные секции, которые полезны, если вам нужна точность, превышающая одну секунду (хотя это делают не многие приложения, а встроенные в PHP функции даты и времени - за исключением microtime ()). Вы также преобразовали бы это в десятичную с помощью hexdec ().

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top