Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
com.xlrit.gears.base.util.PeriodDurationHelper Maven / Gradle / Ivy
package com.xlrit.gears.base.util;
import java.time.Duration;
import java.time.Period;
import java.time.format.DateTimeParseException;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Stream;
import org.threeten.extra.PeriodDuration;
import static com.google.common.base.Preconditions.checkArgument;
public class PeriodDurationHelper {
public static final String FORMAT_DEFAULT = "long";
private final Pattern pattern;
private final Map unitToIndex;
private final String[] unitsShort;
private final String[] unitsPlural;
private final String[] unitsSingular;
private final String join;
private PeriodDurationHelper(Locale locale) {
this.pattern = createPattern(locale);
this.unitToIndex = createUnitToIndexMap(locale);
this.unitsShort = PeriodDurationHelper.getUnitsShort(locale);
this.unitsPlural = PeriodDurationHelper.getUnitsPlural(locale);
this.unitsSingular = PeriodDurationHelper.getUnitsSingular(locale);
this.join = getJoin(locale);
}
public boolean isValid(String input) {
Matcher matcher = pattern.matcher(input);
String unmatched = matcher.replaceAll("");
return unmatched
.replaceAll(" " + join + " ", "")
.replaceAll("\\s*", "")
.isEmpty();
}
public PeriodDuration parse(String input) {
if (input.startsWith("P")) {
return PeriodDuration.parse(input);
}
if (!isValid(input))
throw new DateTimeParseException("Text cannot be parsed to PeriodDuration", input, 0);
int[] values = new int[NR_UNITS];
Matcher matcher = pattern.matcher(input);
while (matcher.find()) {
String value = matcher.group(1);
String unit = matcher.group(2);
try {
Integer index = unitToIndex.get(unit);
values[index] = Integer.parseInt(value);
}
catch (NumberFormatException e) {
throw new DateTimeParseException("Text cannot be parsed to PeriodDuration", input, 0);
}
}
return create(values);
}
public String format(PeriodDuration value) {
return format(value, FORMAT_DEFAULT);
}
public String format(PeriodDuration value, String format) {
return switch (format) {
case "short" -> formatShort(value);
case "long" -> formatLong(value);
default -> throw new IllegalArgumentException("Unsupported format '" + format + "'");
};
}
public String formatShort(PeriodDuration value) {
Period period = value.getPeriod();
Duration duration = value.getDuration();
Stream partStream = Stream.of(
formatWithShortUnit(YEAR, period.getYears()),
formatWithShortUnit(MONTH, period.getMonths()),
formatWithShortUnit(DAY, period.getDays()),
formatWithShortUnit(HOUR, duration.toHours()),
formatWithShortUnit(MINUTE, duration.toMinutesPart()),
formatWithShortUnit(SECOND, duration.toSecondsPart()),
formatWithShortUnit(MILLIS, duration.toMillisPart())
);
List parts = partStream.filter(periodStr -> !periodStr.isEmpty()).toList();
return String.join(" ", parts);
}
public String formatLong(PeriodDuration value) {
Period period = value.getPeriod();
Duration duration = value.getDuration();
Stream partStream = Stream.of(
formatWithLongUnit(YEAR, period.getYears()),
formatWithLongUnit(MONTH, period.getMonths()),
formatWithLongUnit(DAY, period.getDays()),
formatWithLongUnit(HOUR, duration.toHours()),
formatWithLongUnit(MINUTE, duration.toMinutesPart()),
formatWithLongUnit(SECOND, duration.toSecondsPart()),
formatWithLongUnit(MILLIS, duration.toMillisPart())
);
List parts = partStream.filter(periodStr -> !periodStr.isEmpty()).toList();
if (parts.size() > 1) {
int lastIndex = parts.size() - 1;
String initial = String.join(" ", parts.subList(0, lastIndex));
String last = parts.get(lastIndex);
return initial + " " + join + " " + last;
}
else
return String.join(" ", parts);
}
private String formatWithShortUnit(int unitIndex, long value) {
return value == 0 ? "" : value + unitsShort[unitIndex]; // note no space between value and unit
}
private String formatWithLongUnit(int unitIndex, long value) {
if (value == 0) return "";
if (value == 1) return value + " " + unitsSingular[unitIndex];
return value + " " + unitsPlural[unitIndex];
}
// ================================================================================================================ //
public static PeriodDurationHelper forLanguageTag(String languageTag) {
return new PeriodDurationHelper(StringUtils.toLocale(languageTag));
}
public static PeriodDuration create(int[] values) {
checkArgument(values.length == NR_UNITS);
return create(values[0], values[1], values[2], values[3], values[4], values[5], values[6], values[7]);
}
public static PeriodDuration create(int years, int months, int weeks, int days, int hours, int minutes, int seconds, int millis) {
Period period = Period.of(years, months, weeks * 7 + days);
long totalSeconds = hours * 3600L + minutes * 60L + seconds;
long totalMillis = totalSeconds * 1000L + millis;
Duration duration = Duration.ofMillis(totalMillis);
return PeriodDuration.of(period, duration);
}
public static String getJoin(Locale locale) {
return switch (locale.getLanguage()) {
case "en" -> JOIN_EN;
case "nl" -> JOIN_NL;
default -> throw new IllegalArgumentException(String.format("The period parser does not support language: %s", locale.getLanguage()));
};
}
public static String[] getUnits(Locale locale) {
return switch (locale.getLanguage()) {
case "en" -> UNITS_ALL_EN;
case "nl" -> UNITS_ALL_NL;
default -> throw new IllegalArgumentException(String.format("The period parser does not support language: %s", locale.getLanguage()));
};
}
public static String[] getUnitsShort(Locale locale) {
return switch (locale.getLanguage()) {
case "en" -> UNITS_SHORT_EN;
case "nl" -> UNITS_SHORT_NL;
default -> throw new IllegalArgumentException(String.format("The period parser does not support language: %s", locale.getLanguage()));
};
}
public static String[] getUnitsSingular(Locale locale) {
return switch (locale.getLanguage()) {
case "en" -> UNITS_SINGULAR_EN;
case "nl" -> UNITS_SINGULAR_NL;
default -> throw new IllegalArgumentException(String.format("The period parser does not support language: %s", locale.getLanguage()));
};
}
public static String[] getUnitsPlural(Locale locale) {
return switch (locale.getLanguage()) {
case "en" -> UNITS_PLURAL_EN;
case "nl" -> UNITS_PLURAL_NL;
default -> throw new IllegalArgumentException(String.format("The period parser does not support language: %s", locale.getLanguage()));
};
}
private static Map createUnitToIndexMap(Locale locale) {
String[] sjort = getUnitsShort(locale);
String[] singular = getUnitsSingular(locale);
String[] plural = getUnitsPlural(locale);
if (!(sjort.length == singular.length && singular.length == plural.length))
throw new IllegalStateException("Unit arrays must all have the same length");
Map result = new HashMap<>();
for (int i = 0; i < singular.length; i++) {
result.put(sjort[i], i);
result.put(singular[i], i);
result.put(plural[i], i);
}
return result;
}
private static Pattern createPattern(Locale locale) {
String[] units = getUnits(locale);
String pattern = "(-?[0-9]+)\\s*" + "(" + String.join("|", units) + ")\\b";
return Pattern.compile(pattern, Pattern.CASE_INSENSITIVE);
}
private static final String[] UNITS_SHORT_EN = { "y", "mo", "wk", "d", "h", "min", "s", "ms" };
private static final String[] UNITS_SINGULAR_EN = { "year", "month", "week", "day", "hour", "minute", "second", "millisecond" };
private static final String[] UNITS_PLURAL_EN = { "years", "months", "weeks", "days", "hours", "minutes", "seconds", "milliseconds" };
private static final String[] UNITS_ALL_EN = Stream.of(UNITS_SHORT_EN, UNITS_SINGULAR_EN, UNITS_PLURAL_EN).flatMap(Stream::of).toArray(String[]::new);
private static final String JOIN_EN = "and";
private static final String[] UNITS_SHORT_NL = { "jr", "mnd", "wk", "d", "u", "min", "s", "ms" };
private static final String[] UNITS_SINGULAR_NL = { "jaar", "maand", "week", "dag", "uur", "minuut", "seconde", "milliseconde" };
private static final String[] UNITS_PLURAL_NL = { "jaar", "maanden", "weken", "dagen", "uren", "minuten", "seconden", "milliseconden" };
private static final String[] UNITS_ALL_NL = Stream.of(UNITS_SHORT_NL, UNITS_SINGULAR_NL, UNITS_PLURAL_NL).flatMap(Stream::of).toArray(String[]::new);
private static final String JOIN_NL = "en";
public static final int YEAR = 0;
public static final int MONTH = 1;
public static final int WEEK = 2;
public static final int DAY = 3;
public static final int HOUR = 4;
public static final int MINUTE = 5;
public static final int SECOND = 6;
public static final int MILLIS = 7;
public static final int NR_UNITS = 8;
}