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.DAY_OF_MONTH;
035import static org.threeten.bp.temporal.ChronoField.EPOCH_DAY;
036import static org.threeten.bp.temporal.ChronoField.ERA;
037import static org.threeten.bp.temporal.ChronoField.MONTH_OF_YEAR;
038import static org.threeten.bp.temporal.ChronoField.YEAR;
039import static org.threeten.bp.temporal.ChronoField.YEAR_OF_ERA;
040
041import java.util.Objects;
042
043import org.threeten.bp.LocalTime;
044import org.threeten.bp.format.DateTimeFormatter;
045import org.threeten.bp.temporal.Chrono;
046import org.threeten.bp.temporal.ChronoField;
047import org.threeten.bp.temporal.ChronoLocalDate;
048import org.threeten.bp.temporal.ChronoLocalDateTime;
049import org.threeten.bp.temporal.Era;
050import org.threeten.bp.temporal.Temporal;
051import org.threeten.bp.temporal.TemporalAdder;
052import org.threeten.bp.temporal.TemporalAdjuster;
053import org.threeten.bp.temporal.TemporalField;
054import org.threeten.bp.temporal.TemporalQueries;
055import org.threeten.bp.temporal.TemporalQuery;
056import org.threeten.bp.temporal.TemporalSubtractor;
057import org.threeten.bp.temporal.TemporalUnit;
058
059/**
060 * A temporary class providing implementations that will become default interface
061 * methods once integrated into JDK 8.
062 *
063 * @param <C> the chronology of this date-time
064 */
065public abstract class DefaultInterfaceChronoLocalDate<C extends Chrono<C>>
066        extends DefaultInterfaceTemporal
067        implements ChronoLocalDate<C> {
068
069    @Override
070    public Era<C> getEra() {
071        return getChrono().eraOf(get(ERA));
072    }
073
074    @Override
075    public boolean isLeapYear() {
076        return getChrono().isLeapYear(getLong(YEAR));
077    }
078
079    @Override
080    public int lengthOfYear() {
081        return (isLeapYear() ? 366 : 365);
082    }
083
084    @Override
085    public boolean isSupported(TemporalField field) {
086        if (field instanceof ChronoField) {
087            return ((ChronoField) field).isDateField();
088        }
089        return field != null && field.doIsSupported(this);
090    }
091
092    //-------------------------------------------------------------------------
093    @Override
094    public ChronoLocalDate<C> with(TemporalAdjuster adjuster) {
095        return getChrono().ensureChronoLocalDate(super.with(adjuster));
096    }
097
098    @Override
099    public ChronoLocalDate<C> plus(TemporalAdder adjuster) {
100        return getChrono().ensureChronoLocalDate(super.plus(adjuster));
101    }
102
103    @Override
104    public ChronoLocalDate<C> minus(TemporalSubtractor adjuster) {
105        return getChrono().ensureChronoLocalDate(super.minus(adjuster));
106    }
107
108    @Override
109    public ChronoLocalDate<C> minus(long amountToSubtract, TemporalUnit unit) {
110        return getChrono().ensureChronoLocalDate(super.minus(amountToSubtract, unit));
111    }
112
113    //-------------------------------------------------------------------------
114    @Override
115    public Temporal adjustInto(Temporal temporal) {
116        return temporal.with(EPOCH_DAY, toEpochDay());
117    }
118
119    @Override
120    public ChronoLocalDateTime<C> atTime(LocalTime localTime) {
121        return Chrono.dateTime(this, localTime);
122    }
123
124    @Override
125    public <R> R query(TemporalQuery<R> query) {
126        if (query == TemporalQueries.chrono()) {
127            return (R) getChrono();
128        }
129        return super.query(query);
130    }
131
132    @Override
133    public long toEpochDay() {
134        return getLong(EPOCH_DAY);
135    }
136
137    //-------------------------------------------------------------------------
138    @Override
139    public int compareTo(ChronoLocalDate<?> other) {
140        int cmp = Long.compare(toEpochDay(), other.toEpochDay());
141        if (cmp == 0) {
142            cmp = getChrono().compareTo(other.getChrono());
143        }
144        return cmp;
145    }
146
147    @Override
148    public boolean isAfter(ChronoLocalDate<?> other) {
149        return this.toEpochDay() > other.toEpochDay();
150    }
151
152    @Override
153    public boolean isBefore(ChronoLocalDate<?> other) {
154        return this.toEpochDay() < other.toEpochDay();
155    }
156
157    @Override
158    public boolean isEqual(ChronoLocalDate<?> other) {
159        return this.toEpochDay() == other.toEpochDay();
160    }
161
162    //-------------------------------------------------------------------------
163    @Override
164    public boolean equals(Object obj) {
165        if (this == obj) {
166            return true;
167        }
168        if (obj instanceof ChronoLocalDate) {
169            return compareTo((ChronoLocalDate<?>) obj) == 0;
170        }
171        return false;
172    }
173
174    @Override
175    public int hashCode() {
176        long epDay = toEpochDay();
177        return getChrono().hashCode() ^ ((int) (epDay ^ (epDay >>> 32)));
178    }
179
180    //-------------------------------------------------------------------------
181    @Override
182    public String toString() {
183        // getLong() reduces chances of exceptions in toString()
184        long yoe = getLong(YEAR_OF_ERA);
185        long moy = getLong(MONTH_OF_YEAR);
186        long dom = getLong(DAY_OF_MONTH);
187        StringBuilder buf = new StringBuilder(30);
188        buf.append(getChrono().toString())
189                .append(" ")
190                .append(getEra())
191                .append(" ")
192                .append(yoe)
193                .append(moy < 10 ? "-0" : "-").append(moy)
194                .append(dom < 10 ? "-0" : "-").append(dom);
195        return buf.toString();
196    }
197
198    @Override
199    public String toString(DateTimeFormatter formatter) {
200        Objects.requireNonNull(formatter, "formatter");
201        return formatter.print(this);
202    }
203
204}