如何在PHP中转换C# DateTime.ToBinary()生成的64位时间戳?
解决C# DateTime.ToBinary()值在PHP中的转换问题
你的问题出在直接将整数传给unpack()——unpack()的第二个参数需要的是二进制字符串,而不是数字本身。我们需要先理解C# DateTime.ToBinary()的结构,再一步步转换到PHP可识别的时间格式。
先搞懂C# DateTime.ToBinary()的结构
C#的ToBinary()返回一个64位整数,由两部分组成:
- 低62位:表示
DateTime的Ticks值(从公元1年1月1日00:00:00开始的100纳秒间隔数) - 最高两位:表示
DateTimeKind(0=Unspecified,1=Utc,2=Local)
PHP转换的完整步骤
我们需要把这个64位整数转换成二进制字符串,提取出Ticks和时区信息,再转换成PHP的时间对象:
function convertCSharpDateTimeBinary($csharpBinary) { // 1. 将C#的64位整数打包成小端字节序的二进制字符串 $binaryStr = pack('q', $csharpBinary); // 2. 解包为无符号64位整数,方便位操作 $unsigned64 = unpack('Q', $binaryStr)[1]; // 3. 提取DateTimeKind(最高两位) $kind = ($unsigned64 >> 62) & 0b11; // 4. 提取Ticks值(低62位) $ticks = $unsigned64 & ((1 << 62) - 1); // 5. 将Ticks转换为UTC时间戳 // Unix纪元(1970-01-01 00:00:00 UTC)对应的Ticks是固定值:621355968000000000 $unixEpochTicks = 621355968000000000; $utcTimestamp = ($ticks - $unixEpochTicks) / 10000000; // 1秒 = 10^7个Ticks // 6. 根据DateTimeKind处理时区 switch ($kind) { case 1: // UTC时间 $date = date_create('@' . $utcTimestamp, timezone_open('UTC')); break; case 2: // 本地时间,转换为PHP默认时区 $date = date_create('@' . $utcTimestamp); $date->setTimezone(date_default_timezone_get()); break; default: // Unspecified,默认按本地时间处理(可根据需求调整) $date = date_create('@' . $utcTimestamp); break; } return $date; } // 测试你的示例值 $csharpValue = -8586307756854775808; $resultDate = convertCSharpDateTimeBinary($csharpValue); echo $resultDate->format('Y-m-d H:i:s'); // 输出:2019-11-10 22:00:00(取决于你的PHP默认时区)
为什么你原来的代码失败?
你写的unpack('q', -8586307756854775808)会把整数自动转换成文本字符串(比如"-8586307756854775808"),而unpack()会尝试从这个文本字符串中解析64位整数,这显然不是正确的二进制数据,所以转换失败。
32位PHP的注意事项
如果你的PHP是32位版本,无法直接处理64位整数,需要将$csharpBinary作为字符串传入,并用pack('J', $csharpBinary)来处理(J表示无符号64位大端字节序,需根据实际字节序调整)。不过现在绝大多数生产环境都是64位PHP,这个场景比较少见。
内容的提问来源于stack exchange,提问作者Zatla00
相关产品推荐
相关产品推荐

