From 0e64b61be487ece819cc0e642dc6d2c7164f7e3f Mon Sep 17 00:00:00 2001 From: Luck Date: Wed, 25 Dec 2019 00:04:39 +0000 Subject: [PATCH] Improve DurationParser regex --- .../common/util/DurationFormatter.java | 58 +++++++++---------- .../luckperms/common/util/DurationParser.java | 39 ++++++------- 2 files changed, 46 insertions(+), 51 deletions(-) diff --git a/common/src/main/java/me/lucko/luckperms/common/util/DurationFormatter.java b/common/src/main/java/me/lucko/luckperms/common/util/DurationFormatter.java index a28fdb081..f4d9c6c40 100644 --- a/common/src/main/java/me/lucko/luckperms/common/util/DurationFormatter.java +++ b/common/src/main/java/me/lucko/luckperms/common/util/DurationFormatter.java @@ -73,12 +73,38 @@ public enum DurationFormatter { } DurationFormatter(int accuracy) { - if (accuracy <= 0) { - throw new IllegalArgumentException("accuracy must be >= 1"); - } this.accuracy = accuracy; } + /** + * Formats {@code duration} as a string. + * + * @param duration the duration + * @return the formatted string + */ + public String format(Duration duration) { + long seconds = duration.getSeconds(); + StringBuilder output = new StringBuilder(); + int outputSize = 0; + + for (Unit unit : this.units) { + long n = seconds / unit.duration; + if (n > 0) { + seconds -= unit.duration * n; + output.append(' ').append(n).append(unit.toString(n)); + outputSize++; + } + if (seconds <= 0 || outputSize >= this.accuracy) { + break; + } + } + + if (output.length() == 0) { + return "0" + this.units[this.units.length - 1].stringPlural; + } + return output.substring(1); + } + protected String formatUnitPlural(ChronoUnit unit) { return " " + unit.name().toLowerCase(); } @@ -104,30 +130,4 @@ public enum DurationFormatter { } } - private String format(long seconds) { - StringBuilder output = new StringBuilder(); - int outputSize = 0; - - for (Unit unit : this.units) { - long n = seconds / unit.duration; - if (n > 0) { - seconds -= unit.duration * n; - output.append(' ').append(n).append(unit.toString(n)); - outputSize++; - } - if (seconds <= 0 || outputSize >= this.accuracy) { - break; - } - } - - if (output.length() == 0) { - return "0" + this.units[this.units.length - 1].stringPlural; - } - return output.substring(1); - } - - public String format(Duration duration) { - return format(duration.getSeconds()); - } - } diff --git a/common/src/main/java/me/lucko/luckperms/common/util/DurationParser.java b/common/src/main/java/me/lucko/luckperms/common/util/DurationParser.java index a25c035e7..a069891ed 100644 --- a/common/src/main/java/me/lucko/luckperms/common/util/DurationParser.java +++ b/common/src/main/java/me/lucko/luckperms/common/util/DurationParser.java @@ -25,9 +25,11 @@ package me.lucko.luckperms.common.util; +import com.google.common.collect.ImmutableMap; + import java.time.Duration; import java.time.temporal.ChronoUnit; -import java.util.Arrays; +import java.util.Map; import java.util.regex.Matcher; import java.util.regex.Pattern; import java.util.stream.Collectors; @@ -38,28 +40,21 @@ import java.util.stream.Collectors; public final class DurationParser { private DurationParser() {} - private static final ChronoUnit[] UNITS = new ChronoUnit[]{ - ChronoUnit.YEARS, - ChronoUnit.MONTHS, - ChronoUnit.WEEKS, - ChronoUnit.DAYS, - ChronoUnit.HOURS, - ChronoUnit.MINUTES, - ChronoUnit.SECONDS - }; + private static final Map UNITS_PATTERNS = ImmutableMap.builder() + .put(ChronoUnit.YEARS, "y(?:ear)?s?") + .put(ChronoUnit.MONTHS, "mo(?:nth)?s?") + .put(ChronoUnit.WEEKS, "w(?:eek)?s?") + .put(ChronoUnit.DAYS, "d(?:ay)?s?") + .put(ChronoUnit.HOURS, "h(?:our|r)?s?") + .put(ChronoUnit.MINUTES, "m(?:inute|in)?s?") + .put(ChronoUnit.SECONDS, "(?:s(?:econd|ec)?s?)?") + .build(); - private static final String PATTERN_STRING = Arrays.stream(UNITS) - .limit(UNITS.length - 1) // skip seconds - .map(unit -> { - if (unit == ChronoUnit.MONTHS) { - return "mo"; - } - // use the first char as the abbreviation - return String.valueOf(Character.toLowerCase(unit.name().charAt(0))); - }) - .map(abbreviation -> "(?:([0-9]+)\\s*" + abbreviation + "[a-z]*[,\\s]*)?") - .collect(Collectors.joining()) - .concat("(?:([0-9]+)\\s*(?:s[a-z]*)?)?"); + private static final ChronoUnit[] UNITS = UNITS_PATTERNS.keySet().toArray(new ChronoUnit[0]); + + private static final String PATTERN_STRING = UNITS_PATTERNS.values().stream() + .map(pattern -> "(?:(\\d+)\\s*" + pattern + "[,\\s]*)?") + .collect(Collectors.joining()); private static final Pattern PATTERN = Pattern.compile(PATTERN_STRING, Pattern.CASE_INSENSITIVE);