public function format(DateTimePrintContext $context, &$buf)
 {
     /** @var ZoneID $zone */
     $zone = $context->getValue(TemporalQueries::zoneId());
     if ($zone === null) {
         return false;
     }
     $zname = $zone->getId();
     if (!$zone instanceof ZoneOffset) {
         $dt = $context->getTemporal();
         $name = $this->getDisplayName($zname, $dt->isSupported(ChronoField::INSTANT_SECONDS()) ? $zone->getRules()->isDaylightSavings(Instant::from($dt)) ? self::$DST : self::$STD : self::$GENERIC, $context->getLocale());
         if ($name !== null) {
             $zname = $name;
         }
     }
     $buf .= $zname;
     return true;
 }
 /**
  * Obtains an instance of {@code OffsetDateTime} from a temporal object.
  * <p>
  * This obtains an offset date-time based on the specified temporal.
  * A {@code TemporalAccessor} represents an arbitrary set of date and time information,
  * which this factory converts to an instance of {@code OffsetDateTime}.
  * <p>
  * The conversion will first obtain a {@code ZoneOffset} from the temporal object.
  * It will then try to obtain a {@code LocalDateTime}, falling back to an {@code Instant} if necessary.
  * The result will be the combination of {@code ZoneOffset} with either
  * with {@code LocalDateTime} or {@code Instant}.
  * Implementations are permitted to perform optimizations such as accessing
  * those fields that are equivalent to the relevant objects.
  * <p>
  * This method matches the signature of the functional interface {@link TemporalQuery}
  * allowing it to be used as a query via method reference, {@code OffsetDateTime::from}.
  *
  * @param TemporalAccessor $temporal the temporal object to convert, not null
  * @return OffsetDateTime the offset date-time, not null
  * @throws DateTimeException if unable to convert to an {@code OffsetDateTime}
  */
 public static function from(TemporalAccessor $temporal)
 {
     if ($temporal instanceof OffsetDateTime) {
         return $temporal;
     }
     try {
         $offset = ZoneOffset::from($temporal);
         $date = $temporal->query(TemporalQueries::localDate());
         $time = $temporal->query(TemporalQueries::localTime());
         if ($date !== null && $time !== null) {
             return OffsetDateTime::ofDateAndTime($date, $time, $offset);
         } else {
             $instant = Instant::from($temporal);
             return OffsetDateTime::ofInstant($instant, $offset);
         }
     } catch (DateTimeException $ex) {
         throw new DateTimeException("Unable to obtain OffsetDateTime from TemporalAccessor: " . $temporal . " of type " . get_class($temporal), $ex);
     }
 }
