All Downloads are FREE. Search and download functionalities are using the official Maven repository.

net.time4j.StdNormalizer Maven / Gradle / Ivy

There is a newer version: 4.38
Show newest version
/*
 * -----------------------------------------------------------------------
 * Copyright © 2013-2015 Meno Hochschild, 
 * -----------------------------------------------------------------------
 * This file (StdNormalizer.java) is part of project Time4J.
 *
 * Time4J is free software: You can redistribute it and/or modify it
 * under the terms of the GNU Lesser General Public License as published
 * by the Free Software Foundation, either version 2.1 of the License, or
 * (at your option) any later version.
 *
 * Time4J is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with Time4J. If not, see .
 * -----------------------------------------------------------------------
 */

package net.time4j;

import net.time4j.base.MathUtils;
import net.time4j.engine.ChronoUnit;
import net.time4j.engine.Normalizer;
import net.time4j.engine.TimeSpan;

import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;

import static net.time4j.CalendarUnit.*;
import static net.time4j.ClockUnit.*;


/**
 * 

Hilfsobjekt für Standard-Normalisierungen einer Dauer.

* * @author Meno Hochschild * @since 3.1 */ class StdNormalizer implements Normalizer, Comparator> { //~ Statische Felder/Initialisierungen -------------------------------- private static final int MIO = 1000000; private static final int MRD = 1000000000; //~ Instanzvariablen -------------------------------------------------- private final boolean mixed; //~ Konstruktoren ----------------------------------------------------- private StdNormalizer(boolean mixed) { super(); this.mixed = mixed; } //~ Methoden ---------------------------------------------------------- static StdNormalizer ofMixedUnits() { return new StdNormalizer<>(true); } static StdNormalizer ofCalendarUnits() { return new StdNormalizer<>(false); } static StdNormalizer ofClockUnits() { return new StdNormalizer<>(false); } static Comparator> comparator() { return new StdNormalizer<>(false); } @Override public int compare( TimeSpan.Item o1, TimeSpan.Item o2 ) { return compare(o1.getUnit(), o2.getUnit()); } @SuppressWarnings("unchecked") @Override public Duration normalize(TimeSpan timespan) { int count = timespan.getTotalLength().size(); List> items = new ArrayList<>(count); long years = 0, months = 0, weeks = 0, days = 0; long hours = 0, minutes = 0, seconds = 0, nanos = 0; for (int i = 0; i < count; i++) { TimeSpan.Item item = timespan.getTotalLength().get(i); long amount = item.getAmount(); U unit = item.getUnit(); if (unit instanceof CalendarUnit) { switch ((CalendarUnit.class.cast(unit))) { case MILLENNIA: years = MathUtils.safeAdd( MathUtils.safeMultiply(amount, 1000), years ); break; case CENTURIES: years = MathUtils.safeAdd( MathUtils.safeMultiply(amount, 100), years ); break; case DECADES: years = MathUtils.safeAdd( MathUtils.safeMultiply(amount, 10), years ); break; case YEARS: years = MathUtils.safeAdd(amount, years); break; case QUARTERS: months = MathUtils.safeAdd( MathUtils.safeMultiply(amount, 3), months ); break; case MONTHS: months = MathUtils.safeAdd(amount, months); break; case WEEKS: weeks = amount; break; case DAYS: days = amount; break; default: throw new UnsupportedOperationException(unit.toString()); } } else if (unit instanceof ClockUnit) { switch ((ClockUnit.class.cast(unit))) { case HOURS: hours = amount; break; case MINUTES: minutes = amount; break; case SECONDS: seconds = amount; break; case MILLIS: nanos = MathUtils.safeAdd( MathUtils.safeMultiply(amount, MIO), nanos ); break; case MICROS: nanos = MathUtils.safeAdd( MathUtils.safeMultiply(amount, 1000L), nanos ); break; case NANOS: nanos = MathUtils.safeAdd(amount, nanos); break; default: throw new UnsupportedOperationException(unit.toString()); } } else { items.add(TimeSpan.Item.of(amount, unit)); } } long f = 0, s = 0, n = 0, h = 0; if ((hours | minutes | seconds | nanos) != 0) { f = nanos % MRD; seconds = MathUtils.safeAdd(seconds, nanos / MRD); s = seconds % 60; minutes = MathUtils.safeAdd(minutes, seconds / 60); n = minutes % 60; hours = MathUtils.safeAdd(hours, minutes / 60); if (this.mixed) { h = hours % 24; days = MathUtils.safeAdd(days, hours / 24); } else { h = hours; } } U unit; if ((years | months | days) != 0) { long y = MathUtils.safeAdd(years, months / 12); long m = months % 12; long d = MathUtils.safeAdd( MathUtils.safeMultiply(weeks, 7), days ); if (y != 0) { unit = (U) YEARS; items.add(TimeSpan.Item.of(y, unit)); } if (m != 0) { unit = (U) MONTHS; items.add(TimeSpan.Item.of(m, unit)); } if (d != 0) { unit = (U) DAYS; items.add(TimeSpan.Item.of(d, unit)); } } else if (weeks != 0) { unit = (U) WEEKS; items.add(TimeSpan.Item.of(weeks, unit)); } if (h != 0) { unit = (U) HOURS; items.add(TimeSpan.Item.of(h, unit)); } if (n != 0) { unit = (U) MINUTES; items.add(TimeSpan.Item.of(n, unit)); } if (s != 0) { unit = (U) SECONDS; items.add(TimeSpan.Item.of(s, unit)); } if (f != 0) { unit = (U) NANOS; items.add(TimeSpan.Item.of(f, unit)); } return new Duration<>(items, timespan.isNegative()); } static int compare( ChronoUnit u1, ChronoUnit u2 ) { int result = Double.compare(u2.getLength(), u1.getLength()); if ( (result == 0) && !u1.equals(u2) ) { throw new IllegalArgumentException( "Mixing different units of same length not allowed."); } return result; } }