Question

J'ai une valeur de date, dont on me dit qu'elle est de 8 octets, un seul "long" (aka int64) valeur et convertie en hexadécimal:

60f347d15798c901

Comment puis-je convertir ceci et des valeurs comme celle-ci, en utilisant PHP, en heure / date?

La convertir en décimal me donne: 96 243 71 209 87 152 201 1

Un peu plus d'infos: la valeur d'origine est un DateHeure C # et doit représenter une heure / date il y a environ 2 ou 3 semaines.

Était-ce utile?

La solution

(Merci au message de thomasrutter qui m'a donné l'époque de Windows Filetime):

La date donnée semble être un fichier date / heure de fichier little-endian Windows 64 bits, 60 f3 47 d1 57 98 c9 01, qui est équivalent au mot quad 01c99857d147f360 qui est un entier 128801567297500000

C'est "le nombre d'intervalles de 100 nanosecondes qui se sont écoulés depuis minuit le 1 er janvier 1601 A.D. (C.E.) Temps universel coordonné (UTC) "

Après la conversion, cela donne Jeu., 26 février 2009 21:18:49 UTC

Exemple de code:

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

(Merci au message de thomasrutter qui m'a donné l'époque de Windows Filetime):

La date donnée semble être un fichier date / heure de fichier little-endian Windows 64 bits, 60 f3 47 d1 57 98 c9 01, qui est équivalent au mot quad 01c99857d147f360 qui est un entier 128801567297500000

C'est "le nombre d'intervalles de 100 nanosecondes qui se sont écoulés depuis minuit le 1 er janvier 1601 A.D. (C.E.) Temps universel coordonné (UTC) "

Après la conversion, cela donne Jeu., 26 février 2009 21:18:49 UTC

Exemple de code:

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

(Merci au message de thomasrutter qui m'a donné l'époque de Windows Filetime):

La date donnée semble être un fichier date / heure de fichier little-endian Windows 64 bits, 60 f3 47 d1 57 98 c9 01, qui est équivalent au mot quad 01c99857d147f360 qui est un entier 128801567297500000

C'est "le nombre d'intervalles de 100 nanosecondes qui se sont écoulés depuis minuit le 1 er janvier 1601 A.D. (C.E.) Temps universel coordonné (UTC) "

Après la conversion, cela donne Jeu., 26 février 2009 21:18:49 UTC

Exemple de code:

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

Autres conseils

J'ai trouvé une autre référence qui pourrait en indiquer d'autres plus pertinentes. information. Dans ce cas, une date et une heure Windows telles qu'utilisées dans le registre. Apparemment, elles sont également stockées en tant que valeurs 64 bits.

Cela semble un peu plus utile, car il est mentionné que se terminer par C? 01 est un indicateur de ce type de date. Notez que c’est un peu endian (c’est-à-dire que les octets les plus significatifs sont à droite) et que les octets sont dans le mauvais ordre d’octets pour hexdec () sans les inverser 2 chiffres hexadécimaux à la fois puis les deux suivants, etc.).

Et, selon ceci source ,

  

Un tick unique représente cent nanosecondes ou un dix millionième de seconde. La valeur de cette propriété représente le nombre d'intervalles de 100 nanosecondes qui se sont écoulés depuis le 1er janvier minuit à minuit 00:00, ce qui représente.

Malheureusement, PHP ne peut pas gérer les entiers 64 bits. Il atteint au maximum 32 bits. Flotteurs aidera, mais cela n'empêche pas hexdec () de gérer uniquement les ints. Cela peut donc être compliqué de faire ce calcul; vous aurez peut-être encore besoin de la scinder en deux, puis de les combiner en un flottant en exprimant la valeur la plus significative à flotter et en la multipliant par 2 ^ 32, exprimée également en flottant. Il est possible que PHP conçu pour du matériel 64 bits n'ait pas cette limitation, mais je ne le sais pas avec certitude.

Je pense que vous pouvez le convertir en entier décimal avec hexdec (). . Ce sera un horodatage sur lequel vous pourrez travailler avec date ().

La valeur que vous avez indiquée est 36 chiffres hexadécimaux, soit 18 octets. Ce n'est pas un Int64 converti en hexadécimal.

Retournez chez celui qui vous a expliqué le format et demandez-lui de vous dire la vérité cette fois-ci:)

EDIT: OK, étape suivante: découvrez ce que ce nombre signifie réellement. Les tiques depuis 1970? Millis depuis AD 1? Savez-vous ce que votre exemple de chaîne est censé représenter?

S'il s'agit du même type de L’horodatage NTP 64 bits comme décrit ici , vous devez alors scinder la chaîne hexagonale en deux parts égales, c’est-à-dire imaginer un séparateur entre les 8 premiers chiffres hexadécimaux et les 8 autres.

Convertissez la première moitié (valeur des premiers 32 bits) en un entier avec hexdec (), et cet entier sera la valeur de la date au format timestamp Unix (secondes depuis le 1er janvier 1970 GMT) que vous pourrez ensuite utiliser dans la date. Fonction (), etc.

La deuxième partie est constituée de fractions, utile si vous avez besoin d'une précision inférieure à une seconde (bien que peu d'applications le fassent, contrairement aux fonctions de date et d'heure intégrées de PHP, à l'exception de microtime ()). Vous devriez également convertir ceci en décimal avec hexdec ().

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top