/* * ----------------------------------------------------------------------- * Copyright © 2013-2014 Meno Hochschild, <http://www.menodata.de/> * ----------------------------------------------------------------------- * This file (RoundingOperator.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 <http://www.gnu.org/licenses/>. * ----------------------------------------------------------------------- */ package net.time4j; import net.time4j.engine.ChronoEntity; import net.time4j.engine.ChronoOperator; /** * <p>Rundungsoperator. </p> * * @author Meno Hochschild * @concurrency <immutable> */ final class RoundingOperator<T extends ChronoEntity<T>> implements ChronoOperator<T> { //~ Instanzvariablen -------------------------------------------------- private final ProportionalElement<?, T> element; private final Boolean up; private final double stepwidth; private final boolean longBased; //~ Konstruktoren ----------------------------------------------------- /** * <p>Konstruktor. </p> * * @param element referencing element * @param up {@code Boolean.TRUE} if ceiling mode, * {@code null} if half rounding * {@code Boolean.FALSE} if floor mode * @param stepwidth controls limits of rounding */ RoundingOperator( final ProportionalElement<?, T> element, Boolean up, int stepwidth ) { super(); this.element = element; this.up = up; this.stepwidth = stepwidth; this.longBased = element.getType().equals(Long.class); } //~ Methoden ---------------------------------------------------------- @Override public T apply(T entity) { double value = entity.get(this.element).doubleValue(); double nv; if (this.up == null) { double high = Math.ceil(value / this.stepwidth) * this.stepwidth; double low = Math.floor(value / this.stepwidth) * this.stepwidth; nv = ((value - low < high - value) ? low : high); } else if (this.up.booleanValue()) { nv = Math.ceil(value / this.stepwidth) * this.stepwidth; } else { nv = Math.floor(value / this.stepwidth) * this.stepwidth; } Number num; if (this.longBased) { num = Long.valueOf((long) nv); } else { num = Integer.valueOf((int) nv); } return entity.with(lenient(this.element, num)); } private static <V extends Number, T extends ChronoEntity<T>> ChronoOperator<T> lenient( ProportionalElement<V, T> element, Number num ) { return element.setLenient(element.getType().cast(num)); } }