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

org.threeten.bp.chrono.ChronoLocalDateTimeImpl.scala Maven / Gradle / Ivy

/*
 * 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.chrono

import java.util.Objects

import org.threeten.bp.temporal.ChronoField.EPOCH_DAY
import java.io.Serializable
import org.threeten.bp.LocalTime
import org.threeten.bp.ZoneId
import org.threeten.bp.temporal.ChronoField
import org.threeten.bp.temporal.ChronoUnit
import org.threeten.bp.temporal.Temporal
import org.threeten.bp.temporal.TemporalAdjuster
import org.threeten.bp.temporal.TemporalField
import org.threeten.bp.temporal.TemporalUnit
import org.threeten.bp.temporal.ValueRange

@SerialVersionUID(4556003607393004514L)
private[chrono] object ChronoLocalDateTimeImpl {

  /** Hours per minute. */
  private val HOURS_PER_DAY: Int = 24

  /** Minutes per hour. */
  private val MINUTES_PER_HOUR: Int = 60

  /** Minutes per day. */
  private val MINUTES_PER_DAY: Int = MINUTES_PER_HOUR * HOURS_PER_DAY

  /** Seconds per minute. */
  private val SECONDS_PER_MINUTE: Int = 60

  /** Seconds per hour. */
  private val SECONDS_PER_HOUR: Int = SECONDS_PER_MINUTE * MINUTES_PER_HOUR

  /** Seconds per day. */
  private val SECONDS_PER_DAY: Int = SECONDS_PER_HOUR * HOURS_PER_DAY

  /** Milliseconds per day. */
  private val MILLIS_PER_DAY: Long = SECONDS_PER_DAY * 1000L

  /** Microseconds per day. */
  private val MICROS_PER_DAY: Long = SECONDS_PER_DAY * 1000000L

  /** Nanos per second. */
  private val NANOS_PER_SECOND: Long = 1000000000L

  /** Nanos per minute. */
  private val NANOS_PER_MINUTE: Long = NANOS_PER_SECOND * SECONDS_PER_MINUTE

  /** Nanos per hour. */
  private val NANOS_PER_HOUR: Long = NANOS_PER_MINUTE * MINUTES_PER_HOUR

  /** Nanos per day. */
  private val NANOS_PER_DAY: Long = NANOS_PER_HOUR * HOURS_PER_DAY

  /**
   * Obtains an instance of {@code ChronoLocalDateTime} from a date and time.
   *
   * @param date
   *   the local date, not null
   * @param time
   *   the local time, not null
   * @return
   *   the local date-time, not null
   */
  private[chrono] def of[R <: ChronoLocalDate](
    date: R,
    time: LocalTime
  ): ChronoLocalDateTimeImpl[R] =
    new ChronoLocalDateTimeImpl[R](date, time)

}

