【问题标题】:Convert youtube Api v3 video duration in php在 php 中转换 youtube Api v3 视频持续时间
【发布时间】:2014-08-15 02:31:21
【问题描述】:

如何将 PT2H34M25S 转换为 2:34:25

我搜索并使用了这段代码。我是正则表达式的新手,有人可以解释一下吗?并帮助我解决我的问题

function covtime($youtube_time){
        preg_match_all('/(\d+)/',$youtube_time,$parts);
        $hours = floor($parts[0][0]/60);
        $minutes = $parts[0][0]%60;
        $seconds = $parts[0][1];
        if($hours != 0)
            return $hours.':'.$minutes.':'.$seconds;
        else
            return $minutes.':'.$seconds;
    }   

但这段代码只给我 HH:MM

这么笨找到了解决方案:

   function covtime($youtube_time){
            preg_match_all('/(\d+)/',$youtube_time,$parts);
            $hours = $parts[0][0];
            $minutes = $parts[0][1];
            $seconds = $parts[0][2];
            if($seconds != 0)
                return $hours.':'.$minutes.':'.$seconds;
            else
                return $hours.':'.$minutes;
        }

【问题讨论】:

  • 您确定它没有给您 MM:SS(条件中的第二种情况)吗?我没有看到可以输出 HH:MM 的代码路径。
  • 它给了我 MM:SS 但不是 HH:MM:SS
  • 你确定你用一个多小时的视频尝试过吗?此外,您在问题中给出的输入格式示例显然有 3 个单独的数字序列,那么为什么您的代码只考虑前 2 个?
  • 刚刚找到解决方案已在上面发布,感谢您的帮助
  • @DanielEuchar,我用修改后的函数编辑了我的答案,供您查看。还有更多的验证可以完成。此外,看起来有人删除了您对问题所做的编辑。

标签: php regex youtube-api


【解决方案1】:

使用 DateTime 类

您可以使用 PHP 的 DateTime 类来实现这一点。这个解决方案要简单得多,即使字符串中数量的格式顺序不同,它也可以工作。在这种情况下,正则表达式解决方案(很可能)会中断。

在 PHP 中,PT2H34M25S 是一个有效的日期期间字符串,并且可以被 DateTime 解析器理解。然后我们利用这个事实,使用add() 方法将它添加到Unix epoch。然后您可以格式化生成的日期以获得所需的结果:

function covtime($youtube_time){
    if($youtube_time) {
        $start = new DateTime('@0'); // Unix epoch
        $start->add(new DateInterval($youtube_time));
        $youtube_time = $start->format('H:i:s');
    }
    
    return $youtube_time;
}   

echo covtime('PT2H34M25S');

Demo

【讨论】:

  • 哇,这好多了,但是在我的 wamp 服务器中,这给了我一个错误 Uncaught exception 'Exception' with message 'DateInterval::__construct() [dateinterval.--construct]: 未知或错误格式()
  • @DanielEuchar:你能在函数中添加var_dump($youtube_time);,并告诉我当你用你的时间字符串尝试它时它会输出什么?
  • 有时我得到 PT2H34M25S 有时 PT3M22S 取决于视频长度
  • 尝试定义它是否有 hours:minutes:seconds 然后使用这个函数代替你总是可以做一个 switch case 并且在你的每个案例中你都做:例如return $start->format('g:i:s'); //for hours:minutes:seconds
  • @JefferyThaGintoki:是的,这可以通过多种方式进行改进。我把它留给用户来弄清楚如何根据他们的要求修改功能:)
【解决方案2】:

AmalPferate 的解决方案都很棒! 然而,Amal 解决方案一直给我额外的 1 小时。以下是我的解决方案,与 Amal 相同,但方法不同,这对我有用。

$date = new DateTime('1970-01-01');
$date->add(new DateInterval('PT2H34M25S'));
echo $date->format('H:i:s')

datetime->add() reference

