Created
December 3, 2009 21:11
-
-
Save dblevins/248523 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* Licensed to the Apache Software Foundation (ASF) under one or more | |
* contributor license agreements. See the NOTICE file distributed with | |
* this work for additional information regarding copyright ownership. | |
* The ASF licenses this file to You under the Apache License, Version 2.0 | |
* (the "License"); you may not use this file except in compliance with | |
* the License. You may obtain a copy of the License at | |
* | |
* http://www.apache.org/licenses/LICENSE-2.0 | |
* | |
* Unless required by applicable law or agreed to in writing, software | |
* distributed under the License is distributed on an "AS IS" BASIS, | |
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
* See the License for the specific language governing permissions and | |
* limitations under the License. | |
*/ | |
import java.beans.PropertyEditorManager; | |
import java.util.concurrent.TimeUnit; | |
public class Duration { | |
public static enum Unit { | |
// All lowercase so they look good displayed in help | |
NANOSECONDS(1), MICROSECONDS(1000), MILLISECONDS(1000), SECONDS(1000), MINUTES(60), HOURS(60), DAYS(24), WEEKS(7); | |
private int multiplier; | |
Unit(int multiplier) { | |
this.multiplier = multiplier; | |
} | |
public int getMultiplier() { | |
return multiplier; | |
} | |
public long convert(Duration duration) { | |
return convert(duration.getTime(), duration.getUnit()); | |
} | |
public static Unit unit(TimeUnit unit) { | |
switch (unit) { | |
case NANOSECONDS: | |
return Unit.NANOSECONDS; | |
case MICROSECONDS: | |
return Unit.MICROSECONDS; | |
case MILLISECONDS: | |
return Unit.MILLISECONDS; | |
case SECONDS: | |
return Unit.SECONDS; | |
default: | |
throw new IllegalArgumentException("Unknown TimeUnit " + unit); | |
} | |
} | |
public long convert(long time, TimeUnit unit) { | |
return this.convert(time, unit(unit)); | |
} | |
public long convert(long time, Unit unit) { | |
if (this.ordinal() > unit.ordinal()) { | |
Unit[] units = Unit.values(); | |
for (int i = unit.ordinal() + 1; i <= this.ordinal(); i++) { | |
time = time / units[i].getMultiplier(); | |
} | |
} else if (this.ordinal() < unit.ordinal()) { | |
Unit[] units = Unit.values(); | |
for (int i = unit.ordinal(); i > this.ordinal(); i--) { | |
time = time * units[i].getMultiplier(); | |
} | |
} | |
return time; | |
} | |
} | |
private long time; | |
private Unit unit = Unit.MILLISECONDS; | |
public Duration() { | |
} | |
public Duration(long time, Unit unit) { | |
if (unit == null) throw new NullPointerException("unit"); | |
this.time = time; | |
this.unit = unit; | |
} | |
public Duration(String string) { | |
parse(string, this); | |
} | |
public Duration to(Unit unit) { | |
return new Duration(unit.convert(this.time, this.unit), unit); | |
} | |
public Duration to(TimeUnit timeUnit) { | |
return to(Unit.unit(timeUnit)); | |
} | |
public long convert(Unit unit) { | |
return this.unit.convert(this.time, unit); | |
} | |
public long convert(TimeUnit unit) { | |
return this.unit.convert(this.time, unit); | |
} | |
public Unit getUnit() { | |
return unit; | |
} | |
public long getTime() { | |
return time; | |
} | |
public boolean equals(Object o) { | |
if (this == o) return true; | |
if (o == null || getClass() != o.getClass()) return false; | |
final Duration that = (Duration) o; | |
Unit base = Unit.values()[Math.min(this.getUnit().ordinal(), that.getUnit().ordinal())]; | |
long a = base.convert(this.getTime(), this.getUnit()); | |
long b = base.convert(that.getTime(), that.getUnit()); | |
return a == b; | |
} | |
public int hashCode() { | |
int result; | |
result = (int) (time ^ (time >>> 32)); | |
result = 29 * result + (unit != null ? unit.hashCode() : 0); | |
return result; | |
} | |
public String toString() { | |
if (unit == null) { | |
return time + ""; | |
} else { | |
return time + " " + unit; | |
} | |
} | |
public static Duration parse(String text) { | |
Duration d = new Duration(); | |
parse(text, d); | |
return d; | |
} | |
private static void parse(String text, Duration d) { | |
text = text.trim(); | |
StringBuilder t = new StringBuilder(); | |
StringBuilder u = new StringBuilder(); | |
int i = 0; | |
// get the number | |
for (; i < text.length(); i++) { | |
char c = text.charAt(i); | |
if (Character.isDigit(c) || i == 0 && c == '-') { | |
t.append(c); | |
} else { | |
break; | |
} | |
} | |
if (t.length() == 0) { | |
invalidFormat(text); | |
} | |
// skip whitespace | |
for (; i < text.length(); i++) { | |
char c = text.charAt(i); | |
if (Character.isWhitespace(c)) { | |
} else { | |
break; | |
} | |
} | |
// get time unit text part | |
for (; i < text.length(); i++) { | |
char c = text.charAt(i); | |
if (Character.isLetter(c)) { | |
u.append(c); | |
} else { | |
invalidFormat(text); | |
} | |
} | |
d.time = Integer.parseInt(t.toString()); | |
d.unit = parseUnit(u.toString()); | |
} | |
public static Duration parseMultitple(String string) { | |
String[] strings = string.split(",| and "); | |
Duration duration = new Duration(0, Unit.MILLISECONDS); | |
for (String s : strings) { | |
Duration part = new Duration(s); | |
duration = duration.add(part); | |
} | |
return duration; | |
} | |
public Duration add(Duration that) { | |
Unit base = Unit.values()[Math.min(this.getUnit().ordinal(), that.getUnit().ordinal())]; | |
long a = base.convert(this.getTime(), this.getUnit()); | |
long b = base.convert(that.getTime(), that.getUnit()); | |
return new Duration(a + b, base); | |
} | |
public Duration subtract(Duration that) { | |
Unit base = Unit.values()[Math.min(this.getUnit().ordinal(), that.getUnit().ordinal())]; | |
long a = base.convert(this.getTime(), this.getUnit()); | |
long b = base.convert(that.getTime(), that.getUnit()); | |
return new Duration(a - b, base); | |
} | |
private static void invalidFormat(String text) { | |
throw new IllegalArgumentException("Illegal duration format: '" + text + "'. Valid examples are '10s' or '10 seconds'."); | |
} | |
private static Unit parseUnit(String u) { | |
if (u.length() == 0) return Unit.MILLISECONDS; | |
if (u.equalsIgnoreCase("NANOSECONDS")) return Unit.NANOSECONDS; | |
if (u.equalsIgnoreCase("NANOSECOND")) return Unit.NANOSECONDS; | |
if (u.equalsIgnoreCase("NANOS")) return Unit.NANOSECONDS; | |
if (u.equalsIgnoreCase("NANO")) return Unit.NANOSECONDS; | |
if (u.equalsIgnoreCase("NS")) return Unit.NANOSECONDS; | |
if (u.equalsIgnoreCase("MICROSECONDS")) return Unit.MICROSECONDS; | |
if (u.equalsIgnoreCase("MICROSECOND")) return Unit.MICROSECONDS; | |
if (u.equalsIgnoreCase("MICROS")) return Unit.MICROSECONDS; | |
if (u.equalsIgnoreCase("MICRO")) return Unit.MICROSECONDS; | |
if (u.equalsIgnoreCase("MILLISECONDS")) return Unit.MILLISECONDS; | |
if (u.equalsIgnoreCase("MILLISECOND")) return Unit.MILLISECONDS; | |
if (u.equalsIgnoreCase("MILLIS")) return Unit.MILLISECONDS; | |
if (u.equalsIgnoreCase("MILLI")) return Unit.MILLISECONDS; | |
if (u.equalsIgnoreCase("MS")) return Unit.MILLISECONDS; | |
if (u.equalsIgnoreCase("SECONDS")) return Unit.SECONDS; | |
if (u.equalsIgnoreCase("SECOND")) return Unit.SECONDS; | |
if (u.equalsIgnoreCase("SEC")) return Unit.SECONDS; | |
if (u.equalsIgnoreCase("S")) return Unit.SECONDS; | |
if (u.equalsIgnoreCase("MINUTES")) return Unit.MINUTES; | |
if (u.equalsIgnoreCase("MINUTE")) return Unit.MINUTES; | |
if (u.equalsIgnoreCase("MIN")) return Unit.MINUTES; | |
if (u.equalsIgnoreCase("M")) return Unit.MINUTES; | |
if (u.equalsIgnoreCase("HOURS")) return Unit.HOURS; | |
if (u.equalsIgnoreCase("HOUR")) return Unit.HOURS; | |
if (u.equalsIgnoreCase("HRS")) return Unit.HOURS; | |
if (u.equalsIgnoreCase("HR")) return Unit.HOURS; | |
if (u.equalsIgnoreCase("H")) return Unit.HOURS; | |
if (u.equalsIgnoreCase("DAYS")) return Unit.DAYS; | |
if (u.equalsIgnoreCase("DAY")) return Unit.DAYS; | |
if (u.equalsIgnoreCase("D")) return Unit.DAYS; | |
if (u.equalsIgnoreCase("WEEKS")) return Unit.WEEKS; | |
if (u.equalsIgnoreCase("WEEK")) return Unit.WEEKS; | |
if (u.equalsIgnoreCase("W")) return Unit.WEEKS; | |
throw new IllegalArgumentException("Unknown time unit '" + u + "'. Supported units " + Join.join(", ", lowercase(Unit.values()))); | |
} | |
private static String[] lowercase(Unit[] units) { | |
String[] values = new String[units.length]; | |
for (int i = 0; i < units.length; i++) { | |
values[i] = units[i].name().toLowerCase(); | |
} | |
return values; | |
} | |
static { | |
PropertyEditorManager.registerEditor(Duration.class, DurationEditor.class); | |
} | |
public static class DurationEditor extends java.beans.PropertyEditorSupport { | |
public void setAsText(String text) { | |
Duration d = Duration.parse(text); | |
setValue(d); | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* Licensed to the Apache Software Foundation (ASF) under one or more | |
* contributor license agreements. See the NOTICE file distributed with | |
* this work for additional information regarding copyright ownership. | |
* The ASF licenses this file to You under the Apache License, Version 2.0 | |
* (the "License"); you may not use this file except in compliance with | |
* the License. You may obtain a copy of the License at | |
* | |
* http://www.apache.org/licenses/LICENSE-2.0 | |
* | |
* Unless required by applicable law or agreed to in writing, software | |
* distributed under the License is distributed on an "AS IS" BASIS, | |
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
* See the License for the specific language governing permissions and | |
* limitations under the License. | |
*/ | |
import junit.framework.TestCase; | |
import static Duration.Unit.DAYS; | |
import static Duration.Unit.HOURS; | |
import static Duration.Unit.MICROSECONDS; | |
import static Duration.Unit.MILLISECONDS; | |
import static Duration.Unit.MINUTES; | |
import static Duration.Unit.NANOSECONDS; | |
import static Duration.Unit.SECONDS; | |
import static Duration.Unit.WEEKS; | |
public class DurationTest extends TestCase { | |
public void testConstruction() throws Exception { | |
// assertEquals(new Duration(1000, MILLISECONDS), new Duration("1000ms")); | |
// assertEquals(new Duration(1000, MILLISECONDS), new Duration("1000 ms")); | |
// assertEquals(new Duration(1000, MILLISECONDS), new Duration("1000 ms")); | |
// | |
// assertEquals(new Duration(60, SECONDS), new Duration("1m")); | |
// assertEquals(new Duration(3600, SECONDS), new Duration("1h")); | |
// assertEquals(new Duration(86400, SECONDS), new Duration("1d")); | |
// | |
// assertEquals(new Duration(1000, MICROSECONDS), new Duration("1000 microseconds")); | |
// assertEquals(new Duration(1000, NANOSECONDS), new Duration("1000 nanoseconds")); | |
// | |
assertEquals(new Duration(1, MILLISECONDS), new Duration("1")); | |
assertEquals(new Duration(234, MILLISECONDS), new Duration("234")); | |
assertEquals(new Duration(123, MILLISECONDS), new Duration("123")); | |
assertEquals(new Duration(-1, MILLISECONDS), new Duration("-1")); | |
} | |
public void testAddition() throws Exception { | |
Duration a = new Duration(100, MILLISECONDS); | |
Duration b = new Duration(200, MILLISECONDS); | |
assertEquals(new Duration(300, MILLISECONDS), a.add(b)); | |
Duration c = new Duration(2, SECONDS); | |
assertEquals(new Duration(2300, MILLISECONDS), a.add(b).add(c)); | |
} | |
public void testMultiple() throws Exception { | |
assertEquals(new Duration(2300, MILLISECONDS), Duration.parseMultitple("2 seconds and 300 milliseconds")); | |
assertEquals(new Duration(2300, MILLISECONDS), Duration.parseMultitple("2 seconds, 300 milliseconds")); | |
assertEquals(new Duration(2300, MILLISECONDS), Duration.parseMultitple("2 seconds,300 milliseconds")); | |
assertEquals(new Duration(125, SECONDS), Duration.parseMultitple("2 minutes and 5 seconds")); | |
} | |
public void testUnitConversion() throws Exception { | |
assertEquals(2, WEEKS.convert(2, WEEKS)); | |
assertEquals(2 * 7, DAYS.convert(2, WEEKS)); | |
assertEquals(2 * 7 * 24, HOURS.convert(2, WEEKS)); | |
assertEquals(2 * 7 * 24 * 60, MINUTES.convert(2, WEEKS)); | |
assertEquals(2 * 7 * 24 * 60 * 60, SECONDS.convert(2, WEEKS)); | |
assertEquals(2 * 7 * 24 * 60 * 60 * 1000, MILLISECONDS.convert(2, WEEKS)); | |
assertEquals(2 * 1000, MILLISECONDS.convert(2, SECONDS)); | |
assertEquals(2 * 1000 * 1000, MICROSECONDS.convert(2, SECONDS)); | |
assertEquals(2 * 1000 * 1000 * 1000, NANOSECONDS.convert(2, SECONDS)); | |
assertEquals(2, SECONDS.convert(2 * 1000 * 1000 * 1000, NANOSECONDS)); | |
assertEquals(2, SECONDS.convert(2 * 1000 * 1000, MICROSECONDS)); | |
assertEquals(2, SECONDS.convert(2 * 1000, MILLISECONDS)); | |
assertEquals(2, WEEKS.convert(2 * 7 * 24 * 60 * 60 * 1000, MILLISECONDS)); | |
assertEquals(2, WEEKS.convert(2 * 7 * 24 * 60 * 60, SECONDS)); | |
assertEquals(2, WEEKS.convert(2 * 7 * 24 * 60, MINUTES)); | |
assertEquals(2, WEEKS.convert(2 * 7 * 24, HOURS)); | |
assertEquals(2, WEEKS.convert(2 * 7, DAYS)); | |
// The verbose way of doing the above | |
assertEquals(2, new Duration(2, WEEKS).convert(WEEKS).getTime()); | |
assertEquals(2 * 7, new Duration(2, WEEKS).convert(DAYS).getTime()); | |
assertEquals(2 * 7 * 24, new Duration(2, WEEKS).convert(HOURS).getTime()); | |
assertEquals(2 * 7 * 24 * 60, new Duration(2, WEEKS).convert(MINUTES).getTime()); | |
assertEquals(2 * 7 * 24 * 60 * 60, new Duration(2, WEEKS).convert(SECONDS).getTime()); | |
assertEquals(2 * 7 * 24 * 60 * 60 * 1000, new Duration(2, WEEKS).convert(MILLISECONDS).getTime()); | |
assertEquals(2 * 1000, new Duration(2, SECONDS).convert(MILLISECONDS).getTime()); | |
assertEquals(2 * 1000 * 1000, new Duration(2, SECONDS).convert(MICROSECONDS).getTime()); | |
assertEquals(2 * 1000 * 1000 * 1000, new Duration(2, SECONDS).convert(NANOSECONDS).getTime()); | |
assertEquals(2, new Duration(2 * 1000 * 1000 * 1000, NANOSECONDS).convert(SECONDS).getTime()); | |
assertEquals(2, new Duration(2 * 1000 * 1000, MICROSECONDS).convert(SECONDS).getTime()); | |
assertEquals(2, new Duration(2 * 1000, MILLISECONDS).convert(SECONDS).getTime()); | |
assertEquals(2, new Duration(2 * 7 * 24 * 60 * 60 * 1000, MILLISECONDS).convert(WEEKS).getTime()); | |
assertEquals(2, new Duration(2 * 7 * 24 * 60 * 60, SECONDS).convert(WEEKS).getTime()); | |
assertEquals(2, new Duration(2 * 7 * 24 * 60, MINUTES).convert(WEEKS).getTime()); | |
assertEquals(2, new Duration(2 * 7 * 24, HOURS).convert(WEEKS).getTime()); | |
assertEquals(2, new Duration(2 * 7, DAYS).convert(WEEKS).getTime()); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment