apoc.util.DurationFormatUtil Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of apoc-common Show documentation
Show all versions of apoc-common Show documentation
Data types package for Neo4j Procedures
package apoc.util;
import org.neo4j.values.storable.DurationFields;
import org.neo4j.values.storable.DurationValue;
import java.util.Arrays;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
import static apoc.util.DateFormatUtil.ELASTIC_PATTERNS;
import static apoc.util.DateFormatUtil.ISO_DURATION_PATTERNS;
import static org.neo4j.values.storable.DurationFields.DAYS;
import static org.neo4j.values.storable.DurationFields.HOURS;
import static org.neo4j.values.storable.DurationFields.MILLISECONDS;
import static org.neo4j.values.storable.DurationFields.MINUTES_OF_HOUR;
import static org.neo4j.values.storable.DurationFields.MONTHS_OF_YEAR;
import static org.neo4j.values.storable.DurationFields.NANOSECONDS;
import static org.neo4j.values.storable.DurationFields.NANOSECONDS_OF_SECOND;
import static org.neo4j.values.storable.DurationFields.QUARTERS_OF_YEAR;
import static org.neo4j.values.storable.DurationFields.SECONDS_OF_MINUTE;
import static org.neo4j.values.storable.DurationFields.WEEKS;
import static org.neo4j.values.storable.DurationFields.YEARS;
public class DurationFormatUtil {
public static String getOrCreateDurationPattern(String format) {
final String formatLower = format.toLowerCase();
return ISO_DURATION_PATTERNS.getOrDefault(formatLower,
ELASTIC_PATTERNS.getOrDefault(formatLower, format)
);
}
public static String getDurationFormat(DurationValue duration, String formatPattern) {
AtomicInteger idx = new AtomicInteger();
// we split the pattern via the escape char `'` and format only odd part,
// to manage patterns like "yy 'years' dd 'days'"
return Arrays.stream(formatPattern.split("'"))
.map(item -> {
if ((idx.getAndIncrement() % 2) == 0) {
return getInnerDurationFormat(duration, item);
}
return item;
})
.collect(Collectors.joining());
}
private static String getInnerDurationFormat(DurationValue duration, String formatter) {
return Pattern.compile(
"(?[yYu])\\1*|(?[dD])\\2*|(?[ML])\\3*|(?[qQ])\\4*|(?[wW])\\5*|" +
"(?[hHkK])\\6*|(?m)\\7*|(?s)\\8*|(?[nS])\\9*|" +
"(?A)\\10*|(?N)\\11|(?I)\\12*"
).matcher(formatter)
.replaceAll(res -> {
final Matcher m = (Matcher) res;
if (m.group("year") != null) {
return getFieldDigit(m, duration, YEARS);
}
if (m.group("day") != null) {
return getFieldDigit(m, duration, DAYS);
}
if (m.group("monthYear") != null) {
return getFieldDigit(m, duration, MONTHS_OF_YEAR);
}
if (m.group("quarterYear") != null) {
return getFieldDigit(m, duration, QUARTERS_OF_YEAR);
}
if (m.group("week") != null) {
return getFieldDigit(m, duration, WEEKS);
}
if (m.group("hour") != null) {
return getFieldDigit(m, duration, HOURS);
}
if (m.group("minHour") != null) {
return getFieldDigit(m, duration, MINUTES_OF_HOUR);
}
if (m.group("secMin") != null) {
return getFieldDigit(m, duration, SECONDS_OF_MINUTE);
}
if (m.group("nsSeconds") != null) {
return getFieldDigit(m, duration, NANOSECONDS_OF_SECOND, true);
}
if (m.group("ms") != null) {
return getFieldDigit(m, duration, MILLISECONDS);
}
if (m.group("ns") != null) {
return getFieldDigit(m, duration, NANOSECONDS);
}
// the letter `I` is used to create nanoseconds in iso format, i.e. with trailing zeros. e.g. '123000' become '123'
if (m.group("iso") != null) {
final String isoNanos = getFieldDigit(m, duration, NANOSECONDS_OF_SECOND)
.replaceAll("(?!$)0+$", "");
return isoNanos.isEmpty() ? "" : ("." + isoNanos);
}
// fallback
return formatter;
});
}
private static String getFieldDigit(Matcher m, DurationValue duration, DurationFields field) {
return getFieldDigit(m, duration, field, false);
}
private static String getFieldDigit(Matcher m, DurationValue duration, DurationFields field, boolean toTruncate) {
long replacement = duration.get(field.propertyKey).value();
// to add padding zeros, e.g. a duration of 15 years with a pattern 'yyyy' will have m.group().length() = 4
// so the string will be String.format("%04d", years>) --> 0015
final String formatted = String.format("%0" + m.group().length() + "d", replacement);
return toTruncate
? formatted.substring(0, m.group().length())
: formatted;
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy