【问题标题】:Convert influxdb time format to ISO8601 format将 influxdb 时间格式转换为 ISO8601 格式
【发布时间】: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 或自定义格式?

【问题讨论】:

    标签: php date influxdb


    【解决方案1】:

    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格式从字符串中获取时区,而不是在第三个参数中指定。
    • @Dharman:是的,对于 Z 时区,这更智能一些。
    【解决方案2】:

    从 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
    

    【讨论】:

      【解决方案3】:

      由于 PHP 日期处理的时间不超过微秒,您可以使用 + 说明符忽略 6 位微秒之后的字符串的其余部分

      来自documentation:

      +

      如果存在此格式说明符,则字符串中的尾随数据不会导致错误,而是警告

      使用 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
      

      【讨论】:

      • 我也刚刚发现 PHP 不支持 > 6 位数字,这是一个很好的解决方法,虽然它失去了一些精度,但在我的情况下这并不重要。谢谢
      【解决方案4】:

      嗯,大多数时候,人们不需要那么精确的纳秒。 就我而言,只需几秒钟。 根据我的经验,忽略 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';
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2014-01-25
        • 2021-03-28
        • 2014-12-18
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2023-03-26
        相关资源
        最近更新 更多