Skip to content

Commit

Permalink
improved approximate durations
Browse files Browse the repository at this point in the history
  • Loading branch information
MenoData committed May 24, 2019
1 parent 841dcdb commit d34553d
Showing 1 changed file with 55 additions and 18 deletions.
73 changes: 55 additions & 18 deletions time4j-android/src/main/java/net/time4j/Duration.java
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
import java.io.Serializable;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
Expand Down Expand Up @@ -1532,18 +1533,18 @@ public Duration<U> multipliedBy(int factor) {
*/
public List<Duration<U>> union(TimeSpan<? extends U> timespan) {

Duration<U> merged = merge(this, timespan);
Duration<U> merged = merge(this, timespan);

if (merged == null) {
List<Duration<U>> result = new ArrayList<Duration<U>>();
result.add(this);
Duration<U> empty = ofZero();
Duration<U> other = empty.plus(timespan);
result.add(other);
return Collections.unmodifiableList(result);
}
if (merged == null) {
List<Duration<U>> result = new ArrayList<Duration<U>>();
result.add(this);
Duration<U> empty = ofZero();
Duration<U> other = empty.plus(timespan);
result.add(other);
return Collections.unmodifiableList(result);
}

return Collections.singletonList(merged);
return Collections.singletonList(merged);

}

Expand Down Expand Up @@ -1917,8 +1918,20 @@ public static Normalizer<IsoUnit> approximateSeconds(int steps) {
}

/**
* <p>Creates a normalizer which yields an approximate duration based on the maximum unit
* of the original duration (but not smaller than seconds). </p>
* <p>Creates a normalizer which yields an approximate duration based on the maximum
* relevant unit of the original duration (but not smaller than seconds). </p>
*
* <p>Example: </p>
*
* <pre>
* assertThat(
* Duration.&lt;IsoUnit&gt;of(60 * 60 * 24 * 365, ClockUnit.SECONDS)
* .with(Duration.approximateMaxUnitOnly()),
* is(Duration.of(1, YEARS)));
* </pre>
*
* <p>Note: Due to the nature of this approximation-based normalization, exact results
* cannot be expected. Subsecond components are ignored. </p>
*
* @return new normalizer for fuzzy and approximate durations of only one unit
* (either years, months, days, hours, minutes or seconds)
Expand All @@ -1929,9 +1942,21 @@ public static Normalizer<IsoUnit> approximateSeconds(int steps) {
*/
/*[deutsch]
* <p>Liefert einen Normalisierer, der eine gen&auml;herte Dauer basierend auf der
* gr&ouml;&szlig;ten Zeiteinheit der urspr&uuml;nglichen Dauer (aber nicht kleiner
* gr&ouml;&szlig;ten relevanten Zeiteinheit der urspr&uuml;nglichen Dauer (aber nicht kleiner
* als Sekunden) erstellt. </p>
*
* <p>Beispiel: </p>
*
* <pre>
* assertThat(
* Duration.&lt;IsoUnit&gt;of(60 * 60 * 24 * 365, ClockUnit.SECONDS)
* .with(Duration.approximateMaxUnitOnly()),
* is(Duration.of(1, YEARS)));
* </pre>
*
* <p>Hinweis: Die Natur dieser n&auml;herungsweisen Normalisierung l&auml;sst keine exakten Ergebnisse
* erwarten. Subsekundenanteile werden ignoriert. </p>
*
* @return new normalizer for fuzzy and approximate durations of only one unit
* (either years, months, days, hours, minutes or seconds)
* @see #approximateHours(int)
Expand Down Expand Up @@ -4651,22 +4676,22 @@ private static class ApproximateNormalizer
public Duration<IsoUnit> normalize(TimeSpan<? extends IsoUnit> dur) {

double total = 0.0;
IsoUnit umax = null;
boolean empty = true;

for (int i = 0, n = dur.getTotalLength().size(); i < n; i++) {
Item<? extends IsoUnit> item = dur.getTotalLength().get(i);
total += (item.getAmount() * item.getUnit().getLength());
if ((umax == null) && (item.getAmount() > 0)) {
umax = item.getUnit();
if (item.getAmount() > 0) {
empty = false;
}
}

if (umax == null) {
if (empty) {
return Duration.ofZero();
}

// rounding applied
IsoUnit u = ((this.unit == null) ? umax : this.unit);
IsoUnit u = ((this.unit == null) ? maxUnit(total) : this.unit);
double len = u.getLength() * this.steps;
long value = (long) (total + (len / 2.0)); // half-up
int lint = (int) Math.floor(len);
Expand Down Expand Up @@ -4752,6 +4777,18 @@ private static int safeCast(double num) {

}

private static IsoUnit maxUnit(double total) {

for (IsoUnit unit : Arrays.asList(YEARS, MONTHS, DAYS, HOURS, MINUTES)) {
if (total >= unit.getLength()) {
return unit;
}
}

return ClockUnit.SECONDS;

}

}

}

0 comments on commit d34553d

Please sign in to comment.