DurationUnitConverter.java
package com.fasterxml.jackson.datatype.jsr310.util;
import java.time.Duration;
import java.time.temporal.ChronoUnit;
import java.time.temporal.TemporalUnit;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;
import static com.fasterxml.jackson.datatype.jsr310.util.DurationUnitConverter.DurationSerialization.deserializer;
/**
* Handles the conversion of the duration based on the API of {@link Duration} for a restricted set of {@link ChronoUnit}.
* Only the units considered as accurate are supported in this converter since are the only ones capable of handling
* deserialization in a precise manner (see {@link ChronoUnit#isDurationEstimated}).
*
* @since 2.12
*/
public class DurationUnitConverter {
protected static class DurationSerialization {
final Function<Duration, Long> serializer;
final Function<Long, Duration> deserializer;
DurationSerialization(
Function<Duration, Long> serializer,
Function<Long, Duration> deserializer) {
this.serializer = serializer;
this.deserializer = deserializer;
}
static Function<Long, Duration> deserializer(TemporalUnit unit) {
return v -> Duration.of(v, unit);
}
}
private final static Map<String, DurationSerialization> UNITS;
static {
Map<String, DurationSerialization> units = new LinkedHashMap<>();
units.put(ChronoUnit.NANOS.name(), new DurationSerialization(Duration::toNanos, deserializer(ChronoUnit.NANOS)));
units.put(ChronoUnit.MICROS.name(), new DurationSerialization(d -> d.toNanos() / 1000, deserializer(ChronoUnit.MICROS)));
units.put(ChronoUnit.MILLIS.name(), new DurationSerialization(Duration::toMillis, deserializer(ChronoUnit.MILLIS)));
units.put(ChronoUnit.SECONDS.name(), new DurationSerialization(Duration::getSeconds, deserializer(ChronoUnit.SECONDS)));
units.put(ChronoUnit.MINUTES.name(), new DurationSerialization(Duration::toMinutes, deserializer(ChronoUnit.MINUTES)));
units.put(ChronoUnit.HOURS.name(), new DurationSerialization(Duration::toHours, deserializer(ChronoUnit.HOURS)));
units.put(ChronoUnit.HALF_DAYS.name(), new DurationSerialization(d -> d.toHours() / 12, deserializer(ChronoUnit.HALF_DAYS)));
units.put(ChronoUnit.DAYS.name(), new DurationSerialization(Duration::toDays, deserializer(ChronoUnit.DAYS)));
UNITS = units;
}
final DurationSerialization serialization;
DurationUnitConverter(DurationSerialization serialization) {
this.serialization = serialization;
}
public Duration convert(long value) {
return serialization.deserializer.apply(value);
}
public long convert(Duration duration) {
return serialization.serializer.apply(duration);
}
/**
* @return Description of all allowed valued as a sequence of
* double-quoted values separated by comma
*/
public static String descForAllowed() {
return "\"" + UNITS.keySet().stream()
.collect(Collectors.joining("\", \""))
+ "\"";
}
public static DurationUnitConverter from(String unit) {
DurationSerialization def = UNITS.get(unit);
return (def == null) ? null : new DurationUnitConverter(def);
}
}