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

org.threeten.bp.format.DateTimeBuilder Maven / Gradle / Ivy

Go to download

Backport of JSR-310 from JDK 8 to JDK 7 and JDK 6. NOT an implementation of the JSR.

There is a newer version: 1.7.0
Show newest version
/*
 * Copyright (c) 2007-present, Stephen Colebourne & Michael Nascimento Santos
 *
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 *  * Redistributions of source code must retain the above copyright notice,
 *    this list of conditions and the following disclaimer.
 *
 *  * Redistributions in binary form must reproduce the above copyright notice,
 *    this list of conditions and the following disclaimer in the documentation
 *    and/or other materials provided with the distribution.
 *
 *  * Neither the name of JSR-310 nor the names of its contributors
 *    may be used to endorse or promote products derived from this software
 *    without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
package org.threeten.bp.format;

import static org.threeten.bp.temporal.ChronoField.AMPM_OF_DAY;
import static org.threeten.bp.temporal.ChronoField.CLOCK_HOUR_OF_AMPM;
import static org.threeten.bp.temporal.ChronoField.CLOCK_HOUR_OF_DAY;
import static org.threeten.bp.temporal.ChronoField.EPOCH_DAY;
import static org.threeten.bp.temporal.ChronoField.HOUR_OF_AMPM;
import static org.threeten.bp.temporal.ChronoField.HOUR_OF_DAY;
import static org.threeten.bp.temporal.ChronoField.INSTANT_SECONDS;
import static org.threeten.bp.temporal.ChronoField.MICRO_OF_DAY;
import static org.threeten.bp.temporal.ChronoField.MICRO_OF_SECOND;
import static org.threeten.bp.temporal.ChronoField.MILLI_OF_DAY;
import static org.threeten.bp.temporal.ChronoField.MILLI_OF_SECOND;
import static org.threeten.bp.temporal.ChronoField.MINUTE_OF_DAY;
import static org.threeten.bp.temporal.ChronoField.MINUTE_OF_HOUR;
import static org.threeten.bp.temporal.ChronoField.NANO_OF_DAY;
import static org.threeten.bp.temporal.ChronoField.NANO_OF_SECOND;
import static org.threeten.bp.temporal.ChronoField.OFFSET_SECONDS;
import static org.threeten.bp.temporal.ChronoField.SECOND_OF_DAY;
import static org.threeten.bp.temporal.ChronoField.SECOND_OF_MINUTE;

import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;

import org.threeten.bp.DateTimeException;
import org.threeten.bp.Instant;
import org.threeten.bp.LocalDate;
import org.threeten.bp.LocalTime;
import org.threeten.bp.Period;
import org.threeten.bp.ZoneId;
import org.threeten.bp.ZoneOffset;
import org.threeten.bp.chrono.ChronoLocalDate;
import org.threeten.bp.chrono.ChronoLocalDateTime;
import org.threeten.bp.chrono.ChronoZonedDateTime;
import org.threeten.bp.chrono.Chronology;
import org.threeten.bp.chrono.IsoChronology;
import org.threeten.bp.jdk8.DefaultInterfaceTemporalAccessor;
import org.threeten.bp.jdk8.Jdk8Methods;
import org.threeten.bp.temporal.ChronoField;
import org.threeten.bp.temporal.TemporalAccessor;
import org.threeten.bp.temporal.TemporalField;
import org.threeten.bp.temporal.TemporalQueries;
import org.threeten.bp.temporal.TemporalQuery;

/**
 * Builder that can holds date and time fields and related date and time objects.
 * 

* The builder is used to hold onto different elements of date and time. * It is designed as two separate maps: *

    *
  • from {@link TemporalField} to {@code long} value, where the value may be * outside the valid range for the field *
  • from {@code Class} to {@link TemporalAccessor}, holding larger scale objects * like {@code LocalDateTime}. *

* *

Specification for implementors

* This class is mutable and not thread-safe. * It should only be used from a single thread. */ final class DateTimeBuilder extends DefaultInterfaceTemporalAccessor implements TemporalAccessor, Cloneable { /** * The map of other fields. */ final Map fieldValues = new HashMap(); /** * The chronology. */ Chronology chrono; /** * The zone. */ ZoneId zone; /** * The date. */ ChronoLocalDate date; /** * The time. */ LocalTime time; /** * The leap second flag. */ boolean leapSecond; /** * The excess days. */ Period excessDays; //----------------------------------------------------------------------- /** * Creates an empty instance of the builder. */ public DateTimeBuilder() { } /** * Creates a new instance of the builder with a single field-value. *

* This is equivalent to using {@link #addFieldValue(TemporalField, long)} on an empty builder. * * @param field the field to add, not null * @param value the value to add, not null */ public DateTimeBuilder(TemporalField field, long value) { addFieldValue(field, value); } //----------------------------------------------------------------------- private Long getFieldValue0(TemporalField field) { return fieldValues.get(field); } /** * Adds a field-value pair to the builder. *

* This adds a field to the builder. * If the field is not already present, then the field-value pair is added to the map. * If the field is already present and it has the same value as that specified, no action occurs. * If the field is already present and it has a different value to that specified, then * an exception is thrown. * * @param field the field to add, not null * @param value the value to add, not null * @return {@code this}, for method chaining * @throws DateTimeException if the field is already present with a different value */ DateTimeBuilder addFieldValue(TemporalField field, long value) { Jdk8Methods.requireNonNull(field, "field"); Long old = getFieldValue0(field); // check first for better error message if (old != null && old.longValue() != value) { throw new DateTimeException("Conflict found: " + field + " " + old + " differs from " + field + " " + value + ": " + this); } return putFieldValue0(field, value); } private DateTimeBuilder putFieldValue0(TemporalField field, long value) { fieldValues.put(field, value); return this; } //----------------------------------------------------------------------- void addObject(ChronoLocalDate date) { this.date = date; } void addObject(LocalTime time) { this.time = time; } //----------------------------------------------------------------------- /** * Resolves the builder, evaluating the date and time. *

* This examines the contents of the builder and resolves it to produce the best * available date and time, throwing an exception if a problem occurs. * Calling this method changes the state of the builder. * * @param resolverStyle how to resolve * @return {@code this}, for method chaining */ public DateTimeBuilder resolve(ResolverStyle resolverStyle, Set resolverFields) { if (resolverFields != null) { fieldValues.keySet().retainAll(resolverFields); } // handle standard fields mergeInstantFields(); mergeDate(resolverStyle); mergeTime(resolverStyle); if (resolveFields(resolverStyle)) { mergeInstantFields(); mergeDate(resolverStyle); mergeTime(resolverStyle); } resolveTimeInferZeroes(resolverStyle); crossCheck(); if (excessDays != null && excessDays.isZero() == false && date != null && time != null) { date = date.plus(excessDays); excessDays = Period.ZERO; } resolveFractional(); resolveInstant(); return this; } private boolean resolveFields(ResolverStyle resolverStyle) { int changes = 0; outer: while (changes < 100) { for (Map.Entry entry : fieldValues.entrySet()) { TemporalField targetField = entry.getKey(); TemporalAccessor resolvedObject = targetField.resolve(fieldValues, this, resolverStyle); if (resolvedObject != null) { if (resolvedObject instanceof ChronoZonedDateTime) { ChronoZonedDateTime czdt = (ChronoZonedDateTime) resolvedObject; if (zone == null) { zone = czdt.getZone(); } else if (zone.equals(czdt.getZone()) == false) { throw new DateTimeException("ChronoZonedDateTime must use the effective parsed zone: " + zone); } resolvedObject = czdt.toLocalDateTime(); } if (resolvedObject instanceof ChronoLocalDate) { resolveMakeChanges(targetField, (ChronoLocalDate) resolvedObject); changes++; continue outer; // have to restart to avoid concurrent modification } if (resolvedObject instanceof LocalTime) { resolveMakeChanges(targetField, (LocalTime) resolvedObject); changes++; continue outer; // have to restart to avoid concurrent modification } if (resolvedObject instanceof ChronoLocalDateTime) { ChronoLocalDateTime cldt = (ChronoLocalDateTime) resolvedObject; resolveMakeChanges(targetField, cldt.toLocalDate()); resolveMakeChanges(targetField, cldt.toLocalTime()); changes++; continue outer; // have to restart to avoid concurrent modification } throw new DateTimeException("Unknown type: " + resolvedObject.getClass().getName()); } else if (fieldValues.containsKey(targetField) == false) { changes++; continue outer; // have to restart to avoid concurrent modification } } break; } if (changes == 100) { throw new DateTimeException("Badly written field"); } return changes > 0; } private void resolveMakeChanges(TemporalField targetField, ChronoLocalDate date) { if (chrono.equals(date.getChronology()) == false) { throw new DateTimeException("ChronoLocalDate must use the effective parsed chronology: " + chrono); } long epochDay = date.toEpochDay(); Long old = fieldValues.put(ChronoField.EPOCH_DAY, epochDay); if (old != null && old.longValue() != epochDay) { throw new DateTimeException("Conflict found: " + LocalDate.ofEpochDay(old) + " differs from " + LocalDate.ofEpochDay(epochDay) + " while resolving " + targetField); } } private void resolveMakeChanges(TemporalField targetField, LocalTime time) { long nanOfDay = time.toNanoOfDay(); Long old = fieldValues.put(ChronoField.NANO_OF_DAY, nanOfDay); if (old != null && old.longValue() != nanOfDay) { throw new DateTimeException("Conflict found: " + LocalTime.ofNanoOfDay(old) + " differs from " + time + " while resolving " + targetField); } } private void mergeDate(ResolverStyle resolverStyle) { if (chrono instanceof IsoChronology) { checkDate(IsoChronology.INSTANCE.resolveDate(fieldValues, resolverStyle)); } else { if (fieldValues.containsKey(EPOCH_DAY)) { checkDate(LocalDate.ofEpochDay(fieldValues.remove(EPOCH_DAY))); return; } } } private void checkDate(LocalDate date) { if (date != null) { addObject(date); for (TemporalField field : fieldValues.keySet()) { if (field instanceof ChronoField) { if (field.isDateBased()) { long val1; try { val1 = date.getLong(field); } catch (DateTimeException ex) { continue; } Long val2 = fieldValues.get(field); if (val1 != val2) { throw new DateTimeException("Conflict found: Field " + field + " " + val1 + " differs from " + field + " " + val2 + " derived from " + date); } } } } } } private void mergeTime(ResolverStyle resolverStyle) { if (fieldValues.containsKey(CLOCK_HOUR_OF_DAY)) { long ch = fieldValues.remove(CLOCK_HOUR_OF_DAY); if (resolverStyle != ResolverStyle.LENIENT) { if (resolverStyle == ResolverStyle.SMART && ch == 0) { // ok } else { CLOCK_HOUR_OF_DAY.checkValidValue(ch); } } addFieldValue(HOUR_OF_DAY, ch == 24 ? 0 : ch); } if (fieldValues.containsKey(CLOCK_HOUR_OF_AMPM)) { long ch = fieldValues.remove(CLOCK_HOUR_OF_AMPM); if (resolverStyle != ResolverStyle.LENIENT) { if (resolverStyle == ResolverStyle.SMART && ch == 0) { // ok } else { CLOCK_HOUR_OF_AMPM.checkValidValue(ch); } } addFieldValue(HOUR_OF_AMPM, ch == 12 ? 0 : ch); } if (resolverStyle != ResolverStyle.LENIENT) { if (fieldValues.containsKey(AMPM_OF_DAY)) { AMPM_OF_DAY.checkValidValue(fieldValues.get(AMPM_OF_DAY)); } if (fieldValues.containsKey(HOUR_OF_AMPM)) { HOUR_OF_AMPM.checkValidValue(fieldValues.get(HOUR_OF_AMPM)); } } if (fieldValues.containsKey(AMPM_OF_DAY) && fieldValues.containsKey(HOUR_OF_AMPM)) { long ap = fieldValues.remove(AMPM_OF_DAY); long hap = fieldValues.remove(HOUR_OF_AMPM); addFieldValue(HOUR_OF_DAY, ap * 12 + hap); } // if (timeFields.containsKey(HOUR_OF_DAY) && timeFields.containsKey(MINUTE_OF_HOUR)) { // long hod = timeFields.remove(HOUR_OF_DAY); // long moh = timeFields.remove(MINUTE_OF_HOUR); // addFieldValue(MINUTE_OF_DAY, hod * 60 + moh); // } // if (timeFields.containsKey(MINUTE_OF_DAY) && timeFields.containsKey(SECOND_OF_MINUTE)) { // long mod = timeFields.remove(MINUTE_OF_DAY); // long som = timeFields.remove(SECOND_OF_MINUTE); // addFieldValue(SECOND_OF_DAY, mod * 60 + som); // } if (fieldValues.containsKey(NANO_OF_DAY)) { long nod = fieldValues.remove(NANO_OF_DAY); if (resolverStyle != ResolverStyle.LENIENT) { NANO_OF_DAY.checkValidValue(nod); } addFieldValue(SECOND_OF_DAY, nod / 1000000000L); addFieldValue(NANO_OF_SECOND, nod % 1000000000L); } if (fieldValues.containsKey(MICRO_OF_DAY)) { long cod = fieldValues.remove(MICRO_OF_DAY); if (resolverStyle != ResolverStyle.LENIENT) { MICRO_OF_DAY.checkValidValue(cod); } addFieldValue(SECOND_OF_DAY, cod / 1000000L); addFieldValue(MICRO_OF_SECOND, cod % 1000000L); } if (fieldValues.containsKey(MILLI_OF_DAY)) { long lod = fieldValues.remove(MILLI_OF_DAY); if (resolverStyle != ResolverStyle.LENIENT) { MILLI_OF_DAY.checkValidValue(lod); } addFieldValue(SECOND_OF_DAY, lod / 1000); addFieldValue(MILLI_OF_SECOND, lod % 1000); } if (fieldValues.containsKey(SECOND_OF_DAY)) { long sod = fieldValues.remove(SECOND_OF_DAY); if (resolverStyle != ResolverStyle.LENIENT) { SECOND_OF_DAY.checkValidValue(sod); } addFieldValue(HOUR_OF_DAY, sod / 3600); addFieldValue(MINUTE_OF_HOUR, (sod / 60) % 60); addFieldValue(SECOND_OF_MINUTE, sod % 60); } if (fieldValues.containsKey(MINUTE_OF_DAY)) { long mod = fieldValues.remove(MINUTE_OF_DAY); if (resolverStyle != ResolverStyle.LENIENT) { MINUTE_OF_DAY.checkValidValue(mod); } addFieldValue(HOUR_OF_DAY, mod / 60); addFieldValue(MINUTE_OF_HOUR, mod % 60); } // long sod = nod / 1000000000L; // addFieldValue(HOUR_OF_DAY, sod / 3600); // addFieldValue(MINUTE_OF_HOUR, (sod / 60) % 60); // addFieldValue(SECOND_OF_MINUTE, sod % 60); // addFieldValue(NANO_OF_SECOND, nod % 1000000000L); if (resolverStyle != ResolverStyle.LENIENT) { if (fieldValues.containsKey(MILLI_OF_SECOND)) { MILLI_OF_SECOND.checkValidValue(fieldValues.get(MILLI_OF_SECOND)); } if (fieldValues.containsKey(MICRO_OF_SECOND)) { MICRO_OF_SECOND.checkValidValue(fieldValues.get(MICRO_OF_SECOND)); } } if (fieldValues.containsKey(MILLI_OF_SECOND) && fieldValues.containsKey(MICRO_OF_SECOND)) { long los = fieldValues.remove(MILLI_OF_SECOND); long cos = fieldValues.get(MICRO_OF_SECOND); addFieldValue(MICRO_OF_SECOND, los * 1000 + (cos % 1000)); } if (fieldValues.containsKey(MICRO_OF_SECOND) && fieldValues.containsKey(NANO_OF_SECOND)) { long nos = fieldValues.get(NANO_OF_SECOND); addFieldValue(MICRO_OF_SECOND, nos / 1000); fieldValues.remove(MICRO_OF_SECOND); } if (fieldValues.containsKey(MILLI_OF_SECOND) && fieldValues.containsKey(NANO_OF_SECOND)) { long nos = fieldValues.get(NANO_OF_SECOND); addFieldValue(MILLI_OF_SECOND, nos / 1000000); fieldValues.remove(MILLI_OF_SECOND); } if (fieldValues.containsKey(MICRO_OF_SECOND)) { long cos = fieldValues.remove(MICRO_OF_SECOND); addFieldValue(NANO_OF_SECOND, cos * 1000); } else if (fieldValues.containsKey(MILLI_OF_SECOND)) { long los = fieldValues.remove(MILLI_OF_SECOND); addFieldValue(NANO_OF_SECOND, los * 1000000); } } private void resolveTimeInferZeroes(ResolverStyle resolverStyle) { Long hod = fieldValues.get(HOUR_OF_DAY); Long moh = fieldValues.get(MINUTE_OF_HOUR); Long som = fieldValues.get(SECOND_OF_MINUTE); Long nos = fieldValues.get(NANO_OF_SECOND); if (hod == null) { return; } if (moh == null && (som != null || nos != null)) { return; } if (moh != null && som == null && nos != null) { return; } if (resolverStyle != ResolverStyle.LENIENT) { if (hod != null) { if (resolverStyle == ResolverStyle.SMART && hod.longValue() == 24 && (moh == null || moh.longValue() == 0) && (som == null || som.longValue() == 0) && (nos == null || nos.longValue() == 0)) { hod = 0L; excessDays = Period.ofDays(1); } int hodVal = HOUR_OF_DAY.checkValidIntValue(hod); if (moh != null) { int mohVal = MINUTE_OF_HOUR.checkValidIntValue(moh); if (som != null) { int somVal = SECOND_OF_MINUTE.checkValidIntValue(som); if (nos != null) { int nosVal = NANO_OF_SECOND.checkValidIntValue(nos); addObject(LocalTime.of(hodVal, mohVal, somVal, nosVal)); } else { addObject(LocalTime.of(hodVal, mohVal, somVal)); } } else { if (nos == null) { addObject(LocalTime.of(hodVal, mohVal)); } } } else { if (som == null && nos == null) { addObject(LocalTime.of(hodVal, 0)); } } } } else { if (hod != null) { long hodVal = hod; if (moh != null) { if (som != null) { if (nos == null) { nos = 0L; } long totalNanos = Jdk8Methods.safeMultiply(hodVal, 3600000000000L); totalNanos = Jdk8Methods.safeAdd(totalNanos, Jdk8Methods.safeMultiply(moh, 60000000000L)); totalNanos = Jdk8Methods.safeAdd(totalNanos, Jdk8Methods.safeMultiply(som, 1000000000L)); totalNanos = Jdk8Methods.safeAdd(totalNanos, nos); int excessDays = (int) Jdk8Methods.floorDiv(totalNanos, 86400000000000L); // safe int cast long nod = Jdk8Methods.floorMod(totalNanos, 86400000000000L); addObject(LocalTime.ofNanoOfDay(nod)); this.excessDays = Period.ofDays(excessDays); } else { long totalSecs = Jdk8Methods.safeMultiply(hodVal, 3600L); totalSecs = Jdk8Methods.safeAdd(totalSecs, Jdk8Methods.safeMultiply(moh, 60L)); int excessDays = (int) Jdk8Methods.floorDiv(totalSecs, 86400L); // safe int cast long sod = Jdk8Methods.floorMod(totalSecs, 86400L); addObject(LocalTime.ofSecondOfDay(sod)); this.excessDays = Period.ofDays(excessDays); } } else { int excessDays = Jdk8Methods.safeToInt(Jdk8Methods.floorDiv(hodVal, 24L)); hodVal = Jdk8Methods.floorMod(hodVal, 24); addObject(LocalTime.of((int) hodVal, 0)); this.excessDays = Period.ofDays(excessDays); } } } fieldValues.remove(HOUR_OF_DAY); fieldValues.remove(MINUTE_OF_HOUR); fieldValues.remove(SECOND_OF_MINUTE); fieldValues.remove(NANO_OF_SECOND); } //----------------------------------------------------------------------- private void mergeInstantFields() { if (fieldValues.containsKey(INSTANT_SECONDS)) { if (zone != null) { mergeInstantFields0(zone); } else { Long offsetSecs = fieldValues.get(OFFSET_SECONDS); if (offsetSecs != null) { ZoneOffset offset = ZoneOffset.ofTotalSeconds(offsetSecs.intValue()); mergeInstantFields0(offset); } } } } private void mergeInstantFields0(ZoneId selectedZone) { Instant instant = Instant.ofEpochSecond(fieldValues.remove(INSTANT_SECONDS)); ChronoZonedDateTime zdt = chrono.zonedDateTime(instant, selectedZone); if (date == null) { addObject(zdt.toLocalDate()); } else { resolveMakeChanges(INSTANT_SECONDS, zdt.toLocalDate()); } addFieldValue(SECOND_OF_DAY, (long) zdt.toLocalTime().toSecondOfDay()); } //----------------------------------------------------------------------- private void crossCheck() { if (fieldValues.size() > 0) { if (date != null && time != null) { crossCheck(date.atTime(time)); } else if (date != null) { crossCheck(date); } else if (time != null) { crossCheck(time); } } } private void crossCheck(TemporalAccessor temporal) { Iterator> it = fieldValues.entrySet().iterator(); while (it.hasNext()) { Entry entry = it.next(); TemporalField field = entry.getKey(); long value = entry.getValue(); if (temporal.isSupported(field)) { long temporalValue; try { temporalValue = temporal.getLong(field); } catch (RuntimeException ex) { continue; } if (temporalValue != value) { throw new DateTimeException("Cross check failed: " + field + " " + temporalValue + " vs " + field + " " + value); } it.remove(); } } } private void resolveFractional() { if (time == null && (fieldValues.containsKey(INSTANT_SECONDS) || fieldValues.containsKey(SECOND_OF_DAY) || fieldValues.containsKey(SECOND_OF_MINUTE))) { if (fieldValues.containsKey(NANO_OF_SECOND)) { long nos = fieldValues.get(NANO_OF_SECOND); fieldValues.put(MICRO_OF_SECOND, nos / 1000); fieldValues.put(MILLI_OF_SECOND, nos / 1000000); } else { fieldValues.put(NANO_OF_SECOND, 0L); fieldValues.put(MICRO_OF_SECOND, 0L); fieldValues.put(MILLI_OF_SECOND, 0L); } } } private void resolveInstant() { if (date != null && time != null) { if (zone != null) { long instant = date.atTime(time).atZone(zone).getLong(ChronoField.INSTANT_SECONDS); fieldValues.put(INSTANT_SECONDS, instant); } else { Long offsetSecs = fieldValues.get(OFFSET_SECONDS); if (offsetSecs != null) { ZoneOffset offset = ZoneOffset.ofTotalSeconds(offsetSecs.intValue()); long instant = date.atTime(time).atZone(offset).getLong(ChronoField.INSTANT_SECONDS); fieldValues.put(INSTANT_SECONDS, instant); } } } } //----------------------------------------------------------------------- /** * Builds the specified type from the values in this builder. *

* This attempts to build the specified type from this builder. * If the builder cannot return the type, an exception is thrown. * * @param the type to return * @param type the type to invoke {@code from} on, not null * @return the extracted value, not null * @throws DateTimeException if an error occurs */ public R build(TemporalQuery type) { return type.queryFrom(this); } //----------------------------------------------------------------------- @Override public boolean isSupported(TemporalField field) { if (field == null) { return false; } return fieldValues.containsKey(field) || (date != null && date.isSupported(field)) || (time != null && time.isSupported(field)); } @Override public long getLong(TemporalField field) { Jdk8Methods.requireNonNull(field, "field"); Long value = getFieldValue0(field); if (value == null) { if (date != null && date.isSupported(field)) { return date.getLong(field); } if (time != null && time.isSupported(field)) { return time.getLong(field); } throw new DateTimeException("Field not found: " + field); } return value; } @SuppressWarnings("unchecked") @Override public R query(TemporalQuery query) { if (query == TemporalQueries.zoneId()) { return (R) zone; } else if (query == TemporalQueries.chronology()) { return (R) chrono; } else if (query == TemporalQueries.localDate()) { return date != null ? (R) LocalDate.from(date) : null; } else if (query == TemporalQueries.localTime()) { return (R) time; } else if (query == TemporalQueries.zone() || query == TemporalQueries.offset()) { return query.queryFrom(this); } else if (query == TemporalQueries.precision()) { return null; // not a complete date/time } // inline TemporalAccessor.super.query(query) as an optimization // non-JDK classes are not permitted to make this optimization return query.queryFrom(this); } //----------------------------------------------------------------------- @Override public String toString() { StringBuilder buf = new StringBuilder(128); buf.append("DateTimeBuilder["); if (fieldValues.size() > 0) { buf.append("fields=").append(fieldValues); } buf.append(", ").append(chrono); buf.append(", ").append(zone); buf.append(", ").append(date); buf.append(", ").append(time); buf.append(']'); return buf.toString(); } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy