16進数で表現された長い値を日付/時刻に戻すのを手伝ってください

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

質問

日付の値がありますが、それは8バイトで、単一の「長い」 (別名int64)値、16進数に変換:

60f347d15798c901

PHPを使用して、これとこのような値を時刻/日付に変換するにはどうすればよいですか?

10進数に変換すると、次のようになります。 96243 71209 87152201 1

もう少し情報:元の値はC#DateTimeであり、約2〜3週間前の時刻/日付を表す必要があります。

役に立ちましたか?

解決

(thomasrutterの投稿のおかげで、Windowsのファイルタイムエポックが得られました):

指定された日付は、Windows 64ビットリトルエンディアンファイルの日付、時刻、 60 f3 47 d1 57 98 c9 01、 これはクワッドワードと同等です 01c99857d147f360 整数として 128801567297500000

これは" 100ナノ秒間隔の数です 1月1日午前0時から経過した 1601 A.D.(C.E.)協定世界時(UTC)"

変換後、 木、2009年2月26日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(

(thomasrutterの投稿のおかげで、Windowsのファイルタイムエポックが得られました):

指定された日付は、Windows 64ビットリトルエンディアンファイルの日付、時刻、 60 f3 47 d1 57 98 c9 01、 これはクワッドワードと同等です 01c99857d147f360 整数として 128801567297500000

これは&quot; 100ナノ秒間隔の数です 1月1日午前0時から経過した 1601 A.D.(C.E.)協定世界時(UTC)&quot;

変換後、 木、2009年2月26日21:18:49 UTC

サンプルコード:

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

(thomasrutterの投稿のおかげで、Windowsのファイルタイムエポックが得られました):

指定された日付は、Windows 64ビットリトルエンディアンファイルの日付、時刻、 60 f3 47 d1 57 98 c9 01、 これはクワッドワードと同等です 01c99857d147f360 整数として 128801567297500000

これは&quot; 100ナノ秒間隔の数です 1月1日午前0時から経過した 1601 A.D.(C.E.)協定世界時(UTC)&quot;

変換後、 木、2009年2月26日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で終わることはこのタイプの日付の指標であると述べているため、これはもう少し役立つように見えます。これはリトルエンディアン(つまり、右側の最上位バイト)であるため、バイトは一度に2桁の16進数を反転せずにhexdec()のバイト順序が間違っていることに注意してください(つまり、右端の2桁の16進数で始まり、次の2つなど)。

そして、 thisソース

  

単一のティックは、100ナノ秒または1000万分の1秒を表します。このプロパティの値は、0001年1月1日の深夜12:00:00から経過した100ナノ秒間隔の数を表します。

あなたをつまずかせるかもしれないのは、残念ながらPHPは64ビット整数を処理できないことです。 32ビットで最大になります。フロートは役立ちますが、それはhexdec()自体がintに対処することだけを止めません。したがって、この計算を行うのは複雑かもしれません。まだ2つに分割してから、より重要な値をfloatにキャストし、2 ^ 32を乗算してfloatとしてキャストすることにより、それらをfloatに結合する必要があるかもしれません。 64ビットハードウェア用に構築されたPHPにこの制限がない可能性がありますが、私にはわかりません。

hexdec()で10進整数に変換できると思います。これは、 date()。

で作業できるタイムスタンプになります。 >

指定した値は36桁の16進数、つまり18バイトです。これは、 Int64 が16進数に変換された ではありません。

形式の説明をくれた人に戻り、今回は真実を伝えるように頼んでください:)

編集:さて、次のステップ:その数字が実際に何を意味するのかを調べてください。 1970年以降のダニ? AD 1以降のMillis?サンプル文字列が何を表すのか知っていますか?

同じタイプのここで説明する64ビットの16進数NTPタイムスタンプ、16進数文字列を2つに均等に分割する必要があります。つまり、最初の8桁の16進数と他の8桁の区切りを想像してください。

前半(最初の32ビットの価値)をhexdec()で整数に変換すると、この整数はUnixタイムスタンプ形式(1970年1月1日GMTからの秒数)の日付値になり、日付で使用できます()関数など

2番目の部分は小数部です。1秒よりも細かい精度が必要な場合に便利です(ただし、多くのアプリケーションでは必要ありません。また、PHPに組み込まれている日付および時刻関数はmicrotime()を除きます)。また、hexdec()を使用してこれを10進数に変換します。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top