Example #1
0
 public function addTo(Temporal $temporal, $amount)
 {
     switch ($this) {
         case IsoFields::WEEK_BASED_YEARS():
             return $temporal->with(IsoFields::WEEK_BASED_YEAR(), Math::addExact($temporal->get(IsoFields::WEEK_BASED_YEAR()), $amount));
         case IsoFields::QUARTER_YEARS():
             // no overflow (256 is multiple of 4)
             return $temporal->plus($amount / 256, ChronoUnit::YEARS())->plus($amount % 256 * 3, ChronoUnit::MONTHS());
         default:
             throw new IllegalStateException("Unreachable");
     }
 }
Example #2
0
 /**
  * Returns a copy of this {@code LocalDate} with the specified number of days added.
  * <p>
  * This method adds the specified amount to the days field incrementing the
  * month and year fields as necessary to ensure the result remains valid.
  * The result is only invalid if the maximum/minimum year is exceeded.
  * <p>
  * For example, 2008-12-31 plus one day would result in 2009-01-01.
  * <p>
  * This instance is immutable and unaffected by this method call.
  *
  * @param int $daysToAdd the days to add, may be negative
  * @return LocalDate a {@code LocalDate} based on this date with the days added, not null
  * @throws DateTimeException if the result exceeds the supported date range
  */
 public function plusDays($daysToAdd)
 {
     if ($daysToAdd === 0) {
         return $this;
     }
     try {
         $mjDay = Math::addExact($this->toEpochDay(), $daysToAdd);
         return self::ofEpochDay($mjDay);
     } catch (ArithmeticException $ex) {
         throw new DateTimeException('Value out of bounds', $ex);
     }
 }
Example #3
0
 private function nanosUntil(Instant $end)
 {
     $secsDiff = Math::subtractExact($end->seconds, $this->seconds);
     $totalNanos = Math::multiplyExact($secsDiff, LocalTime::NANOS_PER_SECOND);
     return Math::addExact($totalNanos, $end->nanos - $this->nanos);
 }
 /**
  * @param int $amountToAdd
  * @param TemporalUnit $unit
  * @return static
  * @throws UnsupportedTemporalTypeException
  */
 public function plus($amountToAdd, TemporalUnit $unit)
 {
     if ($unit instanceof CU) {
         switch ($unit) {
             case CU::DAYS():
                 return $this->plusDays($amountToAdd);
             case CU::WEEKS():
                 return $this->plusDays(Math::multiplyExact($amountToAdd, 7));
             case CU::MONTHS():
                 return $this->plusMonths($amountToAdd);
             case CU::YEARS():
                 return $this->plusYears($amountToAdd);
             case CU::DECADES():
                 return $this->plusYears(Math::multiplyExact($amountToAdd, 10));
             case CU::CENTURIES():
                 return $this->plusYears(Math::multiplyExact($amountToAdd, 100));
             case CU::MILLENNIA():
                 return $this->plusYears(Math::multiplyExact($amountToAdd, 1000));
             case CU::ERAS():
                 return $this->with(CF::ERA(), Math::addExact($this->getLong(CF::ERA()), $amountToAdd));
         }
         throw new UnsupportedTemporalTypeException("Unsupported unit: " . $unit);
     }
     return parent::plus($amountToAdd, $unit);
 }
Example #5
0
 /**
  * Converts this duration to the total length in nanoseconds expressed as a {@code long}.
  * <p>
  * If this duration is too large to fit in a {@code long} nanoseconds, then an
  * exception is thrown.
  *
  * @return int the total length of the duration in nanoseconds
  * @throws ArithmeticException if numeric overflow occurs
  */
 public function toNanos()
 {
     $totalNanos = Math::multiplyExact($this->seconds, LocalTime::NANOS_PER_SECOND);
     $totalNanos = Math::addExact($totalNanos, $this->nanos);
     return $totalNanos;
 }
