/** * Returns a copy of this {@code Instant} truncated to the specified unit. * <p> * Truncating the instant returns a copy of the original with fields * smaller than the specified unit set to zero. * The fields are calculated on the basis of using a UTC offset as seen * in {@code toString}. * For example, truncating with the {@link ChronoUnit#MINUTES MINUTES} unit will * round down to the nearest minute, setting the seconds and nanoseconds to zero. * <p> * The unit must have a {@linkplain TemporalUnit#getDuration() duration} * that divides into the length of a standard day without remainder. * This includes all supplied time units on {@link ChronoUnit} and * {@link ChronoUnit#DAYS DAYS}. Other units throw an exception. * <p> * This instance is immutable and unaffected by this method call. * * @param TemporalUnit $unit the unit to truncate to, not null * @return Instant an {@code Instant} based on this instant with the time truncated, not null * @throws DateTimeException if the unit is invalid for truncation * @throws UnsupportedTemporalTypeException if the unit is not supported */ public function truncatedTo(TemporalUnit $unit) { if ($unit == ChronoUnit::NANOS()) { return $this; } $unitDur = $unit->getDuration(); if ($unitDur->getSeconds() > LocalTime::SECONDS_PER_DAY) { throw new UnsupportedTemporalTypeException("Unit is too large to be used for truncation"); } $dur = $unitDur->toNanos(); if (LocalTime::NANOS_PER_DAY % $dur !== 0) { throw new UnsupportedTemporalTypeException("Unit must divide into a standard day without remainder"); } $nod = $this->seconds % LocalTime::SECONDS_PER_DAY * LocalTime::NANOS_PER_SECOND + $this->nanos; $result = Math::div($nod, $dur) * $dur; return $this->plusNanos($result - $nod); }
/** * Returns a copy of this {@code LocalTime} with the time truncated. * <p> * Truncation returns a copy of the original time with fields * smaller than the specified unit set to zero. * For example, truncating with the {@link ChronoUnit#MINUTES minutes} unit * will set the second-of-minute and nano-of-second field to zero. * <p> * The unit must have a {@linkplain TemporalUnit#getDuration() duration} * that divides into the length of a standard day without remainder. * This includes all supplied time units on {@link ChronoUnit} and * {@link ChronoUnit#DAYS DAYS}. Other units throw an exception. * <p> * This instance is immutable and unaffected by this method call. * * @param TemporalUnit $unit the unit to truncate to, not null * @return LocalTime a {@code LocalTime} based on this time with the time truncated, not null * @throws DateTimeException if unable to truncate * @throws UnsupportedTemporalTypeException if the unit is not supported */ public function truncatedTo(TemporalUnit $unit) { if ($unit == ChronoUnit::NANOS()) { return $this; } $unitDur = $unit->getDuration(); if ($unitDur->getSeconds() > self::SECONDS_PER_DAY) { throw new UnsupportedTemporalTypeException("Unit is too large to be used for truncation"); } $dur = $unitDur->toNanos(); if (self::NANOS_PER_DAY % $dur != 0) { throw new UnsupportedTemporalTypeException("Unit must divide into a standard day without remainder"); } $nod = $this->toNanoOfDay(); return $this->ofNanoOfDay(Math::div($nod, $dur) * $dur); }
/** * Returns a copy of this duration with the specified duration added. * <p> * The duration amount is measured in terms of the specified unit. * Only a subset of units are accepted by this method. * The unit must either have an {@linkplain TemporalUnit#isDurationEstimated() exact duration} or * be {@link ChronoUnit#DAYS} which is treated as 24 hours. Other units throw an exception. * <p> * This instance is immutable and unaffected by this method call. * * @param int $amountToAdd the amount to add, measured in terms of the unit, positive or negative * @param TemporalUnit $unit the unit that the amount is measured in, must have an exact duration, not null * @return Duration a {@code Duration} based on this duration with the specified duration added, not null * @throws UnsupportedTemporalTypeException if the unit is not supported * @throws ArithmeticException if numeric overflow occurs */ public function plus($amountToAdd, TemporalUnit $unit) { if ($unit == ChronoUnit::DAYS()) { return $this->_plus(Math::multiplyExact($amountToAdd, LocalTime::SECONDS_PER_DAY), 0); } if ($unit->isDurationEstimated()) { throw new UnsupportedTemporalTypeException("Unit must not have an estimated duration"); } if ($amountToAdd == 0) { return $this; } if ($unit instanceof ChronoUnit) { switch ($unit) { case ChronoUnit::NANOS(): return $this->plusNanos($amountToAdd); case ChronoUnit::MICROS(): return $this->plusSeconds(Math::div($amountToAdd, 1000000 * 1000) * 1000)->plusNanos($amountToAdd % (1000000 * 1000) * 1000); case ChronoUnit::MILLIS(): return $this->plusMillis($amountToAdd); case ChronoUnit::SECONDS(): return $this->plusSeconds($amountToAdd); } return $this->plusSeconds(Math::multiplyExact($unit->getDuration()->seconds, $amountToAdd)); } $duration = $unit->getDuration()->multipliedBy($amountToAdd); return $this->plusSeconds($duration->getSeconds())->plusNanos($duration->getNano()); }