我正在尝试在JS / Node中将ISO 8601字符串转换为秒。我能想到的最好的是:
function convert_time(duration) {
var a = duration.match(/\d+/g)
var duration = 0
if(a.length == 3) {
duration = duration + parseInt(a[0]) * 3600;
duration = duration + parseInt(a[1]) * 60;
duration = duration + parseInt(a[2]);
}
if(a.length == 2) {
duration = duration + parseInt(a[0]) * 60;
duration = duration + parseInt(a[1]);
}
if(a.length == 1) {
duration = duration + parseInt(a[0]);
}
return duration
}
当我输入诸如“PT48S”,“PT3M20S”或“PT3H2M31S”的字符串时它起作用,但如果字符串是“PT1H11S”则失败。有没有人有更好的主意?
答案 0 :(得分:25)
答案 1 :(得分:24)
<!doctype html>
<html>
<head>
<title>htag</title>
</head>
<body>
<div id="stream"></div>
<script src="http://code.jquery.com/jquery-1.11.2.min.js"></script>
<script src="https://cdn.socket.io/socket.io-1.3.4.js"></script>
<script>
var socket = io(window.location.origin);
socket.on('message', function (text) {
$('#stream').prepend('<p>' + text);
});
</script>
</body>
</html>
适用于这些情况:
function YTDurationToSeconds(duration) {
var match = duration.match(/PT(\d+H)?(\d+M)?(\d+S)?/);
match = match.slice(1).map(function(x) {
if (x != null) {
return x.replace(/\D/, '');
}
});
var hours = (parseInt(match[0]) || 0);
var minutes = (parseInt(match[1]) || 0);
var seconds = (parseInt(match[2]) || 0);
return hours * 3600 + minutes * 60 + seconds;
}
答案 2 :(得分:23)
我建议这个小小的黑客来防止你的问题:
function convert_time(duration) {
var a = duration.match(/\d+/g);
if (duration.indexOf('M') >= 0 && duration.indexOf('H') == -1 && duration.indexOf('S') == -1) {
a = [0, a[0], 0];
}
if (duration.indexOf('H') >= 0 && duration.indexOf('M') == -1) {
a = [a[0], 0, a[1]];
}
if (duration.indexOf('H') >= 0 && duration.indexOf('M') == -1 && duration.indexOf('S') == -1) {
a = [a[0], 0, 0];
}
duration = 0;
if (a.length == 3) {
duration = duration + parseInt(a[0]) * 3600;
duration = duration + parseInt(a[1]) * 60;
duration = duration + parseInt(a[2]);
}
if (a.length == 2) {
duration = duration + parseInt(a[0]) * 60;
duration = duration + parseInt(a[1]);
}
if (a.length == 1) {
duration = duration + parseInt(a[0]);
}
return duration
}
答案 3 :(得分:8)
这是我的解决方案:
function parseDuration(duration) {
var matches = duration.match(/[0-9]+[HMS]/g);
var seconds = 0;
matches.forEach(function (part) {
var unit = part.charAt(part.length-1);
var amount = parseInt(part.slice(0,-1));
switch (unit) {
case 'H':
seconds += amount*60*60;
break;
case 'M':
seconds += amount*60;
break;
case 'S':
seconds += amount;
break;
default:
// noop
}
});
return seconds;
}
答案 4 :(得分:2)
我的解决方案:
function convert_time(duration) {
var total = 0;
var hours = duration.match(/(\d+)H/);
var minutes = duration.match(/(\d+)M/);
var seconds = duration.match(/(\d+)S/);
if (hours) total += parseInt(hours[1]) * 3600;
if (minutes) total += parseInt(minutes[1]) * 60;
if (seconds) total += parseInt(seconds[1]);
return total;
}
答案 5 :(得分:1)
我写了一个CoffeeScript变体(你可以在需要的时候在coffeescript.org上轻松编译)
差异:返回的持续时间以人类可读的格式出现(例如04:20,01:05:48)
String.prototype.parseDuration = ->
m = @.match /[0-9]+[HMS]/g
res = ""
fS = fM = !1
for part in m
unit = part.slice -1
val = part.slice 0, part.length - 1
switch unit
when "H" then res += val.zeros( 2 ) + ":"
when "M"
fM = 1
res += val.zeros( 2 ) + ":"
when "S"
fS = 1
res += if fM then val.zeros 2 else "00:" + val.zeros 2
if !fS then res += "00"
res
我还实现了这个辅助函数来填充&lt;带有前导零的10个值:
String.prototype.zeros = ( x ) ->
len = @length
if !x or len >= x then return @
zeros = ""
zeros += "0" for [0..(x-len-1)]
zeros + @
3nj0y !!!
答案 6 :(得分:1)
您可以找到一个非常简单的PHP解决方案here - How To Convert Youtube API Time (ISO 8601 String Video Duration) to Seconds In PHP - Code
此函数convert_time()接受一个参数作为输入 - Youtube API时间(视频持续时间),采用ISO 8601字符串格式,并以秒为单位返回其持续时间。
function convert_time($str)
{
$n = strlen($str);
$ans = 0;
$curr = 0;
for($i=0; $i<$n; $i++)
{
if($str[$i] == 'P' || $str[$i] == 'T')
{
}
else if($str[$i] == 'H')
{
$ans = $ans + 3600*$curr;
$curr = 0;
}
else if($str[$i] == 'M')
{
$ans = $ans + 60*$curr;
$curr = 0;
}
else if($str[$i] == 'S')
{
$ans = $ans + $curr;
$curr = 0;
}
else
{
$curr = 10*$curr + $str[$i];
}
}
return($ans);
}
测试一些输入:
"PT2M23S" => 143
"PT2M" => 120
"PT28S" => 28
"PT5H22M31S" => 19351
"PT3H" => 10800
"PT1H6M" => 3660
"PT1H6S" => 3606
答案 7 :(得分:0)
我遇到了上述解决方案的问题。我决定尽可能地把它写成钝。我还使用自己的“getIntValue”代替parseInt以获得额外的理智。
只是认为其他搜索可能会感谢更新。
function convertYouTubeTimeFormatToSeconds(timeFormat) {
if ( timeFormat === null || timeFormat.indexOf("PT") !== 0 ) {
return 0;
}
// match the digits into an array
// each set of digits into an item
var digitArray = timeFormat.match(/\d+/g);
var totalSeconds = 0;
// only 1 value in array
if (timeFormat.indexOf('H') > -1 && timeFormat.indexOf('M') == -1 && timeFormat.indexOf('S') == -1) {
totalSeconds += getIntValue(digitArray[0]) * 60 * 60;
}
else if (timeFormat.indexOf('H') == -1 && timeFormat.indexOf('M') > -1 && timeFormat.indexOf('S') == -1) {
totalSeconds += getIntValue(digitArray[0]) * 60;
}
else if (timeFormat.indexOf('H') == -1 && timeFormat.indexOf('M') == -1 && timeFormat.indexOf('S') > -1) {
totalSeconds += getIntValue(digitArray[0]);
}
// 2 values in array
else if (timeFormat.indexOf('H') > -1 && timeFormat.indexOf('M') > -1 && timeFormat.indexOf('S') == -1) {
totalSeconds += getIntValue(digitArray[0]) * 60 * 60;
totalSeconds += getIntValue(digitArray[1]) * 60;
}
else if (timeFormat.indexOf('H') > -1 && timeFormat.indexOf('M') == -1 && timeFormat.indexOf('S') > -1) {
totalSeconds += getIntValue(digitArray[0]) * 60 * 60;
totalSeconds += getIntValue(digitArray[1]);
}
else if (timeFormat.indexOf('H') == -1 && timeFormat.indexOf('M') > -1 && timeFormat.indexOf('S') > -1) {
totalSeconds += getIntValue(digitArray[0]) * 60;
totalSeconds += getIntValue(digitArray[1]);
}
// all 3 values
else if (timeFormat.indexOf('H') > -1 && timeFormat.indexOf('M') > -1 && timeFormat.indexOf('S') > -1) {
totalSeconds += getIntValue(digitArray[0]) * 60 * 60;
totalSeconds += getIntValue(digitArray[1]) * 60;
totalSeconds += getIntValue(digitArray[2]);
}
// console.log(timeFormat, totalSeconds);
return totalSeconds;
}
function getIntValue(value) {
if (value === null) {
return 0;
}
else {
var intValue = 0;
try {
intValue = parseInt(value);
if (isNaN(intValue)) {
intValue = 0;
}
} catch (ex) { }
return Math.floor(intValue);
}
}
答案 8 :(得分:0)
的Python
它通过一次解析输入字符串1个字符来工作,如果字符是数字,它只是将它(字符串添加,而不是数学添加)添加到正在解析的当前值。 如果它是'wdhms'之一,则将当前值分配给适当的变量(周,日,小时,分钟,秒),然后重置值以准备好采用下一个值。 最后,它总结了5个解析值的秒数。
def ytDurationToSeconds(duration): #eg P1W2DT6H21M32S
week = 0
day = 0
hour = 0
min = 0
sec = 0
duration = duration.lower()
value = ''
for c in duration:
if c.isdigit():
value += c
continue
elif c == 'p':
pass
elif c == 't':
pass
elif c == 'w':
week = int(value) * 604800
elif c == 'd':
day = int(value) * 86400
elif c == 'h':
hour = int(value) * 3600
elif c == 'm':
min = int(value) * 60
elif c == 's':
sec = int(value)
value = ''
return week + day + hour + min + sec
答案 9 :(得分:0)
这不是特定于java的,但我想添加JAVA代码段,因为这可能对其他用户有帮助
String duration = "PT1H23M45S";
Pattern pattern = Pattern.compile("PT(?:(\\d+)H)?(?:(\\d+)M)?(?:(\\d+)S)?");
Matcher matcher = pattern.matcher(duration);
long sec = 0;
long min = 0;
long hour = 0;
if (matcher.find())
{
if(matcher.group(1)!=null)
hour = NumberUtils.toInt(matcher.group(1));
if(matcher.group(2)!=null)
min = NumberUtils.toInt(matcher.group(2));
if(matcher.group(3)!=null)
sec = NumberUtils.toInt(matcher.group(3));
}
long totalSec = (hour*3600)+(min*60)+sec;
System.out.println(totalSec);
答案 10 :(得分:0)
假设输入有效,我们可以使用regex exec
方法对字符串进行迭代并依次提取组:
const YOUTUBE_TIME_RE = /(\d+)([HMS])/g;
const YOUTUBE_TIME_UNITS = {
'H': 3600,
'M': 60,
'S': 1
}
/**
* Returns the # of seconds in a youtube time string
*/
function parseYoutubeDate(date: string): number {
let ret = 0;
let match: RegExpExecArray;
while (match = YOUTUBE_TIME_RE.exec(date)) {
ret += (YOUTUBE_TIME_UNITS[match[2]]) * Number(match[1]);
}
return ret;
}
答案 11 :(得分:0)
我知道评估不受欢迎,但这是我能想到的最简单,最快的方法。享受。
function formatDuration(x) {
return eval(x.replace('PT','').replace('H','*3600+').replace('M','*60+').replace('S', '+').slice(0, -1));
}
答案 12 :(得分:0)
这是ES6中的@redgetan解决方案。
我也修复了好几年,几周和几天。
// Copied from:
// https://stackoverflow.com/questions/22148885/converting-youtube-data-api-v3-video-duration-format-to-seconds-in-javascript-no
function parseISO8601Duration(duration) {
const match = duration.match(/P(\d+Y)?(\d+W)?(\d+D)?T(\d+H)?(\d+M)?(\d+S)?/)
// An invalid case won't crash the app.
if (!match) {
console.error(`Invalid YouTube video duration: ${duration}`)
return 0
}
const [
years,
weeks,
days,
hours,
minutes,
seconds
] = match.slice(1).map(_ => _ ? parseInt(_.replace(/\D/, '')) : 0)
return (((years * 365 + weeks * 7 + days) * 24 + hours) * 60 + minutes) * 60 + seconds
}
if (parseISO8601Duration('PT1H') !== 3600) {
throw new Error()
}
if (parseISO8601Duration('PT23M') !== 1380) {
throw new Error()
}
if (parseISO8601Duration('PT45S') !== 45) {
throw new Error()
}
if (parseISO8601Duration('PT1H23M') !== 4980) {
throw new Error()
}
if (parseISO8601Duration('PT1H45S') !== 3645) {
throw new Error()
}
if (parseISO8601Duration('PT1H23M45S') !== 5025) {
throw new Error()
}
if (parseISO8601Duration('P43W5DT5M54S') !== 26438754) {
throw new Error()
}
if (parseISO8601Duration('P1Y43W5DT5M54S') !== 57974754) {
throw new Error()
}
答案 13 :(得分:0)
我认为使用moment.js将是一个更简单的解决方案。但是,如果有人正在寻找自定义解决方案,这里有一个简单的正则表达式适合您:
var regex = /PT(?:(\d+)H)?(?:(\d+)M)?(?:(\d+)S)?/;
var regex_result = regex.exec("PT1H11S"); //Can be anything like PT2M23S / PT2M / PT28S / PT5H22M31S / PT3H/ PT1H6M /PT1H6S
var hours = parseInt(regex_result[1] || 0);
var minutes = parseInt(regex_result[2] || 0);
var seconds = parseInt(regex_result[3] || 0);
var total_seconds = hours * 60 * 60 + minutes * 60 + seconds;
答案 14 :(得分:0)
ES6:
const durationToSec = formatted =>
formatted
.match(/PT(?:(\d*)H)?(?:(\d*)M)?(?:(\d*)S)?/)
.slice(1)
.map(v => (!v ? 0 : v))
.reverse()
.reduce((acc, v, k) => (acc += v * 60 ** k), 0);
答案 15 :(得分:0)
Kotlin 版本:
private val youtubeDurationPattern: Pattern =
Pattern.compile("PT(?:(\\d+)H)?(?:(\\d+)M)?(?:(\\d+)S)?")
fun String.parseDuration(): Int {
val matcher: Matcher = youtubeDurationPattern.matcher(this)
if (!matcher.find()) {
throw IllegalStateException("Cannot parse $this.")
}
val hour = matcher.group(1)?.toInt() ?: 0
val min = matcher.group(2)?.toInt() ?: 0
val sec = matcher.group(3)?.toInt() ?: 0
return hour * 3600 + min * 60 + sec
}
并测试:
@Test
fun testParseDuration() {
assertEquals(10 * 60, "PT10M".parseDuration())
assertEquals(10 * 60 + 30, "PT10M30S".parseDuration())
assertEquals(30, "PT30S".parseDuration())
assertEquals(2 * 3600 + 3 * 60 + 16, "PT2H3M16S".parseDuration())
}