001/* 002 * Copyright (c) 2007-2013, Stephen Colebourne & Michael Nascimento Santos 003 * 004 * All rights reserved. 005 * 006 * Redistribution and use in source and binary forms, with or without 007 * modification, are permitted provided that the following conditions are met: 008 * 009 * * Redistributions of source code must retain the above copyright notice, 010 * this list of conditions and the following disclaimer. 011 * 012 * * Redistributions in binary form must reproduce the above copyright notice, 013 * this list of conditions and the following disclaimer in the documentation 014 * and/or other materials provided with the distribution. 015 * 016 * * Neither the name of JSR-310 nor the names of its contributors 017 * may be used to endorse or promote products derived from this software 018 * without specific prior written permission. 019 * 020 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 021 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 022 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 023 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 024 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 025 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 026 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 027 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 028 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 029 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 030 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 031 */ 032package org.threeten.bp.jdk8; 033 034import static org.threeten.bp.temporal.ChronoField.INSTANT_SECONDS; 035import static org.threeten.bp.temporal.ChronoField.OFFSET_SECONDS; 036import static org.threeten.bp.temporal.ChronoUnit.NANOS; 037 038import java.util.Objects; 039 040import org.threeten.bp.DateTimeException; 041import org.threeten.bp.Instant; 042import org.threeten.bp.LocalTime; 043import org.threeten.bp.format.DateTimeFormatter; 044import org.threeten.bp.temporal.Chrono; 045import org.threeten.bp.temporal.ChronoField; 046import org.threeten.bp.temporal.ChronoLocalDate; 047import org.threeten.bp.temporal.ChronoZonedDateTime; 048import org.threeten.bp.temporal.TemporalAdder; 049import org.threeten.bp.temporal.TemporalAdjuster; 050import org.threeten.bp.temporal.TemporalField; 051import org.threeten.bp.temporal.TemporalQueries; 052import org.threeten.bp.temporal.TemporalQuery; 053import org.threeten.bp.temporal.TemporalSubtractor; 054import org.threeten.bp.temporal.TemporalUnit; 055import org.threeten.bp.temporal.ValueRange; 056 057/** 058 * A temporary class providing implementations that will become default interface 059 * methods once integrated into JDK 8. 060 * 061 * @param <C> the chronology of this date-time 062 */ 063public abstract class DefaultInterfaceChronoZonedDateTime<C extends Chrono<C>> 064 extends DefaultInterfaceTemporal 065 implements ChronoZonedDateTime<C> { 066 067 @Override 068 public ValueRange range(TemporalField field) { 069 if (field instanceof ChronoField) { 070 if (field == INSTANT_SECONDS || field == OFFSET_SECONDS) { 071 return field.range(); 072 } 073 return getDateTime().range(field); 074 } 075 return field.doRange(this); 076 } 077 078 @Override 079 public int get(TemporalField field) { 080 if (field instanceof ChronoField) { 081 switch ((ChronoField) field) { 082 case INSTANT_SECONDS: throw new DateTimeException("Field too large for an int: " + field); 083 case OFFSET_SECONDS: return getOffset().getTotalSeconds(); 084 } 085 return getDateTime().get(field); 086 } 087 return super.get(field); 088 } 089 090 @Override 091 public long getLong(TemporalField field) { 092 if (field instanceof ChronoField) { 093 switch ((ChronoField) field) { 094 case INSTANT_SECONDS: return toEpochSecond(); 095 case OFFSET_SECONDS: return getOffset().getTotalSeconds(); 096 } 097 return getDateTime().getLong(field); 098 } 099 return field.doGet(this); 100 } 101 102 //----------------------------------------------------------------------- 103 @Override 104 public ChronoLocalDate<C> getDate() { 105 return getDateTime().getDate(); 106 } 107 108 @Override 109 public LocalTime getTime() { 110 return getDateTime().getTime(); 111 } 112 113 //----------------------------------------------------------------------- 114 @Override 115 public ChronoZonedDateTime<C> with(TemporalAdjuster adjuster) { 116 return getDate().getChrono().ensureChronoZonedDateTime(super.with(adjuster)); 117 } 118 119 @Override 120 public ChronoZonedDateTime<C> plus(TemporalAdder adjuster) { 121 return getDate().getChrono().ensureChronoZonedDateTime(super.plus(adjuster)); 122 } 123 124 @Override 125 public ChronoZonedDateTime<C> minus(TemporalSubtractor adjuster) { 126 return getDate().getChrono().ensureChronoZonedDateTime(super.minus(adjuster)); 127 } 128 129 @Override 130 public ChronoZonedDateTime<C> minus(long amountToSubtract, TemporalUnit unit) { 131 return getDate().getChrono().ensureChronoZonedDateTime(super.minus(amountToSubtract, unit)); 132 } 133 134 //------------------------------------------------------------------------- 135 @SuppressWarnings("unchecked") 136 @Override 137 public <R> R query(TemporalQuery<R> query) { 138 if (query == TemporalQueries.zoneId()) { 139 return (R) getZone(); 140 } else if (query == TemporalQueries.chrono()) { 141 return (R) getDate().getChrono(); 142 } else if (query == TemporalQueries.precision()) { 143 return (R) NANOS; 144 } else if (query == TemporalQueries.offset()) { 145 return (R) getOffset(); 146 } 147 return super.query(query); 148 } 149 150 //------------------------------------------------------------------------- 151 @Override 152 public Instant toInstant() { 153 return Instant.ofEpochSecond(toEpochSecond(), getTime().getNano()); 154 } 155 156 @Override 157 public long toEpochSecond() { 158 long epochDay = getDate().toEpochDay(); 159 long secs = epochDay * 86400 + getTime().toSecondOfDay(); 160 secs -= getOffset().getTotalSeconds(); 161 return secs; 162 } 163 164 //------------------------------------------------------------------------- 165 @Override 166 public int compareTo(ChronoZonedDateTime<?> other) { 167 int cmp = Long.compare(toEpochSecond(), other.toEpochSecond()); 168 if (cmp == 0) { 169 cmp = getTime().getNano() - other.getTime().getNano(); 170 if (cmp == 0) { 171 cmp = getDateTime().compareTo(other.getDateTime()); 172 if (cmp == 0) { 173 cmp = getZone().getId().compareTo(other.getZone().getId()); 174 if (cmp == 0) { 175 cmp = getDate().getChrono().compareTo(other.getDate().getChrono()); 176 } 177 } 178 } 179 } 180 return cmp; 181 } 182 183 @Override 184 public boolean isAfter(ChronoZonedDateTime<?> other) { 185 long thisEpochSec = toEpochSecond(); 186 long otherEpochSec = other.toEpochSecond(); 187 return thisEpochSec > otherEpochSec || 188 (thisEpochSec == otherEpochSec && getTime().getNano() > other.getTime().getNano()); 189 } 190 191 @Override 192 public boolean isBefore(ChronoZonedDateTime<?> other) { 193 long thisEpochSec = toEpochSecond(); 194 long otherEpochSec = other.toEpochSecond(); 195 return thisEpochSec < otherEpochSec || 196 (thisEpochSec == otherEpochSec && getTime().getNano() < other.getTime().getNano()); 197 } 198 199 @Override 200 public boolean isEqual(ChronoZonedDateTime<?> other) { 201 return toEpochSecond() == other.toEpochSecond() && 202 getTime().getNano() == other.getTime().getNano(); 203 } 204 205 //------------------------------------------------------------------------- 206 @Override 207 public boolean equals(Object obj) { 208 if (this == obj) { 209 return true; 210 } 211 if (obj instanceof ChronoZonedDateTime) { 212 return compareTo((ChronoZonedDateTime<?>) obj) == 0; 213 } 214 return false; 215 } 216 217 @Override 218 public int hashCode() { 219 return getDateTime().hashCode() ^ getOffset().hashCode() ^ Integer.rotateLeft(getZone().hashCode(), 3); 220 } 221 222 //------------------------------------------------------------------------- 223 @Override 224 public String toString() { 225 String str = getDateTime().toString() + getOffset().toString(); 226 if (getOffset() != getZone()) { 227 str += '[' + getZone().toString() + ']'; 228 } 229 return str; 230 } 231 232 @Override 233 public String toString(DateTimeFormatter formatter) { 234 Objects.requireNonNull(formatter, "formatter"); 235 return formatter.print(this); 236 } 237 238}