1 /* 2 * Copyright (c) 2007-present, Stephen Colebourne & Michael Nascimento Santos 3 * 4 * All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions are met: 8 * 9 * * Redistributions of source code must retain the above copyright notice, 10 * this list of conditions and the following disclaimer. 11 * 12 * * Redistributions in binary form must reproduce the above copyright notice, 13 * this list of conditions and the following disclaimer in the documentation 14 * and/or other materials provided with the distribution. 15 * 16 * * Neither the name of JSR-310 nor the names of its contributors 17 * may be used to endorse or promote products derived from this software 18 * without specific prior written permission. 19 * 20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 21 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 22 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 23 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 24 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 25 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 26 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 27 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 28 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 29 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 30 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 */ 32 package org.threeten.bp.chrono; 33 34 import static org.threeten.bp.temporal.ChronoUnit.DAYS; 35 import static org.threeten.bp.temporal.ChronoUnit.MONTHS; 36 import static org.threeten.bp.temporal.ChronoUnit.YEARS; 37 38 import java.io.Serializable; 39 import java.util.Arrays; 40 import java.util.Collections; 41 import java.util.List; 42 43 import org.threeten.bp.DateTimeException; 44 import org.threeten.bp.jdk8.Jdk8Methods; 45 import org.threeten.bp.temporal.ChronoField; 46 import org.threeten.bp.temporal.Temporal; 47 import org.threeten.bp.temporal.TemporalAmount; 48 import org.threeten.bp.temporal.TemporalQueries; 49 import org.threeten.bp.temporal.TemporalUnit; 50 import org.threeten.bp.temporal.UnsupportedTemporalTypeException; 51 52 /** 53 * An implementation of {@code ChronoPeriod}. 54 */ 55 final class ChronoPeriodImpl 56 extends ChronoPeriod 57 implements Serializable { 58 59 /** 60 * Serialization version. 61 */ 62 private static final long serialVersionUID = 275618735781L; 63 64 private final Chronology chronology; 65 private final int years; 66 private final int months; 67 private final int days; 68 ChronoPeriodImpl(Chronology chronology, int years, int months, int days)69 public ChronoPeriodImpl(Chronology chronology, int years, int months, int days) { 70 this.chronology = chronology; 71 this.years = years; 72 this.months = months; 73 this.days = days; 74 } 75 76 //------------------------------------------------------------------------- 77 @Override get(TemporalUnit unit)78 public long get(TemporalUnit unit) { 79 if (unit == YEARS) { 80 return years; 81 } 82 if (unit == MONTHS) { 83 return months; 84 } 85 if (unit == DAYS) { 86 return days; 87 } 88 throw new UnsupportedTemporalTypeException("Unsupported unit: " + unit); 89 } 90 91 @Override getUnits()92 public List<TemporalUnit> getUnits() { 93 return Collections.unmodifiableList(Arrays.<TemporalUnit>asList(YEARS, MONTHS, DAYS)); 94 } 95 96 @Override getChronology()97 public Chronology getChronology() { 98 return chronology; 99 } 100 101 //------------------------------------------------------------------------- 102 @Override plus(TemporalAmount amountToAdd)103 public ChronoPeriod plus(TemporalAmount amountToAdd) { 104 if (amountToAdd instanceof ChronoPeriodImpl) { 105 ChronoPeriodImpl amount = (ChronoPeriodImpl) amountToAdd; 106 if (amount.getChronology().equals(getChronology())) { 107 return new ChronoPeriodImpl( 108 chronology, 109 Jdk8Methods.safeAdd(years, amount.years), 110 Jdk8Methods.safeAdd(months, amount.months), 111 Jdk8Methods.safeAdd(days, amount.days)); 112 } 113 } 114 throw new DateTimeException("Unable to add amount: " + amountToAdd); 115 } 116 117 @Override minus(TemporalAmount amountToSubtract)118 public ChronoPeriod minus(TemporalAmount amountToSubtract) { 119 if (amountToSubtract instanceof ChronoPeriodImpl) { 120 ChronoPeriodImpl amount = (ChronoPeriodImpl) amountToSubtract; 121 if (amount.getChronology().equals(getChronology())) { 122 return new ChronoPeriodImpl( 123 chronology, 124 Jdk8Methods.safeSubtract(years, amount.years), 125 Jdk8Methods.safeSubtract(months, amount.months), 126 Jdk8Methods.safeSubtract(days, amount.days)); 127 } 128 } 129 throw new DateTimeException("Unable to subtract amount: " + amountToSubtract); 130 } 131 132 @Override multipliedBy(int scalar)133 public ChronoPeriod multipliedBy(int scalar) { 134 return new ChronoPeriodImpl( 135 chronology, 136 Jdk8Methods.safeMultiply(years, scalar), 137 Jdk8Methods.safeMultiply(months, scalar), 138 Jdk8Methods.safeMultiply(days, scalar)); 139 } 140 141 @Override normalized()142 public ChronoPeriod normalized() { 143 if (chronology.range(ChronoField.MONTH_OF_YEAR).isFixed()) { 144 long monthLength = chronology.range(ChronoField.MONTH_OF_YEAR).getMaximum() - chronology.range(ChronoField.MONTH_OF_YEAR).getMinimum() + 1; 145 long total = years * monthLength + months; 146 int years = Jdk8Methods.safeToInt(total / monthLength); 147 int months = Jdk8Methods.safeToInt(total % monthLength); 148 return new ChronoPeriodImpl(chronology, years, months, days); 149 } 150 return this; 151 } 152 153 @Override addTo(Temporal temporal)154 public Temporal addTo(Temporal temporal) { 155 Jdk8Methods.requireNonNull(temporal, "temporal"); 156 Chronology temporalChrono = temporal.query(TemporalQueries.chronology()); 157 if (temporalChrono != null && chronology.equals(temporalChrono) == false) { 158 throw new DateTimeException("Invalid chronology, required: " + chronology.getId() + ", but was: " + temporalChrono.getId()); 159 } 160 if (years != 0) { 161 temporal = temporal.plus(years, YEARS); 162 } 163 if (months != 0) { 164 temporal = temporal.plus(months, MONTHS); 165 } 166 if (days != 0) { 167 temporal = temporal.plus(days, DAYS); 168 } 169 return temporal; 170 } 171 172 @Override subtractFrom(Temporal temporal)173 public Temporal subtractFrom(Temporal temporal) { 174 Jdk8Methods.requireNonNull(temporal, "temporal"); 175 Chronology temporalChrono = temporal.query(TemporalQueries.chronology()); 176 if (temporalChrono != null && chronology.equals(temporalChrono) == false) { 177 throw new DateTimeException("Invalid chronology, required: " + chronology.getId() + ", but was: " + temporalChrono.getId()); 178 } 179 if (years != 0) { 180 temporal = temporal.minus(years, YEARS); 181 } 182 if (months != 0) { 183 temporal = temporal.minus(months, MONTHS); 184 } 185 if (days != 0) { 186 temporal = temporal.minus(days, DAYS); 187 } 188 return temporal; 189 } 190 191 //------------------------------------------------------------------------- 192 @Override equals(Object obj)193 public boolean equals(Object obj) { 194 if (this == obj) { 195 return true; 196 } 197 if (obj instanceof ChronoPeriodImpl) { 198 ChronoPeriodImpl other = (ChronoPeriodImpl) obj; 199 return years == other.years && months == other.months && 200 days == other.days && chronology.equals(other.chronology); 201 } 202 return false; 203 } 204 205 @Override hashCode()206 public int hashCode() { 207 return chronology.hashCode() + Integer.rotateLeft(years, 16) + Integer.rotateLeft(months, 8) + days; 208 } 209 210 @Override toString()211 public String toString() { 212 if (isZero()) { 213 return chronology + " P0D"; 214 } else { 215 StringBuilder buf = new StringBuilder(); 216 buf.append(chronology).append(' ').append('P'); 217 if (years != 0) { 218 buf.append(years).append('Y'); 219 } 220 if (months != 0) { 221 buf.append(months).append('M'); 222 } 223 if (days != 0) { 224 buf.append(days).append('D'); 225 } 226 return buf.toString(); 227 } 228 } 229 230 } 231