【发布时间】:2020-02-06 17:32:44
【问题描述】:
当使用 influxdb PHP 客户端时,我看到这种时间格式具有纳秒精度:
2020-02-06T17:26:38.277740846Z
PHP DateTime 好像看不懂格式:
$date = DateTime::createFromFormat("Y-m-d\TH:i:s.u?",$time);
我得到false 作为返回值。
如何将其转换为 ISO8601 或自定义格式?
【问题讨论】:
当使用 influxdb PHP 客户端时,我看到这种时间格式具有纳秒精度:
2020-02-06T17:26:38.277740846Z
PHP DateTime 好像看不懂格式:
$date = DateTime::createFromFormat("Y-m-d\TH:i:s.u?",$time);
我得到false 作为返回值。
如何将其转换为 ISO8601 或自定义格式?
【问题讨论】:
DateTime 最多只能接受 6 位微秒。字母 Z 代表时区。如果去掉多余的数字,则必须使用第三个参数将时区设置为 Z。
$time = '2020-02-06T17:26:38.277740846Z';
$dateTime = DateTime::createFromFormat('Y-m-d\TH:i:s.u???\Z',$time,new DateTimeZone('Z'));
将 DateTime 对象转换为自定义格式非常容易。
echo $dateTime->format("Y-m-d H:i:s.v");
//2020-02-06 17:26:38.277
【讨论】:
e而不是\Z格式从字符串中获取时区,而不是在第三个参数中指定。
从 PHP8 开始,DateTime 构造函数将不再阻塞这种输入格式。不过会truncate the nanosecond precision to microseconds (6 places)。
代码:(Demo)
$dt = '2020-02-06T17:26:38.277740846Z';
echo (new DateTime($dt))->format('Y-m-d H:i:s');
// 2020-02-06 17:26:38
【讨论】:
由于 PHP 日期处理的时间不超过微秒,您可以使用 + 说明符忽略 6 位微秒之后的字符串的其余部分
+
如果存在此格式说明符,则字符串中的尾随数据不会导致错误,而是警告
使用 DateTime::getLastErrors() 找出是否存在尾随数据。
如果您的日期总是以“Z”结尾,您可以强制使用 UTC 时区:
$time = '2020-02-06T17:26:38.277740846Z' ;
$date = DateTime::createFromFormat("Y-m-d\TH:i:s.u+", $time, new DateTimeZone('UTC'));
echo $date->format('c'); // 2020-02-06T17:26:38+00:00
【讨论】:
嗯,大多数时候,人们不需要那么精确的纳秒。 就我而言,只需几秒钟。 根据我的经验,忽略 InfluxDb 测量的精确设置(大多数用户会这样做......),会导致纳秒位数不一致,从而导致转换失败。 那么,由于 PHP DateTime 在格式不一致时会失败,为什么不将纳秒默认限制为 6 位呢?
我这样做了:
$influxDbDate ="2020-02-06T17:26:38.277740846Z"
$outformat = '%F %T'; //equivalent of 'Y-m-d H:i:s' or you could get just date with 'Y-m-d' and so on...
$datePortions = explode('.', $influxDbDate);
$remadeTime = $datePortions[0] . '.' . substr(explode('Z', $datePortions[1])[0], 0, 6) . 'Z';
$dateTime = DateTime::createFromFormat('Y-m-d\TH:i:s.u\Z', $remadeTime, new DateTimeZone('Z'));
if ($dateTime)
$result = strftime($outformat, $dateTime->getTimestamp());
else
$result = $remadeTime . ' is not InfluxDb timeformat';
【讨论】: