验证 PHP 中的 java 时间戳

Validating java timestamp in PHP

我有一个基于 php 的 API,它接受来自 Android 设备的上传(读取 - Java)。数据采用 JSON 格式,其中一个字段是 java 时间戳,例如1421100231554。 PHP 代码使用以下(简化的)代码检查(相当简单地)此时间戳的有效性:

function check_num($num, $len) {
    return preg_match("/^\d{$len}$/", $num);
}

if(!check_num($data['timestamp'], 13)) {
    exit_error('Invalid timestamp');
}

check_num 函数从许多不同的地方调用。

后来这个时间戳用于使用这段代码将数据插入数据库(这部分与本题的目的几乎无关)。

$dt = new DateTime();                                                                                             
$dt->setTimestamp($data['timestamp'] / 1000);
...
$stmt->execite(array(...
                     ':tmstmp' => $dt->format('Y-m-d H:i:s')));

这对我来说效果很好 - 直到我们将托管从 Fedora 4(不要问)迁移到最新的 CentOS。现在这段代码停止工作了,因为 preg_match('/^\d+$/', $data['timestamp']) 正在返回 0。我开始深入研究它 - 结果发现 PHP 正在将 13 位数字转换为其科学记数法,即 1.42110023155E+12。这显然会抛出模式匹配器。

时间戳以数字形式出现,不是字符串,即JSON的相关部分是:

[
  {
     "timestamp":1421100231554,
     "customer":100274,
     "type":"warehouse",
     "items":[...]
  }
]

我无法控制发送数据的 Android 应用程序,因此我必须进行的任何调整都必须在 PHP.[=20 中的服务器端进行=]

如何修复 PHP 代码使其再次正常工作?

抱歉,您最后的评论...:)

那就试试

$i = gmp_init( $number );
$timestamp = gmp_strval( $i );

对此有两种观点:

如果您在选项中设置了 JSON_BIGINT_AS_STRING 标志的情况下调用 json_encode,它应该将任何太大而无法表示为 int 的整数传递回字符串。这应该保持精度:

$myJson = '{"time":71055011577700000000}'; // too big to fit into 64-bit int
$myobj = json_decode($myJson,false,512,JSON_BIGINT_AS_STRING);
var_dump($myObj);

object(stdClass)#1 (1) {
  ["time"]=>
  string(20) "71055011577700000000"
}

另一种观点是您不应该对数值使用正则表达式来确定它们是否在指定范围内。在数字上使用数学...。革命性的,我知道:

if ($data['timestamp'] > 1e14) {
    die('more than 13 digits in your int!');
} elseif ($data['timestamp'] < 1) {
    die('your int is too small');
}