我有一个日期值,我告诉它是8个字节,一个“长”字节。 (又名int64)值,并转换为十六进制:

60f347d15798c901

如何将这个和使用PHP的值转换为时间/日期?

将其转换为十进制为我提供: 96 243 71 209 87 152 201 1

更多信息:原始值是C#DateTime,应该代表大约2或3周前的时间/日期。

有帮助吗?

解决方案

(感谢thomasrutter的帖子,它给了我Windows文件时间纪录):

给定日期似乎是Windows 64位little-endian文件的日期时间, 60 f3 47 d1 57 98 c9 01, 这相当于四字 01c99857d147f360 它是一个整数 128801567297500000

这是“100纳秒间隔的数量 从1月1日午夜12点开始, 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位little-endian文件的日期时间, 60 f3 47 d1 57 98 c9 01, 这相当于四字 01c99857d147f360 它是一个整数 128801567297500000

这是“100纳秒间隔的数量 从1月1日午夜12点开始, 1601 A.D.(C.E。)世界协调时间(UTC)“

转换后,它给出了 星期四,2009年2月26日21:18:49 UTC

示例代码:

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

(感谢thomasrutter的帖子,它给了我Windows文件时间纪录):

给定日期似乎是Windows 64位little-endian文件的日期时间, 60 f3 47 d1 57 98 c9 01, 这相当于四字 01c99857d147f360 它是一个整数 128801567297500000

这是“100纳秒间隔的数量 从1月1日午夜12点开始, 1601 A.D.(C.E。)世界协调时间(UTC)“

转换后,它给出了 星期四,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结尾是此类日期的指标。请注意,这是小端(即右边最重要的字节),因此字节对于hexdec()的字节顺序是错误的,而不是一次反转2个十六进制数字(即,从最右边的2个十六进制数字开始,然后是下两个,等等。

并且,根据这个源

  

单个刻度表示一百纳秒或一百万分之一秒。此属性的值表示自0001年1月1日午夜12:00:00起经过的100纳秒间隔的数量。

令你失望的是,遗憾的是PHP无法处理64位整数。最大值为32位。浮点数会有所帮助,但这并不能阻止hexdec()本身只处理整数。所以做这个数学可能很复杂;您可能仍需要将其拆分为两个,然后通过将更重要的值转换为float并将其乘以2 ^ 32并将其转换为float来将它们组合成浮点数。 为64位硬件构建的PHP可能没有这个限制,但我不确定。

我相信您可以使用 hexdec()将其转换为十进制int。这将是您可以使用 date()进行处理的时间戳。

您给出的值是36个十六进制数字,即18个字节。那是 Int64 转换为十六进制。

回到给你解释格式的人那里,让他们这次告诉你真相:))

编辑:好的,下一步:找出这个数字实际意味着什么。自1970年以来蜱虫?公元1年以来的Millis?你知道你的示例字符串代表什么吗?

如果是相同类型的这里描述的64位十六进制NTP时间戳,那么你应该将十六进制字符串分成两部分,即想象一下前8个十六进制数字和另外8个数字之间的分隔符。

将前半部分(前32位值)转换为带有hexdec()的整数,此整数将是Unix时间戳格式的日期值(自格林威治标准时间1970年1月1日起的秒数),您可以在日期中使用该日期值()函数等。

第二部分是小数部分,如果你需要精度超过一秒(虽然没有多少应用程序可以做到,但PHP的内置日期和时间函数不包括microtime()),这很有用。您还可以使用hexdec()将其转换为十进制。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top