Як канвертаваць працягласць Youtube API V3 ў Java

Youtube V3 API выкарыстоўвае ISO8601 фармат часу для апісання працягласці відэа. Нешта любіць «PT1M13S». А цяпер я хачу, каб пераўтварыць радок у лік секунд (напрыклад, 73 у дадзеным выпадку).

Ці ёсць бібліятэка Java можа дапамагчы мне лёгка зрабіць задачу пад Java 6? Ці я павінен зрабіць задачу регулярок самастойна?

<�Моцны> Edit

Нарэшце-то я прымаю адказ ад @Joachim Sauer

Прыклад кода з кодам <> Joda , як паказана ніжэй.

PeriodFormatter formatter = ISOPeriodFormat.standard();
Period p = formatter.parsePeriod("PT1H1M13S");
Seconds s = p.toStandardSeconds();

System.out.println(s.getSeconds());
18
@nhahtdh: гэта не дублікат, таму што сувязныя да адзін апрацоўвае даты радкоў, у той час як гэта радок працягласці!
дададзена аўтар Joachim Sauer, крыніца
На самай справе не разумею, як выкарыстоўваць SimpleDateFormat, каб атрымаць колькасць секунд, у гэтым выпадку гэта не фармат даты. Дзякуй!
дададзена аўтар Willy, крыніца
Ці з'яўляецца гэта дубляваць? Гэтае пытанне для дата-фармату.
дададзена аўтар Willy, крыніца

13 адказы

Joda Time is the go-to library for time-related functions of any kind.

Для гэтага канкрэтнага выпадку ISOPeriodFormat. стандарт() вяртае PeriodFormatter , які можа аналізаваць і фарматаваць гэты фармат.

У выніку чаго аб'ект а Перыяд ( JavaDoc ). Атрыманне фактычнага колькасці секунд затым будзе period.toStandardSeconds (). GetSeconds() , але я прапаную вам проста апрацоўваць працягласць як Перыяд аб'ект (для зручнасці звароту і для бяспекі тыпу).

Edit: a note from future me: this answer is several years old now. Java 8 brought java.time.Duration along which can also parse this format and doesn't require an external library.

15
дададзена
Дзякуй! Я гляджу першы
дададзена аўтар Willy, крыніца

Можа быць, я спазніўся на вечарынку, на самой справе гэта вельмі проста. Хоць могуць быць лепшыя спосабы зрабіць гэта. працягласць у мілісекундах.

public long getDuration() {
    String time = "PT15H12M46S".substring(2);
    long duration = 0L;
    Object[][] indexs = new Object[][]{{"H", 3600}, {"M", 60}, {"S", 1}};
    for(int i = 0; i < indexs.length; i++) {
        int index = time.indexOf((String) indexs[i][0]);
        if(index != -1) {
            String value = time.substring(0, index);
            duration += Integer.parseInt(value) * (int) indexs[i][1] * 1000;
            time = time.substring(value.length() + 1);
        }
    }
    return duration;
}
10
дададзена
Выдатна! мая праблема вырашана.
дададзена аўтар Hassan, крыніца
Як проста, як пекла.
дададзена аўтар Yoraco Gonzales, крыніца

Рашэнне ў Java 8:

Duration.parse(duration).getSeconds()
9
дададзена
ў Android дадаць гэта Gradle: compileOptions {sourceCompatibility JavaVersion.VERSION_1_8 targetCompatibility JavaVersion.VERSION_1_8} (але гэта даступна толькі для 26 API, таму не рэкамендуецца выкарыстоўваць яго ў дадзены момант)
дададзена аўтар user924, крыніца
Вы павінны пераканацца, што ваш JAVA_HOME усталяваны ў JDK8 ці ваш IDE настроены на выкарыстанне JDK8. Я павінен быў дадаць Maven плагіна, каб зрабіць вышэй коду працы ў маім IntelliJ IDEA 17. Plugin URL: mvnrepository.com/artifact/org.apache.maven.plugins/…
дададзена аўтар realPK, крыніца

Вось маё рашэнне

public class MyDateFromat{
    public static void main(String args[]){
        String ytdate = "PT1H1M15S";
        String result = ytdate.replace("PT","").replace("H",":").replace("M",":").replace("S","");
        String arr[]=result.split(":");
        String timeString = String.format("%d:%02d:%02d", Integer.parseInt(arr[0]), Integer.parseInt(arr[1]),Integer.parseInt(arr[2]));
        System.out.print(timeString);       
    }
}

Яна вяртае радок у H: фармат SS, калі вы хочаце канвертаваць ў лічаныя секунды вы можаце выкарыстаць: MM

int timeInSedonds = int timeInSecond = Integer.parseInt(arr[0])*3600 + Integer.parseInt(arr[1])*60 +Integer.parseInt(arr[2])

Заўвага: гэта можа выкінуць выключэнне, так калі ласка, апрацоўваць яго на аснове памеру result.split ( «:»);

3
дададзена
адзначыць, што гэта будзе дакладным для часу, якога не стае H, M або S (напрыклад, PT35M10S або PT1H30S). няма ніякай гарантыі H, M або S з'яўляецца ў поле
дададзена аўтар Angel Koh, крыніца
Самае простае і лепшае рашэнне на StackOverflow для гэтай задачы
дададзена аўтар Karan Sharma, крыніца

Выкарыстанне гэты сайта:

// URL that generated this code:
// http://txt2re.com/index-java.php3?s=PT1M13S&6&3&18&20&-19&-21 

import java.util.regex.*;

class Main
{
  public static void main(String[] args)
  {
    String txt="PT1M13S";

    String re1="(P)";  //Any Single Character 1
    String re2="(T)";  //Any Single Character 2
    String re3="(\\d+)";   //Integer Number 1
    String re4="(M)";  //Any Single Character 3
    String re5="(\\d+)";   //Integer Number 2
    String re6="(S)";  //Any Single Character 4

    Pattern p = Pattern.compile(re1+re2+re3+re4+re5+re6,Pattern.CASE_INSENSITIVE | Pattern.DOTALL);
    Matcher m = p.matcher(txt);
    if (m.find())
    {
        String c1=m.group(1);
        String c2=m.group(2);
        String minutes=m.group(3);//Minutes are here
        String c3=m.group(4);
        String seconds=m.group(5);//Seconds are here
        String c4=m.group(6);
        System.out.print("("+c1.toString()+")"+"("+c2.toString()+")"+"("+minutes.toString()+")"+"("+c3.toString()+")"+"("+seconds.toString()+")"+"("+c4.toString()+")"+"\n");

        int totalSeconds = Integer.parseInt(minutes) * 60 + Integer.parseInt(seconds);
    }
  }
}
1
дададзена
Цьфу, прабачце, але няма. <�Я> Калі </я> вы настойваеце на выкарыстанні рэгулярных выразаў для гэтага, то, па меншай меры, зрабіць гэта адзін, што на самой справе <�я> праверкі , калі ўваход нават аддалена добра сфармаваны. Напрыклад ваш код прымае 00 , а таксама Dumdidledum1And доўгую гісторыю і некаторыя tex3asdf0 .
дададзена аўтар Joachim Sauer, крыніца
Лепш, але вы маглі б спрасціць, што шмат: PT (\\ d +) M \ (\\ d + \) S . Мы толькі клапаціцца аб двух лікавых груп і </код > не павінны сапраўды быць выкарыстаны, так як PT1H3M таксама будзе сапраўдным ISO8601, але маю на ўвазе нешта зусім іншае (1 гадзіну + 3 хвілін).
дададзена аўтар Joachim Sauer, крыніца
Вы не спрабавалі разабраць увесь фармат. Гэта можа толькі разбірае прыклад OP, і адбываецца збой дрэнна ў фактычным выкарыстанні. Працягласць відэа можа быць як хвіліны, і можа быць да тых часоў, як некалькі гадзін.
дададзена аўтар nhahtdh, крыніца
@Joachim: Выпраўлена. См рэдагавання.
дададзена аўтар Simon Arsenault, крыніца

Вы можаце выкарыстоўваць Standart SimpleDateFormat для разбору Радок у Дата і апрацаваць яго адтуль:

DateFormat df = new SimpleDateFormat("'PT'mm'M'ss'S'");
String youtubeDuration = "PT1M13S";
Date d = df.parse(youtubeDuration);
Calendar c = new GregorianCalendar();
c.setTime(d);
c.setTimeZone(TimeZone.getDefault());
System.out.println(c.get(Calendar.MINUTE));
System.out.println(c.get(Calendar.SECOND));
0
дададзена
Я згодны, але ўсё-ткі для простай задачы атрымання секунды з вызначанага фармату яна працуе дастаткова добра.
дададзена аўтар kpentchev, крыніца
Гэта стандартная праблема з рэалізацыяй Java SimpleDateFormat, што зноў-такі можа быць лёгка вырашаная з дапамогай некалькіх асобнікаў, за выключэннем выпадкаў, калі маюцца/няма ніякіх гадзін і/або хвілін. Я не забяспечвае 100% -ный, але адпраўную кропку. Дзе падлучэнне да папярэдняга камэнтару?
дададзена аўтар kpentchev, крыніца
Так, але ён прапускае выкарыстанне трэціх бакоў LIBS, што можа быць перавагай у некаторых сітуацыях.
дададзена аўтар kpentchev, крыніца
Увага: працягласць ня дата, і разглядаючы яго як адзін адкрывае вялікую слоік з чарвякамі (думае, высакосныя, скачок секунды, гадзінныя паясы, ...).
дададзена аўтар Joachim Sauer, крыніца
Акрамя таго, што фармат можа ўключаць у сябе гадзіны, і не абавязкова ўключае ў сябе хвілін ( PT10S і PT1H1M1S будзе сапраўдным, у адпаведнасці з ISO8601).
дададзена аўтар Joachim Sauer, крыніца
Так, але праца гэтай праблемы робіць рашэнне больш і больш складанымі, верагодна, больш складаным, чым напісанне правільнага сінтаксічнага аналізу і <�я> вызначана </я> больш складаным, чым , выкарыстоўваючы правільнага сінтаксічнага аналізу. Я адказваў на Ваш апошні каментар.
дададзена аўтар Joachim Sauer, крыніца
Дзякуй! Я гляджу першы
дададзена аўтар Willy, крыніца

Можа быць, гэта дапаможа хто-то, хто не хоча ні адной бібліятэкі, але простую функцыю,

String duration="PT1H11M14S";

Гэта функцыя,

private String getTimeFromString(String duration) {
   //TODO Auto-generated method stub
    String time = "";
    boolean hourexists = false, minutesexists = false, secondsexists = false;
    if (duration.contains("H"))
        hourexists = true;
    if (duration.contains("M"))
        minutesexists = true;
    if (duration.contains("S"))
        secondsexists = true;
    if (hourexists) {
        String hour = "";
        hour = duration.substring(duration.indexOf("T") + 1,
                duration.indexOf("H"));
        if (hour.length() == 1)
            hour = "0" + hour;
        time += hour + ":";
    }
    if (minutesexists) {
        String minutes = "";
        if (hourexists)
            minutes = duration.substring(duration.indexOf("H") + 1,
                    duration.indexOf("M"));
        else
            minutes = duration.substring(duration.indexOf("T") + 1,
                    duration.indexOf("M"));
        if (minutes.length() == 1)
            minutes = "0" + minutes;
        time += minutes + ":";
    } else {
        time += "00:";
    }
    if (secondsexists) {
        String seconds = "";
        if (hourexists) {
            if (minutesexists)
                seconds = duration.substring(duration.indexOf("M") + 1,
                        duration.indexOf("S"));
            else
                seconds = duration.substring(duration.indexOf("H") + 1,
                        duration.indexOf("S"));
        } else if (minutesexists)
            seconds = duration.substring(duration.indexOf("M") + 1,
                    duration.indexOf("S"));
        else
            seconds = duration.substring(duration.indexOf("T") + 1,
                    duration.indexOf("S"));
        if (seconds.length() == 1)
            seconds = "0" + seconds;
        time += seconds;
    }
    return time;
}
0
дададзена

Я напісаў і выкарыстаў гэты метад, каб атрымаць фактычную працягласць. Спадзяюся, што гэта дапамагае.

private String parseDuration(String duration) {
    duration = duration.contains("PT") ? duration.replace("PT", "") : duration;
    duration = duration.contains("S") ? duration.replace("S", "") : duration;
    duration = duration.contains("H") ? duration.replace("H", ":") : duration;
    duration = duration.contains("M") ? duration.replace("M", ":") : duration;
    String[] split = duration.split(":");
    for(int i = 0; i< split.length; i++){
        String item = split[i];
        split[i] = item.length() <= 1 ? "0"+item : item;
    }
    return TextUtils.join(":", split);
}
0
дададзена

Я зрабіў сам

давайце паспрабуем

import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.

public class YouTubeDurationUtils {
    /**
     * 
     * @param duration
     * @return "01:02:30"
     */
    public static String convertYouTubeDuration(String duration) {
        String youtubeDuration = duration; //"PT1H2M30S";//"PT1M13S";
        Calendar c = new GregorianCalendar();
        try {
            DateFormat df = new SimpleDateFormat("'PT'mm'M'ss'S'");
            Date d = df.parse(youtubeDuration);
            c.setTime(d);
        } catch (ParseException e) {
            try {
                DateFormat df = new SimpleDateFormat("'PT'hh'H'mm'M'ss'S'");
                Date d = df.parse(youtubeDuration);
                c.setTime(d);
            } catch (ParseException e1) {
                try {
                    DateFormat df = new SimpleDateFormat("'PT'ss'S'");
                    Date d = df.parse(youtubeDuration);
                    c.setTime(d);
                } catch (ParseException e2) {
                }
            }
        }
        c.setTimeZone(TimeZone.getDefault());

        String time = "";
        if ( c.get(Calendar.HOUR) > 0 ) {
            if ( String.valueOf(c.get(Calendar.HOUR)).length() == 1 ) {
                time += "0" + c.get(Calendar.HOUR);
            }
            else {
                time += c.get(Calendar.HOUR);
            }
            time += ":";
        }
       //test minute
        if ( String.valueOf(c.get(Calendar.MINUTE)).length() == 1 ) {
            time += "0" + c.get(Calendar.MINUTE);
        }
        else {
            time += c.get(Calendar.MINUTE);
        }
        time += ":";
       //test second
        if ( String.valueOf(c.get(Calendar.SECOND)).length() == 1 ) {
            time += "0" + c.get(Calendar.SECOND);
        }
        else {
            time += c.get(Calendar.SECOND);
        }
        return time ;
    }
}
0
дададзена

У выпадку, калі вы можаце быць упэўнены ў пэўнасці ўваходных дадзеных і не можа выкарыстоўваць рэгулярны выраз, я выкарыстоўваю гэты код (вяртае ў мілісекундах):

Integer parseYTDuration(char[] dStr) {
    Integer d = 0;

    for (int i = 0; i < dStr.length; i++) {
        if (Character.isDigit(dStr[i])) {
            String digitStr = "";
            digitStr += dStr[i];
            i++;
            while (Character.isDigit(dStr[i])) {
                digitStr += dStr[i];
                i++;
            }

            Integer digit = Integer.valueOf(digitStr);

            if (dStr[i] == 'H')
                d += digit * 3600;
            else if (dStr[i] == 'M')
                d += digit * 60;
            else
                d += digit;
        }
    }

    return d * 1000;
}
0
дададзена

Я рэалізаваў гэты метад, і ён працуе да гэтага часу.

private String timeHumanReadable (String youtubeTimeFormat) {
// Gets a PThhHmmMssS time and returns a hh:mm:ss time

    String
            temp = "",
            hour = "",
            minute = "",
            second = "",
            returnString;

   //Starts in position 2 to ignore P and T characters
    for (int i = 2; i < youtubeTimeFormat.length(); ++ i)
    {
       //Put current char in c
        char c = youtubeTimeFormat.charAt(i);

       //Put number in temp
        if (c >= '0' && c <= '9')
            temp = temp + c;
        else
        {
           //Test char after number
            switch (c)
            {
                case 'H' ://Deal with hours
                   //Puts a zero in the left if only one digit is found
                    if (temp.length() == 1) temp = "0" + temp;

                   //This is hours
                    hour = temp;

                    break;

                case 'M' ://Deal with minutes
                   //Puts a zero in the left if only one digit is found
                    if (temp.length() == 1) temp = "0" + temp;

                   //This is minutes
                    minute = temp;

                    break;

                case  'S'://Deal with seconds
                   //Puts a zero in the left if only one digit is found
                    if (temp.length() == 1) temp = "0" + temp;

                   //This is seconds
                    second = temp;

                    break;

            }//switch (c)

           //Restarts temp for the eventual next number
            temp = "";

        }//else

    }//for

    if (hour == "" && minute == "")//Only seconds
        returnString = second;
    else {
        if (hour == "")//Minutes and seconds
            returnString = minute + ":" + second;
        else//Hours, minutes and seconds
            returnString = hour + ":" + minute + ":" + second;
    }

   //Returns a string in hh:mm:ss format
    return returnString; 

}
0
дададзена

І яшчэ адзін доўгі шлях, каб зрабіць тое ж самае.

// PT1H9M24S -->  1:09:24
// PT2H1S"   -->  2:00:01
// PT23M2S   -->  23:02
// PT31S     -->  0:31

public String convertDuration(String duration) {
    duration = duration.substring(2); //del. PT-symbols
    String H, M, S;
   //Get Hours:
    int indOfH = duration.indexOf("H"); //position of H-symbol
    if (indOfH > -1) { //there is H-symbol
        H = duration.substring(0,indOfH);     //take number for hours
        duration = duration.substring(indOfH);//del. hours
        duration = duration.replace("H","");  //del. H-symbol
    } else {
        H = "";
    }
   //Get Minutes:
    int indOfM = duration.indexOf("M"); //position of M-symbol
    if (indOfM > -1) { //there is M-symbol
        M = duration.substring(0,indOfM);     //take number for minutes
        duration = duration.substring(indOfM);//del. minutes
        duration = duration.replace("M","");  //del. M-symbol
       //If there was H-symbol and less than 10 minutes
       //then add left "0" to the minutes
        if (H.length() > 0 && M.length() == 1) {
            M = "0" + M;
        }
    } else {
       //If there was H-symbol then set "00" for the minutes
       //otherwise set "0"
        if (H.length() > 0) {
            M = "00";
        } else {
            M = "0";
        }
    }
   //Get Seconds:
    int indOfS = duration.indexOf("S"); //position of S-symbol
    if (indOfS > -1) { //there is S-symbol
        S = duration.substring(0,indOfS);     //take number for seconds
        duration = duration.substring(indOfS);//del. seconds
        duration = duration.replace("S","");  //del. S-symbol
        if (S.length() == 1) {
            S = "0" + S;
        }
    } else {
        S = "00";
    }
    if (H.length() > 0) {
        return H + ":" +  M + ":" + S;
    } else {
        return M + ":" + S;
    }
}
0
дададзена