Exemple #1
0
 /**
  * Returns a copy of this {@code LocalDate} with the specified number of months added.
  * <p>
  * This method adds the specified amount to the months field in three steps:
  * <ol>
  * <li>Add the input months to the month-of-year field</li>
  * <li>Check if the resulting date would be invalid</li>
  * <li>Adjust the day-of-month to the last valid day if necessary</li>
  * </ol>
  * <p>
  * For example, 2007-03-31 plus one month would result in the invalid date
  * 2007-04-31. Instead of returning an invalid result, the last valid day
  * of the month, 2007-04-30, is selected instead.
  * <p>
  * This instance is immutable and unaffected by this method call.
  *
  * @param int $monthsToAdd the months to add, may be negative
  * @return LocalDate a {@code LocalDate} based on this date with the months added, not null
  * @throws DateTimeException if the result exceeds the supported date range
  */
 public function plusMonths($monthsToAdd)
 {
     if ($monthsToAdd === 0) {
         return $this;
     }
     $monthCount = $this->year * 12 + ($this->month - 1);
     $calcMonths = $monthCount + $monthsToAdd;
     // safe overflow
     if (!is_int($calcMonths)) {
         throw new DateTimeException('Overflow');
         // Todo better message
     }
     $newYear = ChronoField::YEAR()->checkValidIntValue(Math::floorDiv($calcMonths, 12));
     $newMonth = Math::floorMod($calcMonths, 12) + 1;
     return self::resolvePreviousValid($newYear, $newMonth, $this->day);
 }
 protected function resolveProlepticMonth(FieldValues $fieldValues, ResolverStyle $resolverStyle)
 {
     $pMonth = $fieldValues->remove(CF::PROLEPTIC_MONTH());
     if ($pMonth !== null) {
         if ($resolverStyle != ResolverStyle::LENIENT()) {
             CF::PROLEPTIC_MONTH()->checkValidValue($pMonth);
         }
         $this->addFieldValue($fieldValues, CF::MONTH_OF_YEAR(), Math::floorMod($pMonth, 12) + 1);
         $this->addFieldValue($fieldValues, CF::YEAR(), Math::floorDiv($pMonth, 12));
     }
 }
Exemple #3
0
 /**
  * Obtains an instance of {@code Instant} using milliseconds from the
  * epoch of 1970-01-01T00:00:00Z.
  * <p>
  * The seconds and nanoseconds are extracted from the specified milliseconds.
  *
  * @param int $epochMilli the number of milliseconds from 1970-01-01T00:00:00Z
  * @return Instant an instant, not null
  * @throws DateTimeException if the instant exceeds the maximum or minimum instant
  */
 public static function ofEpochMilli($epochMilli)
 {
     $secs = Math::floorDiv($epochMilli, 1000);
     $mos = (int) Math::floorMod($epochMilli, 1000);
     return self::create($secs, $mos * 1000000);
 }
 public function millis()
 {
     $tofd = \gettimeofday();
     return $tofd['sec'] * 1000 + Math::floorDiv($tofd['usec'], 1000);
 }
Exemple #5
0
 /**
  * Obtains a {@code Duration} representing a number of seconds and an
  * adjustment in nanoseconds.
  * <p>
  * This method allows an arbitrary number of nanoseconds to be passed in.
  * The factory will alter the values of the second and nanosecond in order
  * to ensure that the stored nanosecond is in the range 0 to 999,999,999.
  * For example, the following will result in the exactly the same duration:
  * <pre>
  *  Duration.ofSeconds(3, 1);
  *  Duration.ofSeconds(4, -999_999_999);
  *  Duration.ofSeconds(2, 1000_000_001);
  * </pre>
  *
  * @param int $seconds the number of seconds, positive or negative
  * @param int $nanoAdjustment the nanosecond adjustment to the number of seconds, positive or negative
  * @return Duration a {@code Duration}, not null
  * @throws ArithmeticException if the adjustment causes the seconds to exceed the capacity of {@code Duration}
  */
 public static function ofSeconds($seconds, $nanoAdjustment = 0)
 {
     $secs = Math::addExact($seconds, Math::floorDiv($nanoAdjustment, LocalTime::NANOS_PER_SECOND));
     $nos = Math::floorMod($nanoAdjustment, LocalTime::NANOS_PER_SECOND);
     return self::create($secs, $nos);
 }
Exemple #6
0
 private function findYear($epochSecond, ZoneOffset $offset)
 {
     // inline for performance
     $localSecond = $epochSecond + $offset->getTotalSeconds();
     $localEpochDay = Math::floorDiv($localSecond, 86400);
     return LocalDate::ofEpochDay($localEpochDay)->getYear();
 }
Exemple #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());
         }
     }
 }
 /**
  * Returns a copy of this {@code LocalDateTime} with the specified period added.
  * <p>
  * This instance is immutable and unaffected by this method call.
  *
  * @param LocalDate $newDate the new date to base the calculation on, not null
  * @param int $hours the hours to add, may be negative
  * @param int $minutes the minutes to add, may be negative
  * @param int $seconds the seconds to add, may be negative
  * @param int $nanos the nanos to add, may be negative
  * @param int $sign the sign to determine add or subtract
  * @return LocalDateTime the combined result, not null
  */
 private function plusWithOverflow(LocalDate $newDate, $hours, $minutes, $seconds, $nanos, $sign)
 {
     // 9223372036854775808 long, 2147483648 int
     if (($hours | $minutes | $seconds | $nanos) == 0) {
         return $this->_with($newDate, $this->time);
     }
     $totDays = Math::div($nanos, LocalTime::NANOS_PER_DAY) + Math::div($seconds, LocalTime::SECONDS_PER_DAY) + Math::div($minutes, LocalTime::MINUTES_PER_DAY) + Math::div($hours, LocalTime::HOURS_PER_DAY);
     //   max/24
     $totDays *= $sign;
     // total max*0.4237...
     $totNanos = $nanos % LocalTime::NANOS_PER_DAY + $seconds % LocalTime::SECONDS_PER_DAY * LocalTime::NANOS_PER_SECOND + $minutes % LocalTime::MINUTES_PER_DAY * LocalTime::NANOS_PER_MINUTE + $hours % LocalTime::HOURS_PER_DAY * LocalTime::NANOS_PER_HOUR;
     //   max  86400000000000
     $curNoD = $this->time->toNanoOfDay();
     //   max  86400000000000
     $totNanos = $totNanos * $sign + $curNoD;
     // total 432000000000000
     $totDays += Math::floorDiv($totNanos, LocalTime::NANOS_PER_DAY);
     $newNoD = Math::floorMod($totNanos, LocalTime::NANOS_PER_DAY);
     $newTime = $newNoD === $curNoD ? $this->time : LocalTime::ofNanoOfDay($newNoD);
     return $this->_with($newDate->plusDays($totDays), $newTime);
 }
Exemple #9
0
 /**
  * @param int $dividend
  * @param int $divisor
  * @return int
  */
 public static function floorMod($dividend, $divisor)
 {
     return $dividend - Math::floorDiv($dividend, $divisor) * $divisor;
 }
 public function format(DateTimePrintContext $context, &$buf)
 {
     // use INSTANT_SECONDS, thus this code is not bound by Instant.MAX
     $inSecs = $context->getValueField(ChronoField::INSTANT_SECONDS());
     $inNanos = null;
     if ($context->getTemporal()->isSupported(ChronoField::NANO_OF_SECOND())) {
         $inNanos = $context->getTemporal()->getLong(ChronoField::NANO_OF_SECOND());
     }
     if ($inSecs === null) {
         return false;
     }
     $inSec = $inSecs;
     $inNano = ChronoField::NANO_OF_SECOND()->checkValidIntValue($inNanos !== null ? $inNanos : 0);
     // format mostly using LocalDateTime.toString
     if ($inSec >= -self::SECONDS_0000_TO_1970) {
         // current era
         $zeroSecs = $inSec - self::SECONDS_PER_10000_YEARS + self::SECONDS_0000_TO_1970;
         $hi = Math::floorDiv($zeroSecs, self::SECONDS_PER_10000_YEARS) + 1;
         $lo = Math::floorMod($zeroSecs, self::SECONDS_PER_10000_YEARS);
         $ldt = LocalDateTime::ofEpochSecond($lo - self::SECONDS_0000_TO_1970, 0, ZoneOffset::UTC());
         if ($hi > 0) {
             $buf .= '+' . $hi;
         }
         $buf .= $ldt;
         if ($ldt->getSecond() === 0) {
             $buf .= ":00";
         }
     } else {
         // before current era
         $zeroSecs = $inSec + self::SECONDS_0000_TO_1970;
         $hi = Math::div($zeroSecs, self::SECONDS_PER_10000_YEARS);
         $lo = $zeroSecs % self::SECONDS_PER_10000_YEARS;
         $ldt = LocalDateTime::ofEpochSecond($lo - self::SECONDS_0000_TO_1970, 0, ZoneOffset::UTC());
         $pos = strlen($buf);
         $buf .= $ldt;
         if ($ldt->getSecond() === 0) {
             $buf .= ":00";
         }
         if ($hi < 0) {
             if ($ldt->getYear() === -10000) {
                 $buf = substr_replace($buf, $hi - 1, $pos, 2);
             } else {
                 if ($lo === 0) {
                     $buf = substr_replace($buf, $hi, $pos, 0);
                 } else {
                     $buf = substr_replace($buf, Math::abs($hi), $pos + 1, 0);
                 }
             }
         }
     }
     // add fraction
     if ($this->fractionalDigits < 0 && $inNano > 0 || $this->fractionalDigits > 0) {
         $buf .= '.';
         $div = 100000000;
         for ($i = 0; $this->fractionalDigits === -1 && $inNano > 0 || $this->fractionalDigits === -2 && ($inNano > 0 || $i % 3 !== 0) || $i < $this->fractionalDigits; $i++) {
             $digit = Math::div($inNano, $div);
             $buf .= $digit;
             $inNano = $inNano - $digit * $div;
             $div = Math::div($div, 10);
         }
     }
     $buf .= 'Z';
     return true;
 }