Reputation: 627
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
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
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
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
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
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
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;
}
Upvotes: 1