in utils/common/src/main/java/org/apache/brooklyn/util/time/Time.java [559:646]
private static double parseElapsedTimeAsDouble(final String timeStringOrig, String timeString, boolean allowNonUnit, boolean allowNegative) {
if (timeString==null)
throw new NullPointerException("GeneralHelper.parseTimeString cannot parse a null string");
try {
if (allowNonUnit) {
if (timeString.trim().matches(".*[A-Za-z]$")) {
// disable parsing eg 1d as a double
} else {
double d = Double.parseDouble(timeString);
return d;
}
}
} catch (NumberFormatException e) {
log.trace("Unable to parse '%s' as pure number. Trying smart parse.", timeStringOrig, e);
}
boolean isNegative = false;
String multipleUnitsDisallowedBecause = null;
try {
//look for a type marker
timeString = timeString.trim();
int i=0;
if (timeString.startsWith("-")) {
if (allowNegative) {
isNegative = true;
} else {
throw new NumberFormatException("Negation is not permitted on an individual time unit in a duration");
}
timeString = timeString.substring(1);
if (!timeString.startsWith(" ")) {
multipleUnitsDisallowedBecause = "Negation must have a space after it to apply to mulitple units";
} else while (timeString.startsWith(" ")) {
timeString = timeString.substring(1);
}
}
while (i < timeString.length()) {
char c = timeString.charAt(i);
if (c=='.' || Character.isDigit(c)) i++;
else break;
}
String num = timeString.substring(0, i);
timeString = timeString.substring(i).trim();
long multiplier = 0;
if (num.isEmpty()) {
//must be never or something
// TODO does 'never' work?
if (allowNegative && !isNegative && (timeString.equalsIgnoreCase("never") || timeString.equalsIgnoreCase("off") || timeString.equalsIgnoreCase("false"))) {
return -1;
}
throw new NumberFormatException("Invalid duration string '"+timeStringOrig+"'");
}
String s = Strings.getFirstWord(timeString);
timeString = timeString.substring(s.length()).trim();
if (s.equalsIgnoreCase("ms") || s.equalsIgnoreCase("milli") || s.equalsIgnoreCase("millis")
|| s.equalsIgnoreCase("millisec") || s.equalsIgnoreCase("millisecs")
|| s.equalsIgnoreCase("millisecond") || s.equalsIgnoreCase("milliseconds"))
multiplier = 1;
else if (s.equalsIgnoreCase("s") || s.equalsIgnoreCase("sec") || s.equalsIgnoreCase("secs")
|| s.equalsIgnoreCase("second") || s.equalsIgnoreCase("seconds"))
multiplier = 1000;
else if (s.equalsIgnoreCase("m") || s.equalsIgnoreCase("min") || s.equalsIgnoreCase("mins")
|| s.equalsIgnoreCase("minute") || s.equalsIgnoreCase("minutes"))
multiplier = 60*1000;
else if (s.equalsIgnoreCase("h") || s.equalsIgnoreCase("hr") || s.equalsIgnoreCase("hrs")
|| s.equalsIgnoreCase("hour") || s.equalsIgnoreCase("hours"))
multiplier = 60*60*1000;
else if (s.equalsIgnoreCase("d") || s.equalsIgnoreCase("day") || s.equalsIgnoreCase("days"))
multiplier = 24*60*60*1000;
else
throw new NumberFormatException("Unknown unit '"+s+"' in time string '"+timeStringOrig+"'");
double d = Double.parseDouble(num);
double dd = 0;
if (timeString.length()>0) {
if (multipleUnitsDisallowedBecause!=null) {
throw new NumberFormatException(multipleUnitsDisallowedBecause);
}
dd = parseElapsedTimeAsDouble(timeStringOrig, timeString, false, false);
if (dd==-1) {
throw new NumberFormatException("Cannot combine '"+timeString+"' with '"+num+" "+s+"'");
}
}
return (d*multiplier + dd) * (isNegative ? -1 : 1);
} catch (Exception ex) {
if (ex instanceof NumberFormatException) throw (NumberFormatException)ex;
log.trace("Details of parse failure:", ex);
throw new NumberFormatException("Cannot parse time string '"+timeStringOrig+"'");
}
}