【讨论】:

  • 它有效。日期部分并不重要。所以也许你可以使用 $date = new DateTime('00:00');
【解决方案3】:

这是我处理缺失 H、M 或 S 的解决方案(测试 video with a reported length of 1:00:01,您会看到其他答案的问题)。仅秒显示为 0:01,但如果您想更改它,只需将最后一个 else 更改为 elseif($M>0) 并添加一个 else 秒,例如else { return ":$S" }

// convert youtube v3 api duration e.g. PT1M3S to HH:MM:SS
// updated to handle videos days long e.g. P1DT1M3S
function covtime($yt){
    $yt=str_replace(['P','T'],'',$yt);
    foreach(['D','H','M','S'] as $a){
        $pos=strpos($yt,$a);
        if($pos!==false) ${$a}=substr($yt,0,$pos); else { ${$a}=0; continue; }
        $yt=substr($yt,$pos+1);
    }
    if($D>0){
        $M=str_pad($M,2,'0',STR_PAD_LEFT);
        $S=str_pad($S,2,'0',STR_PAD_LEFT);
        return ($H+(24*$D)).":$M:$S"; // add days to hours
    } elseif($H>0){
        $M=str_pad($M,2,'0',STR_PAD_LEFT);
        $S=str_pad($S,2,'0',STR_PAD_LEFT);
        return "$H:$M:$S";
    } else {
        $S=str_pad($S,2,'0',STR_PAD_LEFT);
        return "$M:$S";
    }
}

【讨论】:

  • “YouTube API 持续时间时间戳”难题的最佳解决方案。在所有情况下都经过测试和工作。
  • 视频 ID 失败:WBu2pJpgKEo。 contentDetails.duration = P1DT3H8S 来自data api docs:“如果视频长度至少为一天,则字母 P 和 T 是分开的,值的格式是 P#DT#H#M#S。 " 所以,这里有一个修正:$yt = str_replace('P', '', $yt); $yt = str_replace('T', '', $yt); 否则很好的解决方案!编辑:另外,处理D 的情况是必要的,但用函数的当前设置来实现是微不足道的。
  • 我在 Swift here 中做了一个实现,翻译成 PHP 应该不会太难。
【解决方案4】:

您应该在创建 $parts 变量后查看它。

var_dump($parts);

将该输出与您定义变量的方式进行比较。它应该在那之后非常明显地脱颖而出。

我想我的下一个问题是您期望输入时间字符串的哪些变化以及您将进行哪些验证?您要处理的输入格式的变化会影响实际编写的代码的复杂性。

编辑: 这是一个更新的函数,用于处理缺失的数值(如果省略小时或分钟)和超过 60 的秒/小时(不确定这是否会发生)。这不会验证数字的标签:

  • 1 个数字:假设是秒
  • 2 个数字:假设是分、秒
  • 3 个或更多数字:假设前 3 个数字是小时、分钟、秒(忽略其他数字)

可以添加更多验证来验证输入字符串。

<?php
function covtime($youtube_time) {
    preg_match_all('/(\d+)/',$youtube_time,$parts);

    // Put in zeros if we have less than 3 numbers.
    if (count($parts[0]) == 1) {
        array_unshift($parts[0], "0", "0");
    } elseif (count($parts[0]) == 2) {
        array_unshift($parts[0], "0");
    }

    $sec_init = $parts[0][2];
    $seconds = $sec_init%60;
    $seconds_overflow = floor($sec_init/60);

    $min_init = $parts[0][1] + $seconds_overflow;
    $minutes = ($min_init)%60;
    $minutes_overflow = floor(($min_init)/60);

    $hours = $parts[0][0] + $minutes_overflow;

    if($hours != 0)
        return $hours.':'.$minutes.':'.$seconds;
    else
        return $minutes.':'.$seconds;
}

【讨论】:

【解决方案5】:

这是我的解决方案,测试完成!

preg_match_all("/PT(\d+H)?(\d+M)?(\d+S)?/", $duration, $matches);

