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

org.threeten.bp.chrono.ChronoZonedDateTimeImpl.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.ChronoUnit.SECONDS
import org.threeten.bp.Instant
import org.threeten.bp.LocalDateTime
import org.threeten.bp.ZoneId
import org.threeten.bp.ZoneOffset
import org.threeten.bp.temporal.ChronoField
import org.threeten.bp.temporal.ChronoUnit
import org.threeten.bp.temporal.Temporal
import org.threeten.bp.temporal.TemporalField
import org.threeten.bp.temporal.TemporalUnit
import org.threeten.bp.zone.ZoneOffsetTransition
import org.threeten.bp.zone.ZoneRules

private[chrono] object ChronoZonedDateTimeImpl {

  /**
   * Obtains an instance from a local date-time using the preferred offset if possible.
   *
   * @param localDateTime
   *   the local date-time, not null
   * @param zone
   *   the zone identifier, not null
   * @param preferredOffset
   *   the zone offset, null if no preference
   * @return
   *   the zoned date-time, not null
   */
  private[chrono] def ofBest[R <: ChronoLocalDate](
    localDateTime:   ChronoLocalDateTimeImpl[R],
    zone:            ZoneId,
    preferredOffset: ZoneOffset
  ): ChronoZonedDateTime[R] = {
    var _localDateTime = localDateTime
    Objects.requireNonNull(_localDateTime, "localDateTime")
    Objects.requireNonNull(zone, "zone")
    zone match {
      case offset: ZoneOffset => new ChronoZonedDateTimeImpl[R](_localDateTime, offset, zone)
      case _                  =>
        val rules: ZoneRules                         = zone.getRules
        val isoLDT: LocalDateTime                    = LocalDateTime.from(_localDateTime)
        val validOffsets: java.util.List[ZoneOffset] = rules.getValidOffsets(isoLDT)
        var offset: ZoneOffset                       = null
        if (validOffsets.size == 1)
          offset = validOffsets.get(0)
        else if (validOffsets.size == 0) {
          val trans: ZoneOffsetTransition = rules.getTransition(isoLDT)
          _localDateTime = _localDateTime.plusSeconds(trans.getDuration.getSeconds)
          offset = trans.getOffsetAfter
        } else if (preferredOffset != null && validOffsets.contains(preferredOffset))
          offset = preferredOffset
        else
          offset = validOffsets.get(0)
        Objects.requireNonNull(offset, "offset")
        new ChronoZonedDateTimeImpl[R](_localDateTime, offset, zone)
    }
  }

  /**
   * Obtains an instance from an instant using the specified time-zone.
   *
   * @param chrono
   *   the chronology, not null
   * @param instant
   *   the instant, not null
   * @param zone
   *   the zone identifier, not null
   * @return
   *   the zoned date-time, not null
   */
  private[chrono] def ofInstant[R <: ChronoLocalDate](
    chrono:  Chronology,
    instant: Instant,
    zone:    ZoneId
  ): ChronoZonedDateTimeImpl[R] = {
    val rules: ZoneRules                                                       = zone.getRules
    val offset: ZoneOffset                                                     = rules.getOffset(instant)
    Objects.requireNonNull(offset, "offset")
    val ldt: LocalDateTime                                                     =
      LocalDateTime.ofEpochSecond(instant.getEpochSecond, instant.getNano, offset)
    @SuppressWarnings(Array("unchecked")) val cldt: ChronoLocalDateTimeImpl[R] =
      chrono.localDateTime(ldt).asInstanceOf[ChronoLocalDateTimeImpl[R]]
    new ChronoZonedDateTimeImpl[R](cldt, offset, zone)
  }

}

/**
 * A date-time with a time-zone in the calendar neutral API.
 *
 * {@code ZoneChronoDateTime} is an immutable representation of a date-time with a time-zone. This
 * class stores all date and time fields, to a precision of nanoseconds, as well as a time-zone and
 * zone offset.
 *
 * The purpose of storing the time-zone is to distinguish the ambiguous case where the local
 * time-line overlaps, typically as a result of the end of daylight time. Information about the
 * local-time can be obtained using methods on the time-zone.
 *
 * 

Specification for implementors

This class is immutable and thread-safe. * * @tparam D * the date type * @constructor * @param dateTime * the date-time, not null * @param offset * the zone offset, not null * @param zone * the zone ID, not null */ @SerialVersionUID(-5261813987200935591L) final class ChronoZonedDateTimeImpl[D <: ChronoLocalDate] private ( private val dateTime: ChronoLocalDateTimeImpl[D], private val offset: ZoneOffset, private val zone: ZoneId ) extends ChronoZonedDateTime[D] with Serializable { Objects.requireNonNull(dateTime, "dateTime") Objects.requireNonNull(offset, "offset") Objects.requireNonNull(zone, "zone") /** * Obtains an instance from an {@code Instant}. * * @param instant * the instant to create the date-time from, not null * @param zone * the time-zone to use, validated not null * @return * the zoned date-time, validated not null */ private def create(instant: Instant, zone: ZoneId): ChronoZonedDateTimeImpl[D] = ChronoZonedDateTimeImpl.ofInstant(toLocalDate.getChronology, instant, zone) def isSupported(unit: TemporalUnit): Boolean = if (unit.isInstanceOf[ChronoUnit]) unit.isDateBased || unit.isTimeBased else unit != null && unit.isSupportedBy(this) def getOffset: ZoneOffset = offset def withEarlierOffsetAtOverlap: ChronoZonedDateTime[D] = { val trans: ZoneOffsetTransition = getZone.getRules.getTransition(LocalDateTime.from(this)) if (trans != null && trans.isOverlap) { val earlierOffset: ZoneOffset = trans.getOffsetBefore if (!(earlierOffset == offset)) return new ChronoZonedDateTimeImpl[D](dateTime, earlierOffset, zone) } this } def withLaterOffsetAtOverlap: ChronoZonedDateTime[D] = { val trans: ZoneOffsetTransition = getZone.getRules.getTransition(LocalDateTime.from(this)) if (trans != null) { val offset: ZoneOffset = trans.getOffsetAfter if (!(offset == getOffset)) return new ChronoZonedDateTimeImpl[D](dateTime, offset, zone) } this } def toLocalDateTime: ChronoLocalDateTime[D] = dateTime def getZone: ZoneId = zone def withZoneSameLocal(zone: ZoneId): ChronoZonedDateTime[D] = ChronoZonedDateTimeImpl.ofBest(dateTime, zone, offset) def withZoneSameInstant(zone: ZoneId): ChronoZonedDateTime[D] = { Objects.requireNonNull(zone, "zone") if (this.zone == zone) this else create(dateTime.toInstant(offset), zone) } def isSupported(field: TemporalField): Boolean = field.isInstanceOf[ChronoField] || (field != null && field.isSupportedBy(this)) def `with`(field: TemporalField, newValue: Long): ChronoZonedDateTime[D] = field match { case f: ChronoField => import ChronoField._ f match { case INSTANT_SECONDS => plus(newValue - toEpochSecond, SECONDS) case OFFSET_SECONDS => val offset: ZoneOffset = ZoneOffset.ofTotalSeconds(f.checkValidIntValue(newValue)) create(dateTime.toInstant(offset), zone) case _ => ChronoZonedDateTimeImpl.ofBest(dateTime.`with`(field, newValue), zone, offset) } case _ => toLocalDate.getChronology.ensureChronoZonedDateTime(field.adjustInto(this, newValue)) } def plus(amountToAdd: Long, unit: TemporalUnit): ChronoZonedDateTime[D] = if (unit.isInstanceOf[ChronoUnit]) `with`(dateTime.plus(amountToAdd, unit)) else toLocalDate.getChronology.ensureChronoZonedDateTime(unit.addTo(this, amountToAdd)) def until(endExclusive: Temporal, unit: TemporalUnit): Long = { var end: ChronoZonedDateTime[D] = toLocalDate.getChronology.zonedDateTime(endExclusive).asInstanceOf[ChronoZonedDateTime[D]] if (unit.isInstanceOf[ChronoUnit]) { end = end.withZoneSameInstant(offset) dateTime.until(end.toLocalDateTime, unit) } else unit.between(this, end) } override def equals(obj: Any): Boolean = obj match { case other: ChronoZonedDateTime[_] => (this eq other) || (compareTo(other) == 0) case _ => false } override def hashCode: Int = toLocalDateTime.hashCode ^ getOffset.hashCode ^ Integer.rotateLeft(getZone.hashCode, 3) override def toString: String = { var str: String = toLocalDateTime.toString + getOffset.toString if (getOffset ne getZone) str += s"[$getZone]" str } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy