我有一个基于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的服务器端。
如何修复PHP代码以便再次正常工作?
答案 0 :(得分:1)
有两种思想流派:
如果使用选项中设置的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');
}
答案 1 :(得分:0)
抱歉,您的上次评论......:)
然后尝试
$i = gmp_init( $number );
$timestamp = gmp_strval( $i );