Beispiel #3
0
 /**
  * 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_instantNoZone
  */
 public function test_parse_instantNoZone_Instant(DateTimeFormatter $formatter, $text, Instant $expected)
 {
     $actual = $formatter->parse($text);
     $this->assertEquals(Instant::from($actual), $expected);
 }
 public function zonedDateTimeFrom(TemporalAccessor $temporal)
 {
     try {
         $zone = ZoneId::from($temporal);
         try {
             $instant = Instant::from($temporal);
             return $this->zonedDateTime($instant, $zone);
         } catch (DateTimeException $ex1) {
             $cldt = ChronoLocalDateTimeImpl::ensureValid($this, $this->localDateTime($temporal));
             return ChronoZonedDateTimeImpl::ofBest($cldt, $zone, null);
         }
     } catch (DateTimeException $ex) {
         throw new DateTimeException("Unable to obtain ChronoZonedDateTime from TemporalAccessor: " . get_class($temporal), $ex);
     }
 }
 private static function adjust(TemporalAccessor $temporal, DateTimeFormatter $formatter)
 {
     // normal case first (early return is an optimization)
     $overrideChrono = $formatter->getChronology();
     $overrideZone = $formatter->getZone();
     if ($overrideChrono == null && $overrideZone == null) {
         return $temporal;
     }
     // ensure minimal change (early return is an optimization)
     $temporalChrono = $temporal->query(TemporalQueries::chronology());
     $temporalZone = $temporal->query(TemporalQueries::zoneId());
     if ($temporalChrono !== null && $temporalChrono->equals($overrideChrono)) {
         $overrideChrono = null;
     }
     if ($temporalZone !== null && $temporalZone->equals($overrideZone)) {
         $overrideZone = null;
     }
     if ($overrideChrono === null && $overrideZone === null) {
         return $temporal;
     }
     // make adjustment
     $effectiveChrono = $overrideChrono != null ? $overrideChrono : $temporalChrono;
     if ($overrideZone != null) {
         // if have zone and instant, calculation is simple, defaulting chrono if necessary
         if ($temporal->isSupported(ChronoField::INSTANT_SECONDS())) {
             $chrono = $effectiveChrono != null ? $effectiveChrono : IsoChronology::INSTANCE();
             return $chrono->zonedDateTime(Instant::from($temporal), $overrideZone);
         }
         // block changing zone on OffsetTime, and similar problem cases
         if ($overrideZone->normalized() instanceof ZoneOffset && $temporal->isSupported(ChronoField::OFFSET_SECONDS()) && $temporal->get(ChronoField::OFFSET_SECONDS()) != $overrideZone->getRules()->getOffset(Instant::EPOCH())->getTotalSeconds()) {
             throw new DateTimeException("Unable to apply override zone '" . $overrideZone . "' because the temporal object being formatted has a different offset but" . " does not represent an instant: " . $temporal);
         }
     }
     $effectiveZone = $overrideZone !== null ? $overrideZone : $temporalZone;
     $effectiveDate = null;
     if ($overrideChrono !== null) {
         if ($temporal->isSupported(ChronoField::EPOCH_DAY())) {
             $effectiveDate = $effectiveChrono->dateFrom($temporal);
         } else {
             // check for date fields other than epoch-day, ignoring case of converting null to ISO
             if (!($overrideChrono == IsoChronology::INSTANCE() && $temporalChrono === null)) {
                 foreach (ChronoField::values() as $f) {
                     if ($f->isDateBased() && $temporal->isSupported($f)) {
                         throw new DateTimeException("Unable to apply override chronology '" . $overrideChrono . "' because the temporal object being formatted contains date fields but" . " does not represent a whole date: " . $temporal);
                     }
                 }
             }
             $effectiveDate = null;
         }
     } else {
         $effectiveDate = null;
     }
     // combine available data
     // this is a non-standard temporal that is almost a pure delegate
     // this better handles map-like underlying temporal instances
     return new Test($effectiveDate, $temporal, $effectiveZone, $effectiveChrono);
 }
 public function test_parse_fromField_InstantSeconds_NanoOfSecond()
 {
     $fmt = (new DateTimeFormatterBuilder())->appendValue(ChronoField::INSTANT_SECONDS())->appendLiteral('.')->appendValue(ChronoField::NANO_OF_SECOND())->toFormatter();
     $acc = $fmt->parse("86402.123456789");
     $expected = Instant::ofEpochSecond(86402, 123456789);
     $this->assertEquals($acc->isSupported(ChronoField::INSTANT_SECONDS()), true);
     $this->assertEquals($acc->isSupported(ChronoField::NANO_OF_SECOND()), true);
     $this->assertEquals($acc->isSupported(ChronoField::MICRO_OF_SECOND()), true);
     $this->assertEquals($acc->isSupported(ChronoField::MILLI_OF_SECOND()), true);
     $this->assertEquals($acc->getLong(ChronoField::INSTANT_SECONDS()), 86402);
     $this->assertEquals($acc->getLong(ChronoField::NANO_OF_SECOND()), 123456789);
     $this->assertEquals($acc->getLong(ChronoField::MICRO_OF_SECOND()), 123456);
     $this->assertEquals($acc->getLong(ChronoField::MILLI_OF_SECOND()), 123);
     $this->assertEquals(Instant::from($acc), $expected);
 }