$hours   = strlen($matches[1][0]) == 0 ? 0 : substr($matches[1][0], 0, strlen($matches[1][0]) - 1);
$minutes = strlen($matches[2][0]) == 0 ? 0 : substr($matches[2][0], 0, strlen($matches[2][0]) - 1);
$seconds = strlen($matches[3][0]) == 0 ? 0 : substr($matches[3][0], 0, strlen($matches[3][0]) - 1);

return 3600 * $hours + 60 * $minutes + $seconds;

【讨论】:

    【解决方案6】:

    我使用了两个类,一个调用 YouTube API,一个转换时间。这里简化了。

    如您所见,YouTubeGet 是一个静态类,但并非必须如此。但是,由于 DateInterval 的工作方式(正在扩展),YouTubeDateInterval 必须是一个实例。

    class YouTubeGet{
    static public function get_duration($video_id, $api_key){
            // $youtube_api_key
            $url = "https://www.googleapis.com/youtube/v3/videos?id={$video_id}&part=contentDetails&key={$api_key}";
            // Get and convert. This example uses wordpress wp_remote_get()
            // this could be replaced by file_get_contents($url);
            $response = wp_remote_get($url);
    
            // if using file_get_contents(), then remove ['body']
            $result = json_decode($response['body'], true);
            // I've converted to an array, but this works fine as an object
            if(isset($result['items'][0]['contentDetails']['duration'])){
                $duration = $result['items'][0]['contentDetails']['duration'];
                return self::convtime($duration);
            }
            return false;
        }
    
        static protected function convtime($youtube_time){
            $time = new YouTubeDateInterval($youtube_time);        
            return $time->to_seconds();
        }   
    
    }
    
    class YouTubeDateInterval extends DateInterval {
        public function to_seconds() 
          { 
            return ($this->y * 365 * 24 * 60 * 60) + 
                   ($this->m * 30 * 24 * 60 * 60) + 
                   ($this->d * 24 * 60 * 60) + 
                   ($this->h * 60 * 60) + 
                   ($this->i * 60) + 
                   $this->s; 
          } 
    }
    

    用法是将 iso 8601 日期传递给 YouTubeDateInterval。

    $time = new YouTubeDateInterval('PT2H34M25S');
    $duration_in_seconds = $time->to_seconds();
    

    或通过 YouTube 获取 api 和视频 id 密钥

    $duration_in_seconds = YouTubeGet::get_duration('videoIdString','YouTubeApiKeyString');
    

    【讨论】:

      【解决方案7】:

      试试这个会给你几秒钟的持续时间

      function video_length($youtube_time)
      {
          $duration = new \DateInterval($youtube_time);
          return $duration->h  * 3600 + $duration->i  * 60  + $duration->s;
      }
      

      【讨论】:

        【解决方案8】:
        $duration = new \DateInterval($data['items'][0]['contentDetails']['duration']);
        echo $duration->format('%H:%i:%s');
        

        【讨论】:

          【解决方案9】:

          这里是获取、转换和显示视频时长的完整代码

          $vidkey = "           " ; // for example: cHPMH26sw2f
          $apikey = "xxxxxxxxxxxx" ;
          
          $dur = file_get_contents("https://www.googleapis.com/youtube/v3/videos?part=contentDetails&id=$vidkey&key=$apikey");
          $VidDuration =json_decode($dur, true);
          foreach ($VidDuration['items'] as $vidTime) 
          {
          $VidDuration= $vidTime['contentDetails']['duration'];
          }
          // convert duration from ISO to M:S
          $date = new DateTime('2000-01-01');
          $date->add(new DateInterval($VidDuration));
          echo $date->format('i:s') ;
          

          用您的 API 密钥替换 xxxxxxx 结果:13:07

          【讨论】:

            【解决方案10】:

            试试下面的功能:

            function covtime($youtube_time) 
            {
                $hours = '0';
                $minutes = '0';
                $seconds = '0';
            
                $hIndex = strpos($youtube_time, 'H');
                $mIndex = strpos($youtube_time, 'M');
                $sIndex = strpos($youtube_time, 'S');
                $length = strlen($youtube_time);
                if($hIndex > 0)
                {
                    $hours = substr($youtube_time, 2, ($hIndex - 2));
                }
                if($mIndex > 0)
                {
                    if($hIndex > 0)
                    {
                        $minutes = substr($youtube_time, ($hIndex + 1), ($mIndex - ($hIndex + 1)));
                    }      
                    else
                    {
                        $minutes = substr($youtube_time, 2, ($mIndex - 2));
                    }
                }
                if($sIndex > 0)
                {
                    if($mIndex > 0)
                    {
                        $seconds = substr($youtube_time, ($mIndex + 1), ($sIndex - ($mIndex + 1)));
                    }
                    else if($hIndex > 0)
                    {
                        $seconds = substr($youtube_time, ($hIndex + 1), ($sIndex - ($hIndex + 1)));
                    }      
                    else
                    {
                        $seconds = substr($youtube_time, 2, ($sIndex - 2));
                    }
                }
                return $hours.":".$minutes.":".$seconds;        
            }
            

            【讨论】:

              【解决方案11】:

              你可以试试这个——

              function covtime($youtube_time){
                  $start = new DateTime('@0'); // Unix epoch
                  $start->add(new DateInterval($youtube_time));
                  if (strlen($youtube_time)>8)
                  {
                  return $start->format('g:i:s');
              }   else {
              	return $start->format('i:s');
              }
              }

              【讨论】:

                【解决方案12】:

                DateTime 和 DateInterval 在 Yii 或某些 php 版本中不起作用。 所以这是我的解决方案。它和我一起工作。

                function convertTime($time){        
                    if ($time > 0){
                        $time_result = '';
                        $hours = intval($time / 3600);
                        if ($hours > 0)
                            $time_result = $time_result.$hours.':';
                        $time = $time % 3600;
                        $minutes = intval($time / 60);
                        $seconds = $time % 60;
                        $time_result = $time_result.(($minutes > 9)?$minutes:'0'.$minutes).':';
                        $time_result = $time_result.(($seconds > 9)?$seconds:'0'.$seconds);
                    }else 
                        $time_result = '0:00';        
                
                    return $time_result;
                }
                

                【讨论】:

                  【解决方案13】:

                  为什么复杂。跳出框框思考。

                      $seconds = substr(stristr($length, 'S', true), -2, 2);
                      $seconds = preg_replace("/[^0-9]/", '', $seconds);
                      $minutes =  substr(stristr($length, 'M', true), -2, 2);
                      $minutes = preg_replace("/[^0-9]/", '', $minutes);
                      $hours =  substr(stristr($length, 'H', true), -2, 2);
                      $hours = preg_replace("/[^0-9]/", '', $hours);
                  

                  好的。 preg_replace 并不是真正需要的,但我只是为了保证数字。

                  然后对于我的格式(您可以随意进行,没有限制),

                        if($hours == 0){ 
                        $h= '';
                        }else{ 
                        $h= $hours.':';
                        }
                  
                        if($minutes <10){ 
                        $m= '0'.$minutes.':'; 
                          if($h == ''){
                          $m= $minutes.':'; 
                          }
                            if ($minutes == 0){
                              $m= $minutes;                 
                            }
                        }else{ 
                        $m= $minutes.':';
                        }
                  
                        if($seconds <10){ 
                        $s= '0'.$seconds; 
                        }else{ 
                        $s= $seconds;
                        }
                        $time= $h . $m . $s.'s';
                  

                  【讨论】:

                    猜你喜欢
                    • 2013-11-02
                    • 2021-08-05
                    • 1970-01-01
                    • 2013-05-24
                    • 2014-04-04
                    • 2015-08-24
                    • 2016-06-06
                    • 1970-01-01
                    • 2017-07-14
                    相关资源
                    最近更新 更多