可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
how do i convert PT2H34M25S to 2:34:25
I searched and used this code. I'm new to regex can someone explain this ? and help me with my issue
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;
}
but this code only give me HH:MM
so dumb found the solution :
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;
}
回答1:
You should take a look at your $parts
variable after it's created.
var_dump($parts);
Compare that output with how you are defining your variables. It should stand out pretty obviously after that.
I guess my next question after that is what variations of the input time string are you expecting and what validation will you be doing? The variations of the input format you want to handle will affect the complexity of the actual code written.
Edit:
Here is an updated function to handle missing numeric values (if the hours or minutes is omitted) and seconds/hours over 60 (not sure if this will ever happen). This doesn't validate the label for the numbers:
- 1 number: assume it is seconds
- 2 numbers: assume it is minutes, seconds
- 3 or more numbers: assume first 3 numbers are hours, minutes, seconds (ignoring another numbers)
More validation can be added to look into validating the input string.
<?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;
}
回答2:
Using DateTime class
You could use PHP's DateTime class to achieve this. This solution is much simpler, and will work even if the format of the quantities in the string are in different order. A regex solution will (most likely) break in such cases.
In PHP, PT2H34M25S
is a valid date period string, and is understood by the DateTime parser. We then make use of this fact, and just add it to the Unix epoch using add()
method. Then you can format the resulting date to obtain the required results:
function covtime($youtube_time){
$start = new DateTime('@0'); // Unix epoch
$start->add(new DateInterval($youtube_time));
return $start->format('H:i:s');
}
echo covtime('PT2H34M25S');
Demo
回答3:
Both Amal's and Pferate's solutions are great!
However, Amal solution keep giving me 1Hr extra. Below is my solution which is same with Amal but difference approach and this work for me.
$date = new DateTime('1970-01-01');
$date->add(new DateInterval('PT2H34M25S'));
echo $date->format('H:i:s')
datetime->add()
reference
回答4:
Here's my solution which handles missing H, M or S (test a video with a reported length of 1:00:01 and you'll see the problem with other answers). Seconds alone are presented as 0:01, but if you want to change that just change the last else to elseif($M>0)
and add an else for seconds e.g. 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";
}
}
回答5:
This is my solution, test completed!
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:
try this will give you duration by seconds
function video_length($youtube_time)
{
$duration = new \DateInterval($youtube_time);
return $duration->h * 3600 + $duration->i * 60 + $duration->s;
}
回答7:
I use two classes, 1 to call YouTube API, and one to convert the time. here it is simplified.
As you can see, YouTubeGet is a static class, but it does not have to be. YouTubeDateInterval however has to be an instance due to the way that DateInterval works (which is being extended).
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;
}
}
usage is either about passing a iso 8601 date to YouTubeDateInterval.
$time = new YouTubeDateInterval('PT2H34M25S');
$duration_in_seconds = $time->to_seconds();
or passing the YouTubeGet the api and video id key
$duration_in_seconds = YouTubeGet::get_duration('videoIdString','YouTubeApiKeyString');
回答8:
Here is the complete code to get, convert and display the video duration
$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') ;
Replace xxxxxxx with your API Key
Results: 13:07
回答9:
Try the following function:
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;
}
回答10:
You can try this -
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');
}
}
回答11:
DateTime and DateInterval not working in Yii or some php version.
So this is my solution. Its work with me.
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;
}
回答12:
Why the complication. Think outside the box.
$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);
OK. preg_replace is not really needed, but I put it to guarantee only numbers.
Then for my formatting (which you can do however you like without limits),
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';