diff --git a/src/main/java/net/knarcraft/knarlib/formatting/TimeFormatter.java b/src/main/java/net/knarcraft/knarlib/formatting/TimeFormatter.java index fbc79fa..6689db0 100644 --- a/src/main/java/net/knarcraft/knarlib/formatting/TimeFormatter.java +++ b/src/main/java/net/knarcraft/knarlib/formatting/TimeFormatter.java @@ -29,21 +29,32 @@ public final class TimeFormatter { * @return

The string used for displaying this sign's duration

*/ public static String getDurationString(Translator translator, long duration) { + //Initialize time units once, and only if this method is actually used + if (sortedUnits == null) { + initializeUnits(translator); + } + + //This case is handled separately to avoid a divide by 0 exception if (duration == 0) { return translator.getTranslatedMessage(TranslatableTimeUnit.UNIT_NOW); - } else { - if (sortedUnits == null) { - initializeUnits(translator); - } - for (double unit : sortedUnits) { - if (duration / unit >= 1) { - double units = round(duration / unit); - return formatDurationString(units, translator, timeUnits.get(unit)[units == 1 ? 0 : 1], - (units * 10) % 10 == 0); - } - } - return formatDurationString(duration, translator, TranslatableTimeUnit.UNIT_SECONDS, false); } + + //Loop through all units to find the largest unit less than the remaining duration + for (double unit : sortedUnits) { + if (duration / unit < 1) { + continue; + } + + //Round the remaining units of time to two digits + double units = round(duration / unit); + //Cast to int if the number has no decimals + boolean castToInt = (units * 10) % 10 == 0; + //Select the singular form if the unit is 1, and the plural otherwise + TranslatableMessage translatableUnit = timeUnits.get(unit)[units == 1 ? 0 : 1]; + return formatDurationString(units, translator, translatableUnit, castToInt); + } + //It can be assumed this case only happens between 0 and 1 seconds, thus plural is used + return formatDurationString(duration, translator, TranslatableTimeUnit.UNIT_SECONDS, false); } /** @@ -66,7 +77,7 @@ public final class TimeFormatter { * @return

The formatted duration string

*/ private static String formatDurationString(double duration, Translator translator, - TranslatableTimeUnit translatableMessage, boolean castToInt) { + TranslatableMessage translatableMessage, boolean castToInt) { String durationFormat = translator.getTranslatedMessage(TranslatableTimeUnit.DURATION_FORMAT); durationFormat = replacePlaceholder(durationFormat, "{unit}", translator.getTranslatedMessage(translatableMessage)); @@ -78,45 +89,43 @@ public final class TimeFormatter { * Initializes the mapping of available time units for formatting permission sign duration */ private static void initializeUnits(Translator translator) { - double minute = 60; - double hour = 60 * minute; - double day = 24 * hour; - double week = 7 * day; - double month = 4 * week; - double year = 365 * day; - double decade = 10 * year; - + //Register each time unit with a registered singular and plural translation timeUnits = new HashMap<>(); - registerTimeUnit(translator, decade, TranslatableTimeUnit.UNIT_DECADE, TranslatableTimeUnit.UNIT_DECADES); - registerTimeUnit(translator, year, TranslatableTimeUnit.UNIT_YEAR, TranslatableTimeUnit.UNIT_YEARS); - registerTimeUnit(translator, month, TranslatableTimeUnit.UNIT_MONTH, TranslatableTimeUnit.UNIT_MONTHS); - registerTimeUnit(translator, week, TranslatableTimeUnit.UNIT_WEEK, TranslatableTimeUnit.UNIT_WEEKS); - registerTimeUnit(translator, day, TranslatableTimeUnit.UNIT_DAY, TranslatableTimeUnit.UNIT_DAYS); - registerTimeUnit(translator, hour, TranslatableTimeUnit.UNIT_HOUR, TranslatableTimeUnit.UNIT_HOURS); - registerTimeUnit(translator, minute, TranslatableTimeUnit.UNIT_MINUTE, TranslatableTimeUnit.UNIT_MINUTES); - if (!registerTimeUnit(translator, 1D, TranslatableTimeUnit.UNIT_SECOND, TranslatableTimeUnit.UNIT_SECONDS)) { - throw new IllegalStateException("No translation has been registered for UNIT_SECOND and UNIT_SECONDS"); + registerTimeUnit(translator, 315360000, TranslatableTimeUnit.UNIT_DECADE, TranslatableTimeUnit.UNIT_DECADES); + registerTimeUnit(translator, 31536000, TranslatableTimeUnit.UNIT_YEAR, TranslatableTimeUnit.UNIT_YEARS); + registerTimeUnit(translator, 2419200, TranslatableTimeUnit.UNIT_MONTH, TranslatableTimeUnit.UNIT_MONTHS); + registerTimeUnit(translator, 604800, TranslatableTimeUnit.UNIT_WEEK, TranslatableTimeUnit.UNIT_WEEKS); + registerTimeUnit(translator, 86400, TranslatableTimeUnit.UNIT_DAY, TranslatableTimeUnit.UNIT_DAYS); + registerTimeUnit(translator, 3600, TranslatableTimeUnit.UNIT_HOUR, TranslatableTimeUnit.UNIT_HOURS); + registerTimeUnit(translator, 60, TranslatableTimeUnit.UNIT_MINUTE, TranslatableTimeUnit.UNIT_MINUTES); + boolean registeredSeconds = registerTimeUnit(translator, 1, TranslatableTimeUnit.UNIT_SECOND, + TranslatableTimeUnit.UNIT_SECONDS); + + //As now and seconds are the base units, those must be registered to use getDurationString + if (!registeredSeconds || !hasTranslation(translator, TranslatableTimeUnit.UNIT_NOW)) { + throw new IllegalStateException("A translation is missing for UNIT_SECOND, UNIT_SECONDS or UNIT_NOW"); } + //Make a sorted list from each unit's number of seconds sortedUnits = new ArrayList<>(timeUnits.keySet()); Collections.sort(sortedUnits); Collections.reverse(sortedUnits); } /** - * Registers one time unit + * Registers one time unit if its translations have been registered * * @param translator

The translator to use for checking whether necessary translations have been set

* @param seconds

The amount of seconds the time unit corresponds to

* @param singular

The translatable time unit to use for the singular form

* @param plural

The translatable time unit to use for the plural form

+ * @return

True if the time unit was registered. False if a translation is missing

*/ private static boolean registerTimeUnit(Translator translator, double seconds, TranslatableTimeUnit singular, TranslatableTimeUnit plural) { String singularTranslation = translator.getTranslatedMessage(singular); String pluralTranslation = translator.getTranslatedMessage(plural); - if (singularTranslation != null && !singularTranslation.isBlank() && pluralTranslation != null && - !pluralTranslation.isBlank()) { + if (hasTranslation(translator, singular) && hasTranslation(translator, plural)) { timeUnits.put(seconds, new TranslatableTimeUnit[]{singular, plural}); return true; } else { @@ -124,4 +133,16 @@ public final class TimeFormatter { } } + /** + * Checks whether the given translatable message has a registered translation + * + * @param translator

The translator to check

+ * @param translatableMessage

The translatable message to check

+ * @return

True if a non-empty translation has been registered

+ */ + private static boolean hasTranslation(Translator translator, TranslatableMessage translatableMessage) { + String translation = translator.getTranslatedMessage(translatableMessage); + return translation != null && !translation.isBlank(); + } + }