Example #6
0
 /**
  * Returns a copy of this year with the specified amount added.
  * <p>
  * This returns a {@code Year}, based on this one, with the amount
  * in terms of the unit added. If it is not possible to add the amount, because the
  * unit is not supported or for some other reason, an exception is thrown.
  * <p>
  * If the field is a {@link ChronoUnit} then the addition is implemented here.
  * The supported fields behave as follows:
  * <ul>
  * <li>{@code YEARS} -
  *  Returns a {@code Year} with the specified number of years added.
  *  This is equivalent to {@link #plusYears(long)}.
  * <li>{@code DECADES} -
  *  Returns a {@code Year} with the specified number of decades added.
  *  This is equivalent to calling {@link #plusYears(long)} with the amount
  *  multiplied by 10.
  * <li>{@code CENTURIES} -
  *  Returns a {@code Year} with the specified number of centuries added.
  *  This is equivalent to calling {@link #plusYears(long)} with the amount
  *  multiplied by 100.
  * <li>{@code MILLENNIA} -
  *  Returns a {@code Year} with the specified number of millennia added.
  *  This is equivalent to calling {@link #plusYears(long)} with the amount
  *  multiplied by 1,000.
  * <li>{@code ERAS} -
  *  Returns a {@code Year} with the specified number of eras added.
  *  Only two eras are supported so the amount must be one, zero or minus one.
  *  If the amount is non-zero then the year is changed such that the year-of-era
  *  is unchanged.
  * </ul>
  * <p>
  * All other {@code ChronoUnit} instances will throw an {@code UnsupportedTemporalTypeException}.
  * <p>
  * If the field is not a {@code ChronoUnit}, then the result of this method
  * is obtained by invoking {@code TemporalUnit.addTo(Temporal, long)}
  * passing {@code this} as the argument. In this case, the unit determines
  * whether and how to perform the addition.
  * <p>
  * This instance is immutable and unaffected by this method call.
  *
  * @param int $amountToAdd the amount of the unit to add to the result, may be negative
  * @param TemporalUnit $unit the unit of the amount to add, not null
  * @return Year a {@code Year} based on this year with the specified amount added, not null
  * @throws DateTimeException if the addition cannot be made
  * @throws UnsupportedTemporalTypeException if the unit is not supported
  * @throws ArithmeticException if numeric overflow occurs
  */
 public function plus($amountToAdd, TemporalUnit $unit)
 {
     if ($unit instanceof ChronoUnit) {
         switch ($unit) {
             case ChronoUnit::YEARS():
                 return $this->plusYears($amountToAdd);
             case ChronoUnit::DECADES():
                 return $this->plusYears(Math::multiplyExact($amountToAdd, 10));
             case ChronoUnit::CENTURIES():
                 return $this->plusYears(Math::multiplyExact($amountToAdd, 100));
             case ChronoUnit::MILLENNIA():
                 return $this->plusYears(Math::multiplyExact($amountToAdd, 1000));
             case ChronoUnit::ERAS():
                 return $this->with(ChronoField::ERA(), Math::addExact($this->getLong(ChronoField::ERA()), $amountToAdd));
         }
         throw new UnsupportedTemporalTypeException("Unsupported unit: " . $unit);
     }
     return $unit->addTo($this, $amountToAdd);
 }
Example #7
0
 private function resolveTime($hod, $moh, $som, $nos)
 {
     if ($this->resolverStyle == ResolverStyle::LENIENT()) {
         $totalNanos = Math::multiplyExact($hod, 3600000000000);
         $totalNanos = Math::addExact($totalNanos, Math::multiplyExact($moh, 60000000000));
         $totalNanos = Math::addExact($totalNanos, Math::multiplyExact($som, 1000000000));
         $totalNanos = Math::addExact($totalNanos, $nos);
         $excessDays = (int) Math::floorDiv($totalNanos, 86400000000000);
         // safe int cast
         $nod = Math::floorMod($totalNanos, 86400000000000);
         $this->updateCheckConflict(LocalTime::ofNanoOfDay($nod), Period::ofDays($excessDays));
     } else {
         // STRICT or SMART
         $mohVal = CF::MINUTE_OF_HOUR()->checkValidIntValue($moh);
         $nosVal = CF::NANO_OF_SECOND()->checkValidIntValue($nos);
         // handle 24:00 end of day
         if ($this->resolverStyle == ResolverStyle::SMART() && $hod == 24 && $mohVal == 0 && $som == 0 && $nosVal == 0) {
             $this->updateCheckConflict(LocalTime::MIDNIGHT(), Period::ofDays(1));
         } else {
             $hodVal = CF::HOUR_OF_DAY()->checkValidIntValue($hod);
             $somVal = CF::SECOND_OF_MINUTE()->checkValidIntValue($som);
             $this->updateCheckConflict(LocalTime::of($hodVal, $mohVal, $somVal, $nosVal), Period::ZERO());
         }
     }
 }
