/** * @inheritdoc */ public function isUnitSupported(TemporalUnit $unit) { if ($unit instanceof ChronoUnit) { return $unit != ChronoUnit::FOREVER(); } return $unit != null && $unit->isSupportedBy($this); }
/** * Calculates the amount of time until another instant in terms of the specified unit. * <p> * This calculates the amount of time between two {@code Instant} * objects in terms of a single {@code TemporalUnit}. * The start and end points are {@code this} and the specified instant. * The result will be negative if the end is before the start. * The calculation returns a whole number, representing the number of * complete units between the two instants. * The {@code Temporal} passed to this method is converted to a * {@code Instant} using {@link #from(TemporalAccessor)}. * For example, the amount in days between two dates can be calculated * using {@code startInstant.until(endInstant, SECONDS)}. * <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, SECONDS); * amount = SECONDS.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}, {@code HALF_DAYS} and {@code DAYS} * 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 an Instant {@code Instant}, not null * @param TemporalUnit $unit the unit to measure the amount in, not null * @return int the amount of time between this instant and the end instant * @throws DateTimeException if the amount cannot be calculated, or the end * temporal cannot be converted to an Instant {@code Instant} * @throws UnsupportedTemporalTypeException if the unit is not supported * @throws ArithmeticException if numeric overflow occurs */ public function until(Temporal $endExclusive, TemporalUnit $unit) { $end = Instant::from($endExclusive); if ($unit instanceof ChronoUnit) { $f = $unit; switch ($f) { case ChronoUnit::NANOS(): return $this->nanosUntil($end); case ChronoUnit::MICROS(): return Math::div($this->nanosUntil($end), 1000); case ChronoUnit::MILLIS(): return Math::subtractExact($end->toEpochMilli(), $this->toEpochMilli()); case ChronoUnit::SECONDS(): return $this->secondsUntil($end); case ChronoUnit::MINUTES(): return Math::div($this->secondsUntil($end), LocalTime::SECONDS_PER_MINUTE); case ChronoUnit::HOURS(): return Math::div($this->secondsUntil($end), LocalTime::SECONDS_PER_HOUR); case ChronoUnit::HALF_DAYS(): return Math::div($this->secondsUntil($end), 12 * LocalTime::SECONDS_PER_HOUR); case ChronoUnit::DAYS(): return Math::div($this->secondsUntil($end), LocalTime::SECONDS_PER_DAY); } throw new UnsupportedTemporalTypeException("Unsupported unit: " . $unit); } return $unit->between($this, $end); }
/** * @dataProvider data_periodUntilUnit */ public function test_until_TemporalUnit_between(LocalDateTime $dt1, LocalDateTime $dt2, TemporalUnit $unit, $expected) { $amount = $unit->between($dt1, $dt2); $this->assertEquals($amount, $expected); }
/** * @dataProvider data_periodUntilUnit */ public function test_until_TemporalUnit_between(YearMonth $ym1, YearMonth $ym2, TemporalUnit $unit, $expected) { $amount = $unit->between($ym1, $ym2); $this->assertEquals($amount, $expected); }
public function until(Temporal $endExclusive, TemporalUnit $unit) { $end = $this->getChronology()->dateFrom($endExclusive); if ($unit instanceof ChronoUnit) { switch ($unit) { case CU::DAYS(): return $this->daysUntil($end); case CU::WEEKS(): return $this->daysUntil($end) / 7; case CU::MONTHS(): return $this->monthsUntil($end); case CU::YEARS(): return $this->monthsUntil($end) / 12; case CU::DECADES(): return $this->monthsUntil($end) / 120; case CU::CENTURIES(): return $this->monthsUntil($end) / 1200; case CU::MILLENNIA(): return $this->monthsUntil($end) / 12000; case CU::ERAS(): return $end->getLong(CF::ERA()) - $this->getLong(CF::ERA()); } throw new UnsupportedTemporalTypeException("Unsupported unit: " . $unit); } return $unit->between($this, $end); }
/** * 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()); }
/** * Calculates the amount of time until another year in terms of the specified unit. * <p> * This calculates the amount of time between two {@code Year} * objects in terms of a single {@code TemporalUnit}. * The start and end points are {@code this} and the specified year. * The result will be negative if the end is before the start. * The {@code Temporal} passed to this method is converted to a * {@code Year} using {@link #from(TemporalAccessor)}. * For example, the amount in decades between two year can be calculated * using {@code startYear.until(endYear, DECADES)}. * <p> * The calculation returns a whole number, representing the number of * complete units between the two years. * For example, the amount in decades between 2012 and 2031 * will only be one decade as it is one year short of two decades. * <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, YEARS); * amount = YEARS.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 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 Year}, not null * @param TemporalUnit $unit the unit to measure the amount in, not null * @return int the amount of time between this year and the end year * @throws DateTimeException if the amount cannot be calculated, or the end * temporal cannot be converted to a {@code Year} * @throws UnsupportedTemporalTypeException if the unit is not supported * @throws ArithmeticException if numeric overflow occurs */ public function until(Temporal $endExclusive, TemporalUnit $unit) { $end = Year::from($endExclusive); if ($unit instanceof ChronoUnit) { $yearsUntil = $end->year - $this->year; // no overflow switch ($unit) { case ChronoUnit::YEARS(): return $yearsUntil; case ChronoUnit::DECADES(): return Math::div($yearsUntil, 10); case ChronoUnit::CENTURIES(): return Math::div($yearsUntil, 100); case ChronoUnit::MILLENNIA(): return Math::div($yearsUntil, 1000); case ChronoUnit::ERAS(): return $end->getLong(ChronoField::ERA()) - $this->getLong(ChronoField::ERA()); } throw new UnsupportedTemporalTypeException("Unsupported unit: " . $unit); } return $unit->between($this, $end); }
/** * Calculates the amount of time until another time in terms of the specified unit. * <p> * This calculates the amount of time between two {@code OffsetTime} * objects in terms of a single {@code TemporalUnit}. * The start and end points are {@code this} and the specified time. * The result will be negative if the end is before the start. * For example, the amount in hours between two times can be calculated * using {@code startTime.until(endTime, HOURS)}. * <p> * The {@code Temporal} passed to this method is converted to a * {@code OffsetTime} using {@link #from(TemporalAccessor)}. * If the offset differs between the two times, then the specified * end time is normalized to have the same offset as this time. * <p> * The calculation returns a whole number, representing the number of * complete units between the two times. * For example, the amount in hours between 11:30Z and 13:29Z will only * be one hour as it is one minute short of two hours. * <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, MINUTES); * amount = MINUTES.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} 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 time, exclusive, which is converted to an {@code OffsetTime}, not null * @param TemporalUnit $unit the unit to measure the amount in, not null * @return int the amount of time between this time and the end time * @throws DateTimeException if the amount cannot be calculated, or the end * temporal cannot be converted to an {@code OffsetTime} * @throws UnsupportedTemporalTypeException if the unit is not supported * @throws ArithmeticException if numeric overflow occurs */ public function until(Temporal $endExclusive, TemporalUnit $unit) { $end = OffsetTime::from($endExclusive); if ($unit instanceof ChronoUnit) { $nanosUntil = $end->toEpochNano() - $this->toEpochNano(); // no overflow switch ($unit) { case ChronoUnit::NANOS(): return $nanosUntil; case ChronoUnit::MICROS(): return $nanosUntil / 1000; case ChronoUnit::MILLIS(): return $nanosUntil / 1000000; case ChronoUnit::SECONDS(): return $nanosUntil / LocalTime::NANOS_PER_SECOND; case ChronoUnit::MINUTES(): return $nanosUntil / LocalTime::NANOS_PER_MINUTE; case ChronoUnit::HOURS(): return $nanosUntil / LocalTime::NANOS_PER_HOUR; case ChronoUnit::HALF_DAYS(): return $nanosUntil / (12 * LocalTime::NANOS_PER_HOUR); } throw new UnsupportedTemporalTypeException("Unsupported unit: " . $unit); } return $unit->between($this, $end); }
/** * @inheritdoc */ public function plus($amountToAdd, TemporalUnit $unit) { if ($unit instanceof ChronoUnit) { throw new UnsupportedTemporalTypeException("Unsupported unit: " . $unit); } return ChronoLocalDateImpl::ensureValid($this->getChronology(), $unit->addTo($this, $amountToAdd)); }
/** * 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); }
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); }
/** * 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 ZonedDateTime} * 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. * For example, the amount in days between two date-times can be calculated * using {@code startDateTime.until(endDateTime, DAYS)}. * <p> * The {@code Temporal} passed to this method is converted to a * {@code ZonedDateTime} using {@link #from(TemporalAccessor)}. * If the time-zone differs between the two zoned date-times, the specified * end date-time is normalized to have the same zone as this date-time. * <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:00Z and 2012-08-14T23:59Z * 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> * The calculation for date and time units differ. * <p> * Date units operate on the local time-line, using the local date-time. * For example, the period from noon on day 1 to noon the following day * in days will always be counted as exactly one day, irrespective of whether * there was a daylight savings change or not. * <p> * Time units operate on the instant time-line. * The calculation effectively converts both zoned date-times to instants * and then calculates the period between the instants. * For example, the period from noon on day 1 to noon the following day * in hours may be 23, 24 or 25 hours (or some other amount) depending on * whether there was a daylight savings change or not. * <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 ZonedDateTime}, 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 ZonedDateTime} * @throws UnsupportedTemporalTypeException if the unit is not supported * @throws ArithmeticException if numeric overflow occurs */ public function until(Temporal $endExclusive, TemporalUnit $unit) { $end = ZonedDateTime::from($endExclusive); if ($unit instanceof ChronoUnit) { $end = $end->withZoneSameInstant($this->zone); if ($unit->isDateBased()) { return $this->dateTime->until($end->dateTime, $unit); } else { return $this->toOffsetDateTime()->until($end->toOffsetDateTime(), $unit); } } return $unit->between($this, $end); }
/** * @dataProvider data_untilUnit */ public function test_until_TemporalUnit_between(OffsetTime $offsetTime1, OffsetTime $offsetTime2, TemporalUnit $unit, $expected) { $amount = $unit->between($offsetTime1, $offsetTime2); $this->assertEquals($amount, $expected); }
/** * Calculates the amount of time until another date in terms of the specified unit. * <p> * This calculates the amount of time between two {@code LocalDate} * objects in terms of a single {@code TemporalUnit}. * The start and end points are {@code this} and the specified date. * The result will be negative if the end is before the start. * The {@code Temporal} passed to this method is converted to a * {@code LocalDate} using {@link #from(TemporalAccessor)}. * For example, the amount in days between two dates can be calculated * using {@code startDate.until(endDate, DAYS)}. * <p> * The calculation returns a whole number, representing the number of * complete units between the two dates. * For example, the amount in months between 2012-06-15 and 2012-08-14 * will only be one month as it is one day 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 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 LocalDate}, not null * @param TemporalUnit $unit the unit to measure the amount in, not null * @return int the amount of time between this date and the end date * @throws DateTimeException if the amount cannot be calculated, or the end * temporal cannot be converted to a {@code LocalDate} * @throws UnsupportedTemporalTypeException if the unit is not supported * @throws ArithmeticException if numeric overflow occurs */ public function until(Temporal $endExclusive, TemporalUnit $unit) { $end = LocalDate::from($endExclusive); if ($unit instanceof ChronoUnit) { switch ($unit) { case ChronoUnit::DAYS(): return $this->daysUntil($end); case ChronoUnit::WEEKS(): return Math::div($this->daysUntil($end), 7); case ChronoUnit::MONTHS(): return $this->monthsUntil($end); case ChronoUnit::YEARS(): return Math::div($this->monthsUntil($end), 12); case ChronoUnit::DECADES(): return Math::div($this->monthsUntil($end), 120); case ChronoUnit::CENTURIES(): return Math::div($this->monthsUntil($end), 1200); case ChronoUnit::MILLENNIA(): return Math::div($this->monthsUntil($end), 12000); case ChronoUnit::ERAS(): return $end->getLong(ChronoField::ERA()) - $this->getLong(ChronoField::ERA()); } throw new UnsupportedTemporalTypeException("Unsupported unit: " . $unit); } return $unit->between($this, $end); }
public function equals($obj) { if ($this === $obj) { return true; } if ($obj instanceof MockSimplePeriod) { $other = $obj; return $this->amount == $other->amount && $this->unit->equals($other->unit); } return false; }
/** * Calculates the amount of time until another time in terms of the specified unit. * <p> * This calculates the amount of time between two {@code LocalTime} * objects in terms of a single {@code TemporalUnit}. * The start and end points are {@code this} and the specified 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 LocalTime} using {@link #from(TemporalAccessor)}. * For example, the amount in hours between two times can be calculated * using {@code startTime.until(endTime, HOURS)}. * <p> * The calculation returns a whole number, representing the number of * complete units between the two times. * For example, the amount in hours between 11:30 and 13:29 will only * be one hour as it is one minute short of two hours. * <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, MINUTES); * amount = MINUTES.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} 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 time, exclusive, which is converted to a {@code LocalTime}, not null * @param $unit $unit the unit to measure the amount in, not null * @return int the amount of time between this time and the end time * @throws DateTimeException if the amount cannot be calculated, or the end * temporal cannot be converted to a {@code LocalTime} * @throws UnsupportedTemporalTypeException if the unit is not supported * @throws ArithmeticException if numeric overflow occurs */ public function until(Temporal $endExclusive, TemporalUnit $unit) { $end = self::from($endExclusive); if ($unit instanceof ChronoUnit) { $nanosUntil = $end->toNanoOfDay() - $this->toNanoOfDay(); // no overflow switch ($unit) { case ChronoUnit::NANOS(): return $nanosUntil; case ChronoUnit::MICROS(): return Math::div($nanosUntil, 1000); case ChronoUnit::MILLIS(): return Math::div($nanosUntil, 1000000); case ChronoUnit::SECONDS(): return Math::div($nanosUntil, self::NANOS_PER_SECOND); case ChronoUnit::MINUTES(): return Math::div($nanosUntil, self::NANOS_PER_MINUTE); case ChronoUnit::HOURS(): return Math::div($nanosUntil, self::NANOS_PER_HOUR); case ChronoUnit::HALF_DAYS(): return Math::div($nanosUntil, 12 * self::NANOS_PER_HOUR); } throw new UnsupportedTemporalTypeException("Unsupported unit: " . $unit); } return $unit->between($this, $end); }
/** * @dataProvider data_periodUntilUnit */ public function test_until_TemporalUnit_between($seconds1, $nanos1, $seconds2, $nanos2, TemporalUnit $unit, $expected) { $i1 = Instant::ofEpochSecond($seconds1, $nanos1); $i2 = Instant::ofEpochSecond($seconds2, $nanos2); $amount = $unit->between($i1, $i2); $this->assertEquals($amount, $expected); }