Frage

Ich habe einen Datumswert, den ich gesagt 8 Bytes ist, ein einziger "long" (auch bekannt als int64) Wert, und konvertierte zum hex:

60f347d15798c901

Wie kann ich diese Werte und wie diese zu konvertieren, mit PHP, in eine Zeit / Datum?

Umwandlung in dezimal gibt mir: 96 243 71 209 87 152 201 1

Ein wenig mehr Info: der ursprüngliche Wert ist eine C # Datetime und soll vor eine Zeit / Datum etwa 2 oder 3 Wochen stellen

.
War es hilfreich?

Lösung

(Dank thomasrutter der Post, die mir die Windows-Epoche gab filetime):

Das angegebene Datum eine Windows 64-Bit-Little-Endian-Datei Datum-Zeit zu sein scheint, 60 f3 d1 47 57 98 01 c9, was äquivalent zu dem Viererwort 01c99857d147f360 die als eine ganze Zahl ist, 128801567297500000

Dies ist „die Zahl der 100-Nanosekunden-Intervalle das hat seit 0.00 Uhr Mitternacht am 1. Januar abgelaufen ist, 1601 A. D. (C. E.) Coordinated Universal Time (UTC) "

Nach der Konvertierung gibt es Do, 26. Februar 2009 21.18.49 UTC

Beispielcode:

<?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($_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);

?><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>

Andere Tipps

Ich fand eine andere Referenz denen einige relevanter Punkt könnte Information. In diesem Fall wird ein Windows-Datum und Uhrzeit wie in der Registrierung verwendet. Offenbar auch als 64-Bit-Werte gespeichert werden diese.

Dies sucht ein bisschen mehr hilfreich, da es erwähnt, dass ein Indikator für diese Art von Datum C 01 endet in ist. Beachten Sie, dass dies Little-Endian (dh höchstwertigen Bytes auf der rechten Seite), so dass die Bytes in die falsche Byte-Reihenfolge für hexdec (), ohne sie zu zwei hexadezimalen Ziffern zu einem Zeitpunkt umgekehrt (dh, beginnen Sie mit der rechten höchstens 2 Hex-Ziffern, dann nächsten zwei, usw.).

Und nach dieser Quelle ,

  

Eine einzige Zecke stellt einhundert Nanosekunden oder ein Zehnmillionstel Sekunde. Der Wert dieser Eigenschaft stellt die Anzahl der 100-Nanosekunden-Intervalle, die seit 00.00.00 Mitternacht verstrichen sind, 1. Januar 0001, die darstellt.

Was könnten Sie stolpern ist, dass leider PHP nicht 64-Bit-Integer umgehen kann. Es maxes bei 32-Bit-out. Floats helfen, aber das bedeutet nicht zu stoppen hexdec () selbst aus nur mit ints fertig zu werden. So kann es kompliziert sein, um diese Mathematik zu tun; Sie können es immer noch in zwei Teile spalten müssen, dann in einem Schwimmer kombinieren, indem die bedeutendere Wert Gießen es zu schweben und Multiplikation mit 2 ^ 32 auch als Schwimmer gegossen. Es ist möglich, dass PHP für 64-Bit-Hardware gebaut kann diese Einschränkung nicht haben, aber ich weiß es nicht sicher.

Ich glaube, Sie es in eine Dezimalzahl int mit hexdec(). umwandeln können, die ein timestap sein wird, die Sie mit date(). arbeiten können

Der Wert, den Sie gegeben haben, ist 36 hexadezimalen Ziffern, das heißt 18 Byte-Wert. Das ist nicht ein Int64 zu hex umgewandelt.

Gehen Sie zurück zu wer auch immer sind Sie auf die Erklärung des Formats und sie bitten, Ihnen die Wahrheit dieser Zeit zu sagen:)

EDIT: Okay, nächster Schritt: Finden Sie heraus, was diese Zahl tatsächlich bedeutet, gemeint ist. Ticks seit 1970? Millis seit AD 1? Weißt du, was ist Ihr Beispiel Zeichenfolge gemeint darstellen?

Wenn es die gleiche Art von 64-Bit-hex-NTP-Zeitstempel wie hier beschrieben, dann sollten Sie den hex-String gleich in zwei sein Aufspalten, das heißt, eine Trennlinie zwischen den ersten 8 hexadezimalen Ziffern vorstellen und die andere 8.

Konvertieren Sie die erste Hälfte (erste 32 Bits' wert) in eine ganzen Zahl mit hexdec (), und dieser ganzen Zahl wird der Datumswert in Unix-Zeitstempel-Format (Sekunden seit dem 1. Januar 1970 GMT), die Sie dann in dem Zeitpunkt verwenden können () Funktion, etc.

Der zweite Teil ist gebrochene Abschnitte, nützlich, wenn Sie Genauigkeit feiner als eine Sekunde benötigen (wenn auch nicht viele Anwendungen tun, und PHP in Datums- und Zeitfunktionen gebaut tun, außer nicht für micro ()). Sie würden dies auch konvertieren mit hexdec in Dezimalzahlen ().

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top