When setting issue estimates in JIRA, you can enter a string like "1d 2h 30m"
and JIRA will translate this (I'm assuming) into a corresponding number of milliseconds.
Is there an available Java library that does this?
I'm using a Spring managed bean that takes a property indicating how often a directory ought to be purged, and I'd like to allow the configuration to开发者_运维技巧 take a human-readable string rather than an explicit number of milliseconds.
Alternatively, if there's a better approach I'm not thinking of, I'd love to hear it.
The parser is not too complex:
public static long parse(String input) {
long result = 0;
String number = "";
for (int i = 0; i < input.length(); i++) {
char c = input.charAt(i);
if (Character.isDigit(c)) {
number += c;
} else if (Character.isLetter(c) && !number.isEmpty()) {
result += convert(Integer.parseInt(number), c);
number = "";
}
}
return result;
}
private static long convert(int value, char unit) {
switch(unit) {
case 'd' : return value * 1000*60*60*24;
case 'h' : return value * 1000*60*60;
case 'm' : return value * 1000*60;
case 's' : return value * 1000;
}
return 0;
}
The code is pretty fault tolerant, it just ignores almost anything it can't decode (and it ignores any whitspace, so it accepts "1d 1s", "1s 1d", "1d20m300s" and so on).
Here's another solution, this one's configurable:
public class TimeReader{
private final Map<String, Long> units = new HashMap<String, Long>();
private static final String UNIT_PATTERN = "\\w+";
private static final Pattern ITEM_PATTERN = Pattern.compile("(\\d+)\\s*("
+ UNIT_PATTERN + ")");
/**
* Add a new time unit.
*
* @param unit
* the unit, e.g. "s"
* @param value
* the unit's modifier value (multiplier from milliseconds, e.g.
* 1000)
* @return self reference for chaining
*/
public TimeReader addUnit(final String unit, final long value){
if(value < 0 || !unit.matches(UNIT_PATTERN)){
throw new IllegalArgumentException();
}
units.put(unit, Long.valueOf(value));
return this;
}
/**
* Parse a string using the defined units.
*
* @return the resulting number of milliseconds
*/
public long parse(final String input){
long value = 0l;
final Matcher matcher = ITEM_PATTERN.matcher(input);
while(matcher.find()){
final long modifier = Long.parseLong(matcher.group(1));
final String unit = matcher.group(2);
if(!units.containsKey(unit)){
throw new IllegalArgumentException("Unrecognized token: "
+ unit);
}
value += units.get(unit).longValue() * modifier;
}
return value;
}
}
Sample Usage:
public static void main(final String[] args){
final TimeReader timeReader =
new TimeReader()
.addUnit("h", 3600000l)
.addUnit("m", 60000l)
.addUnit("s", 1000l);
System.out.println(timeReader.parse("3h, 2m 25 s"));
}
Output:
10945000
Take a look at joda-time's PeriodConverter. I have never used this part of the joda-time library myself, but it looks like it does what you need.
In general, for date/time stuff, look at joda-time first :)
As far as I know, no. I believe you would have to convert those numbers yourself into Calendar (GregorianCalendar) and then from there you can proceed to get the milliseconds, which you probably already know which is why you posted this for the hope of a better answer.
My vote: If no one else can find one perhaps now is a good time to start one yourself and contribute it to the community. :)
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
public class DateTest {
public static void main(String[] args) {
DateFormat df = new SimpleDateFormat("dd'd' HH'h' mm'm'");
try {
Date d = df.parse("1d 2h 30m");
System.out.println(d.getTime());
} catch (ParseException e) {
e.printStackTrace();
}
}
}
Maybe cron expressions would be more helpful for your current task at hand: specyfing how often something should happen. This format is quite flexible, well known and understood. To drive your bean that is doing the periodic chore you could, use the Quartz scheduler, EJB3 timer annotations or the Spring timer annotations.
精彩评论