Converting Youtube Data API V3 video duration format to seconds in JavaScript/Node.js

后端 未结 15 1990
北海茫月
北海茫月 2020-12-05 07:09

I\'m trying to convert ISO 8601 string to seconds in JS/Node. The best I could come up with was:

function convert_time(duration) {
    var a = duration.match         


        
相关标签:
15条回答
  • 2020-12-05 07:45

    I've written a CoffeeScript variation (you can easily compile it at coffeescript.org when desired)

    DIFFERENCE: the returning duration comes in a human readable format (e.g. 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
    

    I've also implemented this helper function to fill < 10 values with a leading zero:

    String.prototype.zeros = ( x ) ->
        len = @length
        if !x or len >= x then return @
        zeros = ""
        zeros += "0" for [0..(x-len-1)]
        zeros + @
    

    3nj0y!!!

    0 讨论(0)
  • 2020-12-05 07:45

    Here's @redgetan 's solution in ES6.

    I also fixed it for years, weeks and days.

    https://www.digi.com/resources/documentation/digidocs/90001437-13/reference/r_iso_8601_duration_format.htm

    // 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()
    }
    
    0 讨论(0)
  • 2020-12-05 07:47

    I ran into issues with the above solution. I decided to write it as obtuse as possible. I also use my own "getIntValue" in place of parseInt for extra sanity.

    Just thought other searching might appreciate the update.

    Fiddle

        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);
        }
    }
    
    0 讨论(0)
  • 2020-12-05 07:48

    This is not java specific, but i would like to add JAVA snippet as that may helpful to other users

    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);
    
    0 讨论(0)
  • 2020-12-05 07:49
    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;
    }
    

    works for these cases:

    PT1H
    PT23M
    PT45S
    PT1H23M
    PT1H45S
    PT23M45S
    PT1H23M45S
    
    0 讨论(0)
  • 2020-12-05 07:50

    Python

    It works by parsing the input string 1 character at a time, if the character is numerical it simply adds it (string add, not mathematical add) to the current value being parsed. If it is one of 'wdhms' the current value is assigned to the appropriate variable (week, day, hour, minute, second), and value is then reset ready to take the next value. Finally it sum the number of seconds from the 5 parsed values.

    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
    
    0 讨论(0)
提交回复
热议问题