UNPKG

create-expo-cljs-app

Version:

Create a react native application with Expo and Shadow-CLJS!

536 lines (509 loc) 22.7 kB
/* * @copyright (c) 2016, Philipp Thürwächter & Pattrick Hüper * @copyright (c) 2007-present, Stephen Colebourne & Michael Nascimento Santos * @license BSD-3-Clause (see LICENSE in the root directory of this source tree) */ import {requireNonNull} from '../assert'; import {DateTimeException} from '../errors'; import {MathUtil} from '../MathUtil'; import {EnumMap} from './EnumMap'; import {ResolverStyle} from './ResolverStyle'; import {IsoChronology} from '../chrono/IsoChronology'; import {ChronoLocalDate} from '../chrono/ChronoLocalDate'; import {ChronoField} from '../temporal/ChronoField'; import {Temporal} from '../temporal/Temporal'; import {TemporalQueries} from '../temporal/TemporalQueries'; import {LocalTime} from '../LocalTime'; import {LocalDate} from '../LocalDate'; import {Period} from '../Period'; import {ZoneOffset} from '../ZoneOffset'; /** * 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 `long` value, where the value may be * outside the valid range for the field * * from {@link Class} to {@link TemporalAccessor}, holding larger scale objects * like {@link LocalDateTime}. * * @private */ export class DateTimeBuilder extends Temporal { /** * Creates a new instance of the builder with a single field-value. * * This is equivalent to using {@link addFieldValue} on an empty builder. * * @param {TemporalField} field - the field to add, not null * @param {number} value - the value to add, not null * @return {DateTimeBuilder} */ static create(field, value) { const dtb = new DateTimeBuilder(); dtb._addFieldValue(field, value); return dtb; } constructor(){ super(); /** * The map of other fields. */ this.fieldValues = new EnumMap(); /** * The chronology. */ this.chrono = null; /** * The zone. */ this.zone = null; /** * The date. */ this.date = null; /** * The time. */ this.time = null; /** * The leap second flag. */ this.leapSecond = false; /** * The excess days. */ this.excessDays = null; } /** * * @param {TemporalField} field * @return {Number} field value */ getFieldValue0(field) { return this.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 {TemporalField} field - the field to add, not null * @param {Number} value - the value to add, not null * @return {DateTimeBuilder}, this for method chaining * @throws DateTimeException if the field is already present with a different value */ _addFieldValue(field, value) { requireNonNull(field, 'field'); const old = this.getFieldValue0(field); // check first for better error message if (old != null && old !== value) { throw new DateTimeException('Conflict found: ' + field + ' ' + old + ' differs from ' + field + ' ' + value + ': ' + this); } return this._putFieldValue0(field, value); } /** * @param {TemporalField} field * @param {Number} value * @return {DateTimeBuilder}, this for method chaining */ _putFieldValue0(field, value) { this.fieldValues.put(field, value); return this; } /** * Resolves the builder, evaluating the date and time. * * This examines the contents of the build.er 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} resolverStyle - how to resolve * @param {TemporalField[]} resolverFields * @return {DateTimeBuilder} this, for method chaining */ resolve(resolverStyle, resolverFields) { if (resolverFields != null) { this.fieldValues.retainAll(resolverFields); } // handle standard fields // this._mergeInstantFields(); this._mergeDate(resolverStyle); this._mergeTime(resolverStyle); //if (resolveFields(resolverStyle)) { // mergeInstantFields(); // mergeDate(resolverStyle); // mergeTime(resolverStyle); //} this._resolveTimeInferZeroes(resolverStyle); //this._crossCheck(); if (this.excessDays != null && this.excessDays.isZero() === false && this.date != null && this.time != null) { this.date = this.date.plus(this.excessDays); this.excessDays = Period.ZERO; } //resolveFractional(); this._resolveInstant(); return this; } /** * * @param {ResolverStyle} resolverStyle * @private */ _mergeDate(resolverStyle) { //if (this.chrono instanceof IsoChronology) { this._checkDate(IsoChronology.INSTANCE.resolveDate(this.fieldValues, resolverStyle)); //} else { // if (this.fieldValues.containsKey(ChronoField.EPOCH_DAY)) { // this._checkDate(LocalDate.ofEpochDay(this.fieldValues.remove(ChronoField.EPOCH_DAY))); // return; // } //} } /** * * @param {LocalDate} date * @private */ _checkDate(date) { if (date != null) { this._addObject(date); for (const fieldName in this.fieldValues.keySet()) { const field = ChronoField.byName(fieldName); if (field) { if (this.fieldValues.get(field) !== undefined) { // undefined if "removed" in EnumMap if (field.isDateBased()) { let val1; try { val1 = date.getLong(field); } catch (ex) { if (ex instanceof DateTimeException) { continue; } else { throw ex; } } const val2 = this.fieldValues.get(field); if (val1 !== val2) { throw new DateTimeException('Conflict found: Field ' + field + ' ' + val1 + ' differs from ' + field + ' ' + val2 + ' derived from ' + date); } } } } } } } /** * * @param {ResolverStyle} resolverStyle * @private */ _mergeTime(resolverStyle) { if (this.fieldValues.containsKey(ChronoField.CLOCK_HOUR_OF_DAY)) { const ch = this.fieldValues.remove(ChronoField.CLOCK_HOUR_OF_DAY); if (resolverStyle !== ResolverStyle.LENIENT) { if (resolverStyle === ResolverStyle.SMART && ch === 0) { // ok } else { ChronoField.CLOCK_HOUR_OF_DAY.checkValidValue(ch); } } this._addFieldValue(ChronoField.HOUR_OF_DAY, ch === 24 ? 0 : ch); } if (this.fieldValues.containsKey(ChronoField.CLOCK_HOUR_OF_AMPM)) { const ch = this.fieldValues.remove(ChronoField.CLOCK_HOUR_OF_AMPM); if (resolverStyle !== ResolverStyle.LENIENT) { if (resolverStyle === ResolverStyle.SMART && ch === 0) { // ok } else { ChronoField.CLOCK_HOUR_OF_AMPM.checkValidValue(ch); } } this._addFieldValue(ChronoField.HOUR_OF_AMPM, ch === 12 ? 0 : ch); } if (resolverStyle !== ResolverStyle.LENIENT) { if (this.fieldValues.containsKey(ChronoField.AMPM_OF_DAY)) { ChronoField.AMPM_OF_DAY.checkValidValue(this.fieldValues.get(ChronoField.AMPM_OF_DAY)); } if (this.fieldValues.containsKey(ChronoField.HOUR_OF_AMPM)) { ChronoField.HOUR_OF_AMPM.checkValidValue(this.fieldValues.get(ChronoField.HOUR_OF_AMPM)); } } if (this.fieldValues.containsKey(ChronoField.AMPM_OF_DAY) && this.fieldValues.containsKey(ChronoField.HOUR_OF_AMPM)) { const ap = this.fieldValues.remove(ChronoField.AMPM_OF_DAY); const hap = this.fieldValues.remove(ChronoField.HOUR_OF_AMPM); this._addFieldValue(ChronoField.HOUR_OF_DAY, ap * 12 + hap); } // if (timeFields.containsKey(HOUR_OF_DAY) && timeFields.containsKey(MINUTE_OF_HOUR)) { // const hod = timeFields.remove(HOUR_OF_DAY); // const moh = timeFields.remove(MINUTE_OF_HOUR); // this._addFieldValue(MINUTE_OF_DAY, hod * 60 + moh); // } // if (timeFields.containsKey(MINUTE_OF_DAY) && timeFields.containsKey(SECOND_OF_MINUTE)) { // const mod = timeFields.remove(MINUTE_OF_DAY); // const som = timeFields.remove(SECOND_OF_MINUTE); // this._addFieldValue(SECOND_OF_DAY, mod * 60 + som); // } if (this.fieldValues.containsKey(ChronoField.NANO_OF_DAY)) { const nod = this.fieldValues.remove(ChronoField.NANO_OF_DAY); if (resolverStyle !== ResolverStyle.LENIENT) { ChronoField.NANO_OF_DAY.checkValidValue(nod); } this._addFieldValue(ChronoField.SECOND_OF_DAY, MathUtil.intDiv(nod, 1000000000)); this._addFieldValue(ChronoField.NANO_OF_SECOND, MathUtil.intMod(nod, 1000000000)); } if (this.fieldValues.containsKey(ChronoField.MICRO_OF_DAY)) { const cod = this.fieldValues.remove(ChronoField.MICRO_OF_DAY); if (resolverStyle !== ResolverStyle.LENIENT) { ChronoField.MICRO_OF_DAY.checkValidValue(cod); } this._addFieldValue(ChronoField.SECOND_OF_DAY, MathUtil.intDiv(cod, 1000000)); this._addFieldValue(ChronoField.MICRO_OF_SECOND, MathUtil.intMod(cod, 1000000)); } if (this.fieldValues.containsKey(ChronoField.MILLI_OF_DAY)) { const lod = this.fieldValues.remove(ChronoField.MILLI_OF_DAY); if (resolverStyle !== ResolverStyle.LENIENT) { ChronoField.MILLI_OF_DAY.checkValidValue(lod); } this._addFieldValue(ChronoField.SECOND_OF_DAY, MathUtil.intDiv(lod, 1000)); this._addFieldValue(ChronoField.MILLI_OF_SECOND, MathUtil.intMod(lod, 1000)); } if (this.fieldValues.containsKey(ChronoField.SECOND_OF_DAY)) { const sod = this.fieldValues.remove(ChronoField.SECOND_OF_DAY); if (resolverStyle !== ResolverStyle.LENIENT) { ChronoField.SECOND_OF_DAY.checkValidValue(sod); } this._addFieldValue(ChronoField.HOUR_OF_DAY, MathUtil.intDiv(sod, 3600)); this._addFieldValue(ChronoField.MINUTE_OF_HOUR, MathUtil.intMod(MathUtil.intDiv(sod, 60), 60)); this._addFieldValue(ChronoField.SECOND_OF_MINUTE, MathUtil.intMod(sod, 60)); } if (this.fieldValues.containsKey(ChronoField.MINUTE_OF_DAY)) { const mod = this.fieldValues.remove(ChronoField.MINUTE_OF_DAY); if (resolverStyle !== ResolverStyle.LENIENT) { ChronoField.MINUTE_OF_DAY.checkValidValue(mod); } this._addFieldValue(ChronoField.HOUR_OF_DAY, MathUtil.intDiv(mod, 60)); this._addFieldValue(ChronoField.MINUTE_OF_HOUR, MathUtil.intMod(mod, 60)); } // const sod = MathUtil.intDiv(nod, 1000000000L); // this._addFieldValue(HOUR_OF_DAY, MathUtil.intDiv(sod, 3600)); // this._addFieldValue(MINUTE_OF_HOUR, MathUtil.intMod(MathUtil.intDiv(sod, 60), 60)); // this._addFieldValue(SECOND_OF_MINUTE, MathUtil.intMod(sod, 60)); // this._addFieldValue(NANO_OF_SECOND, MathUtil.intMod(nod, 1000000000L)); if (resolverStyle !== ResolverStyle.LENIENT) { if (this.fieldValues.containsKey(ChronoField.MILLI_OF_SECOND)) { ChronoField.MILLI_OF_SECOND.checkValidValue(this.fieldValues.get(ChronoField.MILLI_OF_SECOND)); } if (this.fieldValues.containsKey(ChronoField.MICRO_OF_SECOND)) { ChronoField.MICRO_OF_SECOND.checkValidValue(this.fieldValues.get(ChronoField.MICRO_OF_SECOND)); } } if (this.fieldValues.containsKey(ChronoField.MILLI_OF_SECOND) && this.fieldValues.containsKey(ChronoField.MICRO_OF_SECOND)) { const los = this.fieldValues.remove(ChronoField.MILLI_OF_SECOND); const cos = this.fieldValues.get(ChronoField.MICRO_OF_SECOND); this._putFieldValue0(ChronoField.MICRO_OF_SECOND, los * 1000 + (MathUtil.intMod(cos, 1000))); } if (this.fieldValues.containsKey(ChronoField.MICRO_OF_SECOND) && this.fieldValues.containsKey(ChronoField.NANO_OF_SECOND)) { const nos = this.fieldValues.get(ChronoField.NANO_OF_SECOND); this._putFieldValue0(ChronoField.MICRO_OF_SECOND, MathUtil.intDiv(nos, 1000)); this.fieldValues.remove(ChronoField.MICRO_OF_SECOND); } if (this.fieldValues.containsKey(ChronoField.MILLI_OF_SECOND) && this.fieldValues.containsKey(ChronoField.NANO_OF_SECOND)) { const nos = this.fieldValues.get(ChronoField.NANO_OF_SECOND); this._putFieldValue0(ChronoField.MILLI_OF_SECOND, MathUtil.intDiv(nos, 1000000)); this.fieldValues.remove(ChronoField.MILLI_OF_SECOND); } if (this.fieldValues.containsKey(ChronoField.MICRO_OF_SECOND)) { const cos = this.fieldValues.remove(ChronoField.MICRO_OF_SECOND); this._putFieldValue0(ChronoField.NANO_OF_SECOND, cos * 1000); } else if (this.fieldValues.containsKey(ChronoField.MILLI_OF_SECOND)) { const los = this.fieldValues.remove(ChronoField.MILLI_OF_SECOND); this._putFieldValue0(ChronoField.NANO_OF_SECOND, los * 1000000); } } /** * * @param {ResolverStyle} resolverStyle * @private */ _resolveTimeInferZeroes(resolverStyle) { let hod = this.fieldValues.get(ChronoField.HOUR_OF_DAY); const moh = this.fieldValues.get(ChronoField.MINUTE_OF_HOUR); const som = this.fieldValues.get(ChronoField.SECOND_OF_MINUTE); let nos = this.fieldValues.get(ChronoField.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 === 24 && (moh == null || moh === 0) && (som == null || som === 0) && (nos == null || nos === 0)) { hod = 0; this.excessDays = Period.ofDays(1); } const hodVal = ChronoField.HOUR_OF_DAY.checkValidIntValue(hod); if (moh != null) { const mohVal = ChronoField.MINUTE_OF_HOUR.checkValidIntValue(moh); if (som != null) { const somVal = ChronoField.SECOND_OF_MINUTE.checkValidIntValue(som); if (nos != null) { const nosVal = ChronoField.NANO_OF_SECOND.checkValidIntValue(nos); this._addObject(LocalTime.of(hodVal, mohVal, somVal, nosVal)); } else { this._addObject(LocalTime.of(hodVal, mohVal, somVal)); } } else { if (nos == null) { this._addObject(LocalTime.of(hodVal, mohVal)); } } } else { if (som == null && nos == null) { this._addObject(LocalTime.of(hodVal, 0)); } } } } else { if (hod != null) { let hodVal = hod; if (moh != null) { if (som != null) { if (nos == null) { nos = 0; } let totalNanos = MathUtil.safeMultiply(hodVal, 3600000000000); totalNanos = MathUtil.safeAdd(totalNanos, MathUtil.safeMultiply(moh, 60000000000)); totalNanos = MathUtil.safeAdd(totalNanos, MathUtil.safeMultiply(som, 1000000000)); totalNanos = MathUtil.safeAdd(totalNanos, nos); const excessDays = MathUtil.floorDiv(totalNanos, 86400000000000); // safe int cast const nod = MathUtil.floorMod(totalNanos, 86400000000000); this._addObject(LocalTime.ofNanoOfDay(nod)); this.excessDays = Period.ofDays(excessDays); } else { let totalSecs = MathUtil.safeMultiply(hodVal, 3600); totalSecs = MathUtil.safeAdd(totalSecs, MathUtil.safeMultiply(moh, 60)); const excessDays = MathUtil.floorDiv(totalSecs, 86400); // safe int cast const sod = MathUtil.floorMod(totalSecs, 86400); this._addObject(LocalTime.ofSecondOfDay(sod)); this.excessDays = Period.ofDays(excessDays); } } else { const excessDays = MathUtil.safeToInt(MathUtil.floorDiv(hodVal, 24)); hodVal = MathUtil.floorMod(hodVal, 24); this._addObject(LocalTime.of(hodVal, 0)); this.excessDays = Period.ofDays(excessDays); } } } this.fieldValues.remove(ChronoField.HOUR_OF_DAY); this.fieldValues.remove(ChronoField.MINUTE_OF_HOUR); this.fieldValues.remove(ChronoField.SECOND_OF_MINUTE); this.fieldValues.remove(ChronoField.NANO_OF_SECOND); } /** * * @param {ChronoLocalDate|LocalTime} dateOrTime * @private */ _addObject(dateOrTime) { if (dateOrTime instanceof ChronoLocalDate){ this.date = dateOrTime; } else if (dateOrTime instanceof LocalTime){ this.time = dateOrTime; } } _resolveInstant() { if (this.date != null && this.time != null) { const offsetSecs = this.fieldValues.get(ChronoField.OFFSET_SECONDS); if (offsetSecs != null) { const offset = ZoneOffset.ofTotalSeconds(offsetSecs); const instant = this.date.atTime(this.time).atZone(offset).getLong(ChronoField.INSTANT_SECONDS); this.fieldValues.put(ChronoField.INSTANT_SECONDS, instant); } else if (this.zone != null) { const instant = this.date.atTime(this.time).atZone(this.zone).getLong(ChronoField.INSTANT_SECONDS); this.fieldValues.put(ChronoField.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 {!TemporalQuery} type - the type to invoke `from` on, not null * @return {*} the extracted value, not null * @throws DateTimeException if an error occurs */ build(type) { return type.queryFrom(this); } /** * * @param {TemporalField} field * @returns {number} */ isSupported(field) { if (field == null) { return false; } return (this.fieldValues.containsKey(field) && this.fieldValues.get(field) !== undefined) || (this.date != null && this.date.isSupported(field)) || (this.time != null && this.time.isSupported(field)); } /** * * @param {TemporalField} field * @returns {number} */ getLong(field) { requireNonNull(field, 'field'); const value = this.getFieldValue0(field); if (value == null) { if (this.date != null && this.date.isSupported(field)) { return this.date.getLong(field); } if (this.time != null && this.time.isSupported(field)) { return this.time.getLong(field); } throw new DateTimeException('Field not found: ' + field); } return value; } /** * * @param {!TemporalQuery} query * @returns {*} */ query(query) { if (query === TemporalQueries.zoneId()) { return this.zone; } else if (query === TemporalQueries.chronology()) { return this.chrono; } else if (query === TemporalQueries.localDate()) { return this.date != null ? LocalDate.from(this.date) : null; } else if (query === TemporalQueries.localTime()) { return this.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); } }