/**
 * A date-time without a time-zone for the calendar neutral API.
 *
 * {@code ChronoLocalDateTime} is an immutable date-time object that represents a date-time, often
 * viewed as year-month-day-hour-minute-second. This object can also access other fields such as
 * day-of-year, day-of-week and week-of-year.
 *
 * This class stores all date and time fields, to a precision of nanoseconds. It does not store or
 * represent a time-zone. For example, the value "2nd October 2007 at 13:45.30.123456789" can be
 * stored in an {@code ChronoLocalDateTime}.
 *
 * 

Specification for implementors

This class is immutable and thread-safe. * * @tparam D * the date type * * @constructor * @param date * the date part of the date-time, not null * @param time * the time part of the date-time, not null */ @SerialVersionUID(4556003607393004514L) final class ChronoLocalDateTimeImpl[D <: ChronoLocalDate] private ( private val date: D, private val time: LocalTime ) extends ChronoLocalDateTime[D] with Temporal with TemporalAdjuster with Serializable { Objects.requireNonNull(date, "date") Objects.requireNonNull(time, "time") /** * Returns a copy of this date-time with the new date and time, checking to see if a new object is * in fact required. * * @param newDate * the date of the new date-time, not null * @param newTime * the time of the new date-time, not null * @return * the date-time, not null */ private def `with`(newDate: Temporal, newTime: LocalTime): ChronoLocalDateTimeImpl[D] = if ((date eq newDate) && (time eq newTime)) this else { val cd: D = date.getChronology.ensureChronoLocalDate[D](newDate) new ChronoLocalDateTimeImpl[D](cd, newTime) } def toLocalDate: D = date def toLocalTime: LocalTime = time def isSupported(field: TemporalField): Boolean = if (field.isInstanceOf[ChronoField]) field.isDateBased || field.isTimeBased else field != null && field.isSupportedBy(this) def isSupported(unit: TemporalUnit): Boolean = if (unit.isInstanceOf[ChronoUnit]) unit.isDateBased || unit.isTimeBased else unit != null && unit.isSupportedBy(this) override def range(field: TemporalField): ValueRange = if (field.isInstanceOf[ChronoField]) if (field.isTimeBased) time.range(field) else date.range(field) else field.rangeRefinedBy(this) override def get(field: TemporalField): Int = if (field.isInstanceOf[ChronoField]) if (field.isTimeBased) time.get(field) else date.get(field) else range(field).checkValidIntValue(getLong(field), field) def getLong(field: TemporalField): Long = if (field.isInstanceOf[ChronoField]) if (field.isTimeBased) time.getLong(field) else date.getLong(field) else field.getFrom(this) override def `with`(adjuster: TemporalAdjuster): ChronoLocalDateTimeImpl[D] = if (adjuster.isInstanceOf[ChronoLocalDate]) `with`(adjuster.asInstanceOf[ChronoLocalDate], time) else if (adjuster.isInstanceOf[LocalTime]) `with`(date, adjuster.asInstanceOf[LocalTime]) else if (adjuster.isInstanceOf[ChronoLocalDateTimeImpl[_ <: ChronoLocalDate]]) date.getChronology.ensureChronoLocalDateTime( adjuster.asInstanceOf[ChronoLocalDateTimeImpl[_]] ) else date.getChronology.ensureChronoLocalDateTime( adjuster.adjustInto(this).asInstanceOf[ChronoLocalDateTimeImpl[_]] ) def `with`(field: TemporalField, newValue: Long): ChronoLocalDateTimeImpl[D] = if (field.isInstanceOf[ChronoField]) if (field.isTimeBased) `with`(date, time.`with`(field, newValue)) else `with`(date.`with`(field, newValue), time) else date.getChronology.ensureChronoLocalDateTime(field.adjustInto(this, newValue)) def plus(amountToAdd: Long, unit: TemporalUnit): ChronoLocalDateTimeImpl[D] = if (unit.isInstanceOf[ChronoUnit]) { val f: ChronoUnit = unit.asInstanceOf[ChronoUnit] import ChronoUnit._ f match { case NANOS => plusNanos(amountToAdd) case MICROS => plusDays(amountToAdd / ChronoLocalDateTimeImpl.MICROS_PER_DAY) .plusNanos((amountToAdd % ChronoLocalDateTimeImpl.MICROS_PER_DAY) * 1000) case MILLIS => plusDays(amountToAdd / ChronoLocalDateTimeImpl.MILLIS_PER_DAY) .plusNanos((amountToAdd % ChronoLocalDateTimeImpl.MILLIS_PER_DAY) * 1000000) case SECONDS => plusSeconds(amountToAdd) case MINUTES => plusMinutes(amountToAdd) case HOURS => plusHours(amountToAdd) case HALF_DAYS => plusDays(amountToAdd / 256).plusHours((amountToAdd % 256) * 12) case _ => `with`(date.plus(amountToAdd, unit), time) } } else date.getChronology.ensureChronoLocalDateTime(unit.addTo(this, amountToAdd)) private def plusDays(days: Long): ChronoLocalDateTimeImpl[D] = `with`(date.plus(days, ChronoUnit.DAYS), time) private def plusHours(hours: Long): ChronoLocalDateTimeImpl[D] = plusWithOverflow(date, hours, 0, 0, 0) private def plusMinutes(minutes: Long): ChronoLocalDateTimeImpl[D] = plusWithOverflow(date, 0, minutes, 0, 0) private[chrono] def plusSeconds(seconds: Long): ChronoLocalDateTimeImpl[D] = plusWithOverflow(date, 0, 0, seconds, 0) private def plusNanos(nanos: Long): ChronoLocalDateTimeImpl[D] = plusWithOverflow(date, 0, 0, 0, nanos) private def plusWithOverflow( newDate: D, hours: Long, minutes: Long, seconds: Long, nanos: Long ): ChronoLocalDateTimeImpl[D] = { if ((hours | minutes | seconds | nanos) == 0) return `with`(newDate, time) var totDays: Long = nanos / ChronoLocalDateTimeImpl.NANOS_PER_DAY + seconds / ChronoLocalDateTimeImpl.SECONDS_PER_DAY + minutes / ChronoLocalDateTimeImpl.MINUTES_PER_DAY + hours / ChronoLocalDateTimeImpl.HOURS_PER_DAY var totNanos: Long = nanos % ChronoLocalDateTimeImpl.NANOS_PER_DAY + (seconds % ChronoLocalDateTimeImpl.SECONDS_PER_DAY) * ChronoLocalDateTimeImpl.NANOS_PER_SECOND + (minutes % ChronoLocalDateTimeImpl.MINUTES_PER_DAY) * ChronoLocalDateTimeImpl.NANOS_PER_MINUTE + (hours % ChronoLocalDateTimeImpl.HOURS_PER_DAY) * ChronoLocalDateTimeImpl.NANOS_PER_HOUR val curNoD: Long = time.toNanoOfDay totNanos = totNanos + curNoD totDays += Math.floorDiv(totNanos, ChronoLocalDateTimeImpl.NANOS_PER_DAY) val newNoD: Long = Math.floorMod(totNanos, ChronoLocalDateTimeImpl.NANOS_PER_DAY) val newTime: LocalTime = if (newNoD == curNoD) time else LocalTime.ofNanoOfDay(newNoD) `with`(newDate.plus(totDays, ChronoUnit.DAYS), newTime) } def atZone(zoneId: ZoneId): ChronoZonedDateTime[D] = ChronoZonedDateTimeImpl.ofBest(this, zoneId, null) def until(endExclusive: Temporal, unit: TemporalUnit): Long = { val end: ChronoLocalDateTime[D] = toLocalDate.getChronology.localDateTime(endExclusive).asInstanceOf[ChronoLocalDateTime[D]] if (unit.isInstanceOf[ChronoUnit]) { val f: ChronoUnit = unit.asInstanceOf[ChronoUnit] if (f.isTimeBased) { var amount: Long = end.getLong(EPOCH_DAY) - date.getLong(EPOCH_DAY) import ChronoUnit._ f match { case NANOS => amount = Math.multiplyExact(amount, ChronoLocalDateTimeImpl.NANOS_PER_DAY) case MICROS => amount = Math.multiplyExact(amount, ChronoLocalDateTimeImpl.MICROS_PER_DAY) case MILLIS => amount = Math.multiplyExact(amount, ChronoLocalDateTimeImpl.MILLIS_PER_DAY) case SECONDS => amount = Math.multiplyExact(amount, ChronoLocalDateTimeImpl.SECONDS_PER_DAY.toLong) case MINUTES => amount = Math.multiplyExact(amount, ChronoLocalDateTimeImpl.MINUTES_PER_DAY.toLong) case HOURS => amount = Math.multiplyExact(amount, ChronoLocalDateTimeImpl.HOURS_PER_DAY.toLong) case HALF_DAYS => amount = Math.multiplyExact(amount, 2L) case _ => throw new UnsupportedOperationException() } return Math.addExact(amount, time.until(end.toLocalTime, unit)) } var endDate: ChronoLocalDate = end.toLocalDate if (end.toLocalTime.isBefore(time)) endDate = endDate.minus(1, ChronoUnit.DAYS) return date.until(endDate, unit) } unit.between(this, end) } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy