diff --git a/src/java/com/threerings/util/TimeUtil.java b/src/java/com/threerings/util/TimeUtil.java index 9c88cc307..eaa5ea7eb 100644 --- a/src/java/com/threerings/util/TimeUtil.java +++ b/src/java/com/threerings/util/TimeUtil.java @@ -1,5 +1,5 @@ // -// $Id: TimeUtil.java,v 1.4 2004/08/27 02:20:36 mdb Exp $ +// $Id$ // // Narya library - tools for developing networked games // Copyright (C) 2002-2004 Three Rings Design, Inc., All Rights Reserved @@ -21,95 +21,128 @@ package com.threerings.util; +import java.util.ArrayList; + /** * Utility for times. */ public class TimeUtil { - /** Granularity constant. */ + /** Time unit constant. */ public static final byte MILLISECOND = 0; - /** Granularity constant. */ + /** Time unit constant. */ public static final byte SECOND = 1; - /** Granularity constant. */ + /** Time unit constant. */ public static final byte MINUTE = 2; - /** Granularity constant. */ + /** Time unit constant. */ public static final byte HOUR = 3; - /** Granularity constant. */ + /** Time unit constant. */ public static final byte DAY = 4; // TODO: Weeks?, months? + protected static final byte MAX_UNIT = DAY; /** * Get a translatable string specifying the magnitude of the specified * duration. Results will be between "1 second" and "X hours", with - * all times rounded to the nearest unit. + * all times rounded to the nearest unit. "0 units" will never be + * displayed, the minimum is 1. */ - public static String getTimeOrderString ( - long duration, byte minGranularity) + public static String getTimeOrderString (long duration, byte minUnit) { - return getTimeOrderString(duration, minGranularity, Byte.MAX_VALUE); + return getTimeOrderString(duration, minUnit, MAX_UNIT); } /** * Get a translatable string specifying the magnitude of the specified * duration, with the units of time bounded between the minimum and - * maximum specified. + * maximum specified. "0 units" will never be returned, the minimum is 1. */ public static String getTimeOrderString ( - long duration, byte minGranularity, byte maxGranularity) + long duration, byte minUnit, byte maxUnit) { // enforce sanity - minGranularity = (byte) Math.min(minGranularity, maxGranularity); + minUnit = (byte) Math.min(minUnit, maxUnit); + maxUnit = (byte) Math.min(maxUnit, MAX_UNIT); - if (minGranularity == MILLISECOND) { - if (duration < 2) { - return "m.1millisecond"; - } else if (duration < 1000 || maxGranularity == MILLISECOND) { - return MessageBundle.tcompose("m.milliseconds", - String.valueOf(duration)); + for (byte uu = MILLISECOND; uu <= MAX_UNIT; uu++) { + int quantity = getQuantityPerUnit(uu); + if ((minUnit <= uu) && (duration < quantity || maxUnit == uu)) { + duration = Math.max(1, duration); + return MessageBundle.tcompose(getTransKey(uu), + String.valueOf(duration)); + } + duration = Math.round(duration / quantity); + } + + // will not happen, because eventually gg will be MAX_UNIT + Thread.dumpStack(); + return null; + } + + /** + * Get a translatable string specifying the duration, down to the + * minimum granularity. + */ + public static String getTimeString (long duration, byte minUnit) + { + // sanity + minUnit = (byte) Math.min(minUnit, MAX_UNIT); + duration = Math.abs(duration); + + ArrayList list = new ArrayList(); + int parts = 0; // how many parts are in the translation string? + for (byte uu = MILLISECOND; uu <= MAX_UNIT; uu++) { + int quantity = getQuantityPerUnit(uu); + if (minUnit <= uu) { + list.add(MessageBundle.tcompose(getTransKey(uu), + String.valueOf(duration % quantity))); + parts++; + } + duration /= quantity; + if (duration <= 0 && parts > 0) { + break; } } - int seconds = (int) Math.round(duration / 1000f); - if (minGranularity <= SECOND) { - if (seconds < 2) { - return "m.1second"; - } else if (seconds < 60 || maxGranularity == SECOND) { - return MessageBundle.tcompose("m.seconds", - String.valueOf(seconds)); - } - } - - int minutes = (int) Math.round(seconds / 60f); - if (minGranularity <= MINUTE) { - if (minutes < 2) { - return "m.1minute"; - } else if (minutes < 60 || maxGranularity == MINUTE) { - return MessageBundle.tcompose("m.minutes", - String.valueOf(minutes)); - } - } - - int hours = (int) Math.round(minutes / 60f); - if (minGranularity <= HOUR) { - if (hours < 2) { - return "m.1hour"; - } else if (hours < 24 || maxGranularity == HOUR) { - return MessageBundle.tcompose("m.hours", String.valueOf(hours)); - } - } - - int days = (int) Math.round(hours / 24f); - if (days < 2) { - return "m.1day"; + if (parts == 1) { + return (String) list.get(0); } else { - return MessageBundle.tcompose("m.days", String.valueOf(days)); + return MessageBundle.compose("m.times_" + parts, list.toArray()); } + } - // TODO: weeks? months? + /** + * Internal method to get the quantity for the specified unit. + * (Not very OO) + */ + protected static int getQuantityPerUnit (byte unit) + { + switch (unit) { + case MILLISECOND: return 1000; + case SECOND: case MINUTE: return 60; + case HOUR: return 24; + default: return -1; + } + } + + /** + * Internal method to get the translation key for the specified unit. + * (Not very OO) + */ + protected static String getTransKey (byte unit) + { + switch (unit) { + case MILLISECOND: return "m.millisecond"; + case SECOND: return "m.second"; + case MINUTE: return "m.minute"; + case HOUR: return "m.hour"; + case DAY: return "m.day"; + default: return null; + } } }