Example #8
0
 /**
  * Calculates the amount of time until another date-time in terms of the specified unit.
  * <p>
  * This calculates the amount of time between two {@code LocalDateTime}
  * objects in terms of a single {@code TemporalUnit}.
  * The start and end points are {@code this} and the specified date-time.
  * The result will be negative if the end is before the start.
  * The {@code Temporal} passed to this method is converted to a
  * {@code LocalDateTime} using {@link #from(TemporalAccessor)}.
  * For example, the amount in days between two date-times can be calculated
  * using {@code startDateTime.until(endDateTime, DAYS)}.
  * <p>
  * The calculation returns a whole number, representing the number of
  * complete units between the two date-times.
  * For example, the amount in months between 2012-06-15T00:00 and 2012-08-14T23:59
  * will only be one month as it is one minute short of two months.
  * <p>
  * There are two equivalent ways of using this method.
  * The first is to invoke this method.
  * The second is to use {@link TemporalUnit#between(Temporal, Temporal)}:
  * <pre>
  *   // these two lines are equivalent
  *   amount = start.until(end, MONTHS);
  *   amount = MONTHS.between(start, end);
  * </pre>
  * The choice should be made based on which makes the code more readable.
  * <p>
  * The calculation is implemented in this method for {@link ChronoUnit}.
  * The units {@code NANOS}, {@code MICROS}, {@code MILLIS}, {@code SECONDS},
  * {@code MINUTES}, {@code HOURS} and {@code HALF_DAYS}, {@code DAYS},
  * {@code WEEKS}, {@code MONTHS}, {@code YEARS}, {@code DECADES},
  * {@code CENTURIES}, {@code MILLENNIA} and {@code ERAS} are supported.
  * Other {@code ChronoUnit} values will throw an exception.
  * <p>
  * If the unit is not a {@code ChronoUnit}, then the result of this method
  * is obtained by invoking {@code TemporalUnit.between(Temporal, Temporal)}
  * passing {@code this} as the first argument and the converted input temporal
  * as the second argument.
  * <p>
  * This instance is immutable and unaffected by this method call.
  *
  * @param Temporal $endExclusive the end date, exclusive, which is converted to a {@code LocalDateTime}, not null
  * @param TemporalUnit $unit the unit to measure the amount in, not null
  * @return int the amount of time between this date-time and the end date-time
  * @throws DateTimeException if the amount cannot be calculated, or the end
  *  temporal cannot be converted to a {@code LocalDateTime}
  * @throws UnsupportedTemporalTypeException if the unit is not supported
  * @throws ArithmeticException if numeric overflow occurs
  */
 public function until(Temporal $endExclusive, TemporalUnit $unit)
 {
     $end = LocalDateTime::from($endExclusive);
     if ($unit instanceof ChronoUnit) {
         if ($unit->isTimeBased()) {
             $amount = $this->date->daysUntil($end->date);
             if ($amount === 0) {
                 return $this->time->until($end->time, $unit);
             }
             $timePart = $end->time->toNanoOfDay() - $this->time->toNanoOfDay();
             if ($amount > 0) {
                 $amount--;
                 // safe
                 $timePart += LocalTime::NANOS_PER_DAY;
                 // safe
             } else {
                 $amount++;
                 // safe
                 $timePart -= LocalTime::NANOS_PER_DAY;
                 // safe
             }
             switch ($unit) {
                 case ChronoUnit::NANOS():
                     $amount = Math::multiplyExact($amount, LocalTime::NANOS_PER_DAY);
                     break;
                 case ChronoUnit::MICROS():
                     $amount = Math::multiplyExact($amount, LocalTime::MICROS_PER_DAY);
                     $timePart = Math::div($timePart, 1000);
                     break;
                 case ChronoUnit::MILLIS():
                     $amount = Math::multiplyExact($amount, LocalTime::MILLIS_PER_DAY);
                     $timePart = Math::div($timePart, 1000000);
                     break;
                 case ChronoUnit::SECONDS():
                     $amount = Math::multiplyExact($amount, LocalTime::SECONDS_PER_DAY);
                     $timePart = Math::div($timePart, LocalTime::NANOS_PER_SECOND);
                     break;
                 case ChronoUnit::MINUTES():
                     $amount = Math::multiplyExact($amount, LocalTime::MINUTES_PER_DAY);
                     $timePart = Math::div($timePart, LocalTime::NANOS_PER_MINUTE);
                     break;
                 case ChronoUnit::HOURS():
                     $amount = Math::multiplyExact($amount, LocalTime::HOURS_PER_DAY);
                     $timePart = Math::div($timePart, LocalTime::NANOS_PER_HOUR);
                     break;
                 case ChronoUnit::HALF_DAYS():
                     $amount = Math::multiplyExact($amount, 2);
                     $timePart = Math::div($timePart, LocalTime::NANOS_PER_HOUR * 12);
                     break;
             }
             return Math::addExact($amount, $timePart);
         }
         $endDate = $end->date;
         if ($endDate->isAfter($this->date) && $end->time->isBefore($this->time)) {
             $endDate = $endDate->minusDays(1);
         } else {
             if ($endDate->isBefore($this->date) && $end->time->isAfter($this->time)) {
                 $endDate = $endDate->plusDays(1);
             }
         }
         return $this->date->until($endDate, $unit);
     }
     return $unit->between($this, $end);
 }
 private function resolveWoY(FieldValues $fieldValues, Chronology $chrono, $year, $woy, $localDow, ResolverStyle $resolverStyle)
 {
     $date = $chrono->date($year, 1, 1);
     if ($resolverStyle == ResolverStyle::LENIENT()) {
         $weeks = Math::subtractExact($woy, $this->localizedWeekOfYear($date));
         $days = $localDow - $this->localizedDayOfWeek($date);
         // safe from overflow
         $date = $date->plus(Math::addExact(Math::multiplyExact($weeks, 7), $days), ChronoUnit::DAYS());
     } else {
         $womInt = $this->range->checkValidIntValue($woy, $this);
         // validate
         $weeks = (int) ($womInt - $this->localizedWeekOfYear($date));
         // safe from overflow
         $days = $localDow - $this->localizedDayOfWeek($date);
         // safe from overflow
         $date = $date->plus($weeks * 7 + $days, ChronoUnit::DAYS());
         if ($resolverStyle == ResolverStyle::STRICT() && $date->getLong(CF::YEAR()) !== $year) {
             throw new DateTimeException("Strict mode rejected resolved date as it is in a different year");
         }
     }
     $fieldValues->remove($this);
     $fieldValues->remove(CF::YEAR());
     $fieldValues->remove(CF::DAY_OF_WEEK());
     return $date;
 }
 public function until(Temporal $endExclusive, TemporalUnit $unit)
 {
     $end = $this->getChronology()->localDateTime($endExclusive);
     if ($unit instanceof ChronoUnit) {
         if ($unit->isTimeBased()) {
             $amount = $end->getLong(ChronoField::EPOCH_DAY()) - $this->date->getLong(ChronoField::EPOCH_DAY());
             switch ($unit) {
                 case ChronoUnit::NANOS():
                     $amount = Math::multiplyExact($amount, self::NANOS_PER_DAY);
                     break;
                 case ChronoUnit::MICROS():
                     $amount = Math::multiplyExact($amount, self::MICROS_PER_DAY);
                     break;
                 case ChronoUnit::MILLIS():
                     $amount = Math::multiplyExact($amount, self::MILLIS_PER_DAY);
                     break;
                 case ChronoUnit::SECONDS():
                     $amount = Math::multiplyExact($amount, self::SECONDS_PER_DAY);
                     break;
                 case ChronoUnit::MINUTES():
                     $amount = Math::multiplyExact($amount, self::MINUTES_PER_DAY);
                     break;
                 case ChronoUnit::HOURS():
                     $amount = Math::multiplyExact($amount, self::HOURS_PER_DAY);
                     break;
                 case ChronoUnit::HALF_DAYS():
                     $amount = Math::multiplyExact($amount, 2);
                     break;
             }
             return Math::addExact($amount, $this->time->until($end->toLocalTime(), $unit));
         }
         $endDate = $end->toLocalDate();
         if ($end->toLocalTime()->isBefore($this->time)) {
             $endDate = $endDate->minus(1, ChronoUnit::DAYS());
         }
         return $this->date->until($endDate, $unit);
     }
     return $unit->between($this, $end);
 }
Example #11
0
 /**
  * Gets the total number of months in this period.
  * <p>
  * This returns the total number of months in the period by multiplying the
  * number of years by 12 and adding the number of months.
  * <p>
  * This instance is immutable and unaffected by this method call.
  *
  * @return int the total number of months in the period, may be negative
  */
 public function toTotalMonths()
 {
     return Math::addExact(Math::multiplyExact($this->years, 12), $this->months);
 }