BlackVoid
BlackVoid

Reputation: 627

String containing time (1H4M10S) converted to seconds

I want to convert a string that looks like this "5W3D10H5M10S" to seconds, the function would return "3319510", when having the previous string as an argument.

I've been thinking of ways to do this, but none of them will be efficient, if anyone could point me in the right direction that would be great.

Upvotes: 2

Views: 171

Answers (6)

Yogendra Singh
Yogendra Singh

Reputation: 34367

EDIT: Little simplified(Less string manipulations)

    DateFormat dateFormat = new SimpleDateFormat("d'D'HH'H'mm'M'ss'S'");
    dateFormat.setTimeZone(TimeZone.getTimeZone("GMT"));
    String dateString = "5W3D10H5M10S";
    String[] dateAndWeek = dateString.split("W");
    Calendar cal = Calendar.getInstance(TimeZone.getTimeZone("GMT"));
    cal.setTime(dateFormat.parse(dateAndWeek[1]));
    cal.add(Calendar.DATE, 1);
    cal.add(Calendar.WEEK_OF_YEAR, Integer.parseInt(dateAndWeek[0]));
    long dateSeconds = cal.getTimeInMillis()/1000;//<--3319510

Upvotes: 0

Kent
Kent

Reputation: 195079

how about translate your string into an expression and let ScriptEngineManager do the calculation?

public void testIt() throws Exception {
        final String in = "5W3D10H5M10S";
        final String after = in.replaceAll("W", "*7D").
                replaceAll("D", "*24H").
                replaceAll("H", "*60M").
                replaceAll("M", "*60+").
                replaceAll("S", "");
        final ScriptEngineManager manager = new ScriptEngineManager();
        final ScriptEngine engine = manager.getEngineByName("js");
        final Object result = engine.eval(after);
        System.out.println("Result:" + String.valueOf(result));
    }

output:

Result:3319510.0

Upvotes: 1

robert
robert

Reputation: 4867

You'll have to tweak this to take care of some boundary conditions and unexpected input...

long wdh(String fmt) {

    long tot = 0;
    int current = 0;
    for (char c : fmt.toCharArray()) {

        if (Character.isDigit(c)) {
            current *= 10;
            current += c - '0';
            continue;
        }

        switch (c) {

            case 'W': tot += WEEK_SECONDS * current; current = 0; continue;
            case 'D': tot += DAY_SECONDS * current; current = 0; continue;
            case 'H': tot += HOUR_SECONDS * current; current = 0; continue;
            case 'M': tot += MINUTE_SECONDS * current; current = 0; continue;
            case 'S': tot += current; break;
        }
    }

    return tot;
}

Upvotes: 0

aleroot
aleroot

Reputation: 72636

You can parse it back with the help of a regular expression, see below an implementation with Java 7 :

    String str = "5W3D10H5M10S";
    String pat = "((?<week>\\d+)W)?((?<day>\\d+)D)?((?<hour>\\d+)H)?((?<min>\\d+)M)?((?<sec>\\d+)S)?";

    Matcher m = Pattern.compile (pat).matcher(str);

    if(m.matches()) {
        int week = Integer.parseInt( m.group("week") );
        int day  = Integer.parseInt( m.group("day") );
                    //And so on ..
    }

Upvotes: 4

Xonar
Xonar

Reputation: 1326

The easiest would be to simple loop through the text until it reaches a non numerical character then take a substring of the previous character location and get that section of text, parse it to int and multiply it by the amount needed according to the character.

Example:

public long getSeconds(String funnyFormat) 
{
    long seconds = 0;
    int lastIndex = 0;
    for(int i = 0;i<funnyFormat.length;i++) {
        char cur = funnyFormat.charAt(i);
        if(cur < '0' && cur > '9') {
            //If it's not a Number
            int seg = Integer.parseInt(funnyFormat.substring(lastIndex,i));
            lastIndex = i+1;
            switch(cur){
            case 'H':
                long += seg*3600;
                break;
            case 'M':
                long += seg*60;
                break;
            case 'S':
                long += seg;
                break;
            //And so on and so forth
            }
        }
    }
}

Upvotes: 0

Sergey Kalinichenko
Sergey Kalinichenko

Reputation: 726599

You can do it with a regexp and a simple loop:

private static final int[] timeMul = new int[] {7, 24, 60, 60, 1};
private static final Pattern rx = Pattern.compile(
    "(?:(\\d+)W)?(?:(\\d+)D)?(?:(\\d+)H)?(?:(\\d+)M)?(?:(\\d+)S)?"
);
public static int getSeconds(String str) {
    Matcher m = rx.matcher(str);
    if (!m.find()) {
        return -1;
    }
    int res = 0;
    for (int i = 0 ; i != m.groupCount() ; i++) {
        String g = m.group(i+1);
        res += g == null ? 0 : Integer.parseInt(g);
        res *= timeMul[i];
    }
    return res;
}

Link to ideone.

Upvotes: 1

Related Questions