public function format(DateTimePrintContext $context, &$buf)
 {
     $offsetSecs = $context->getValueField(ChronoField::OFFSET_SECONDS());
     if ($offsetSecs === null) {
         return false;
     }
     $totalSecs = $offsetSecs;
     if ($totalSecs === 0) {
         $buf .= $this->noOffsetText;
     } else {
         $absHours = Math::abs($totalSecs / 3600 % 100);
         // anything larger than 99 silently dropped
         $absMinutes = Math::abs($totalSecs / 60 % 60);
         $absSeconds = Math::abs($totalSecs % 60);
         $bufPos = strlen($buf);
         $output = $absHours;
         $buf .= ($totalSecs < 0 ? "-" : "+") . Math::div($absHours, 10) . $absHours % 10;
         if ($this->type >= 3 || $this->type >= 1 && $absMinutes > 0) {
             $buf .= ($this->type % 2 === 0 ? ":" : "") . Math::div($absMinutes, 10) . $absMinutes % 10;
             $output += $absMinutes;
             if ($this->type >= 7 || $this->type >= 5 && $absSeconds > 0) {
                 $buf .= ($this->type % 2 === 0 ? ":" : "") . Math::div($absSeconds, 10) . $absSeconds % 10;
                 $output += $absSeconds;
             }
         }
         if ($output === 0) {
             $buf = substr($buf, 0, $bufPos);
             $buf .= $this->noOffsetText;
         }
     }
     return true;
 }
Example #2
0
 public function getFrom(TemporalAccessor $temporal)
 {
     if ($this->isSupportedBy($temporal) == false) {
         throw new UnsupportedTemporalTypeException("Unsupported field: QuarterOfYear");
     }
     $moy = $temporal->getLong(ChronoField::MONTH_OF_YEAR());
     return Math::div($moy + 2, 3);
 }
Example #3
0
 public function getFrom(TemporalAccessor $temporal)
 {
     if ($this->isSupportedBy($temporal) == false) {
         throw new UnsupportedTemporalTypeException("Unsupported field: DayOfQuarter");
     }
     $doy = $temporal->get(ChronoField::DAY_OF_YEAR());
     $moy = $temporal->get(ChronoField::MONTH_OF_YEAR());
     $year = $temporal->getLong(ChronoField::YEAR());
     $quarterDays = [0, 90, 181, 273, 0, 91, 182, 274];
     return $doy - $quarterDays[Math::div($moy - 1, 3) + (IsoChronology::INSTANCE()->isLeapYear($year) ? 4 : 0)];
 }
 public function resolve(FieldValues $fieldValues, TemporalAccessor $partialTemporal, ResolverStyle $resolverStyle)
 {
     $wbyLong = $fieldValues->get(IsoFields::WEEK_BASED_YEAR());
     $dowLong = $fieldValues->get(ChronoField::DAY_OF_WEEK());
     if ($wbyLong === null || $dowLong === null) {
         return null;
     }
     $wby = IsoFields::WEEK_BASED_YEAR()->range()->checkValidIntValue($wbyLong, IsoFields::WEEK_BASED_YEAR());
     // always validate
     $wowby = $fieldValues->get(IsoFields::WEEK_OF_WEEK_BASED_YEAR());
     IsoFields::ensureIso($partialTemporal);
     $date = LocalDate::of($wby, 1, 4);
     if ($resolverStyle == ResolverStyle::LENIENT()) {
         $dow = $dowLong;
         // unvalidated
         if ($dow > 7) {
             $date = $date->plusWeeks(Math::div($dow - 1, 7));
             $dow = ($dow - 1) % 7 + 1;
         } else {
             if ($dow < 1) {
                 $date = $date->plusWeeks(Math::div(Math::subtractExact($dow, 7), 7));
                 $dow = ($dow + 6) % 7 + 1;
             }
         }
         $date = $date->plusWeeks(Math::subtractExact($wowby, 1))->with(ChronoField::DAY_OF_WEEK(), $dow);
     } else {
         $dow = ChronoField::DAY_OF_WEEK()->checkValidIntValue($dowLong);
         // validated
         if ($wowby < 1 || $wowby > 52) {
             if ($resolverStyle == ResolverStyle::STRICT()) {
                 IsoFields::getWeekRange($date)->checkValidValue($wowby, $this);
                 // only allow exact range
             } else {
                 // SMART
                 $this->range()->checkValidValue($wowby, $this);
                 // allow 1-53 rolling into next year
             }
         }
         $date = $date->plusWeeks($wowby - 1)->with(ChronoField::DAY_OF_WEEK(), $dow);
     }
     $fieldValues->remove($this);
     $fieldValues->remove(IsoFields::WEEK_BASED_YEAR());
     $fieldValues->remove(ChronoField::DAY_OF_WEEK());
     return $date;
 }
 public function format(DateTimePrintContext $context, &$buf)
 {
     $offsetSecs = $context->getValueField(ChronoField::OFFSET_SECONDS());
     if ($offsetSecs === null) {
         return false;
     }
     $gmtText = "GMT";
     // TODO: get localized version of 'GMT'
     if ($gmtText !== null) {
         $buf .= $gmtText;
     }
     $totalSecs = Math::toIntExact($offsetSecs);
     if ($totalSecs !== 0) {
         $absHours = Math::abs($totalSecs / 3600 % 100);
         // anything larger than 99 silently dropped
         $absMinutes = Math::abs($totalSecs / 60 % 60);
         $absSeconds = Math::abs($totalSecs % 60);
         $buf .= $totalSecs < 0 ? "-" : "+";
         if ($this->style == TextStyle::FULL()) {
             $this->appendHMS($buf, $absHours);
             $buf .= ':';
             $this->appendHMS($buf, $absMinutes);
             if ($absSeconds != 0) {
                 $buf .= ':';
                 $this->appendHMS($buf, $absSeconds);
             }
         } else {
             if ($absHours >= 10) {
                 $buf .= Math::div($absHours, 10);
             }
             $buf .= $absHours % 10;
             if ($absMinutes != 0 || $absSeconds != 0) {
                 $buf .= ':';
                 $this->appendHMS($buf, $absMinutes);
                 if ($absSeconds != 0) {
                     $buf .= ':';
                     self::appendHMS($buf, $absSeconds);
                 }
             }
         }
     }
     return true;
 }
Example #6
0
 /**
  * A string representation of this duration using ISO-8601 seconds
  * based representation, such as {@code PT8H6M12.345S}.
  * <p>
  * The format of the returned string will be {@code PTnHnMnS}, where n is
  * the relevant hours, minutes or seconds part of the duration.
  * Any fractional seconds are placed after a decimal point i the seconds section.
  * If a section has a zero value, it is omitted.
  * The hours, minutes and seconds will all have the same sign.
  * <p>
  * Examples:
  * <pre>
  *    "20.345 seconds"                 -- "PT20.345S
  *    "15 minutes" (15 * 60 seconds)   -- "PT15M"
  *    "10 hours" (10 * 3600 seconds)   -- "PT10H"
  *    "2 days" (2 * 86400 seconds)     -- "PT48H"
  * </pre>
  * Note that multiples of 24 hours are not output as days to avoid confusion
  * with {@code Period}.
  *
  * @return string an ISO-8601 representation of this duration, not null
  */
 public function __toString()
 {
     if ($this === self::$ZERO) {
         return "PT0S";
     }
     $hours = Math::div($this->seconds, LocalTime::SECONDS_PER_HOUR);
     $minutes = Math::div($this->seconds % LocalTime::SECONDS_PER_HOUR, LocalTime::SECONDS_PER_MINUTE);
     $secs = $this->seconds % LocalTime::SECONDS_PER_MINUTE;
     $buf = "PT";
     if ($hours !== 0) {
         $buf .= $hours . 'H';
     }
     if ($minutes !== 0) {
         $buf .= $minutes . 'M';
     }
     if ($secs === 0 && $this->nanos === 0 && strlen($buf) > 2) {
         return $buf;
     }
     if ($secs < 0 && $this->nanos > 0) {
         if ($secs === -1) {
             $buf .= "-0";
         } else {
             $buf .= $secs + 1;
         }
     } else {
         $buf .= $secs;
     }
     if ($this->nanos > 0) {
         $pos = strlen($buf);
         if ($secs < 0) {
             $buf .= 2 * LocalTime::NANOS_PER_SECOND - $this->nanos;
         } else {
             $buf .= $this->nanos + LocalTime::NANOS_PER_SECOND;
         }
         $buf = rtrim($buf, "0");
         $buf[$pos] = '.';
     }
     $buf .= 'S';
     return $buf;
 }
Example #7
0
 /**
  * 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);
 }
 function provider_toString()
 {
     return [[0, 0, "PT0S"], [0, 1, "PT0.000000001S"], [0, 10, "PT0.00000001S"], [0, 100, "PT0.0000001S"], [0, 1000, "PT0.000001S"], [0, 10000, "PT0.00001S"], [0, 100000, "PT0.0001S"], [0, 1000000, "PT0.001S"], [0, 10000000, "PT0.01S"], [0, 100000000, "PT0.1S"], [0, 120000000, "PT0.12S"], [0, 123000000, "PT0.123S"], [0, 123400000, "PT0.1234S"], [0, 123450000, "PT0.12345S"], [0, 123456000, "PT0.123456S"], [0, 123456700, "PT0.1234567S"], [0, 123456780, "PT0.12345678S"], [0, 123456789, "PT0.123456789S"], [1, 0, "PT1S"], [59, 0, "PT59S"], [60, 0, "PT1M"], [61, 0, "PT1M1S"], [3599, 0, "PT59M59S"], [3600, 0, "PT1H"], [3601, 0, "PT1H1S"], [3661, 0, "PT1H1M1S"], [86399, 0, "PT23H59M59S"], [86400, 0, "PT24H"], [59, 0, "PT59S"], [59, 0, "PT59S"], [-1, 0, "PT-1S"], [-1, 1000, "PT-0.999999S"], [-1, 900000000, "PT-0.1S"], [Long::MAX_VALUE, 0, "PT" . Math::div(Long::MAX_VALUE, 3600) . "H" . Math::div(Long::MAX_VALUE % 3600, 60) . "M" . Long::MAX_VALUE % 60 . "S"], [Long::MIN_VALUE, 0, "PT" . Math::div(Long::MIN_VALUE, 3600) . "H" . Math::div(Long::MIN_VALUE % 3600, 60) . "M" . Long::MIN_VALUE % 60 . "S"]];
 }
 /**
  * @group long
  */
 public function test_tick_ClockDuration_20nanos()
 {
     for ($i = 0; $i < 1000; $i++) {
         $test = Clock::tick(Clock::fixed(self::ZDT()->withNano($i)->toInstant(), self::PARIS()), Duration::ofNanos(20));
         $this->assertEquals($test->instant(), self::ZDT()->withNano(Math::div($i, 20) * 20)->toInstant());
         $this->assertEquals($test->getZone(), self::PARIS());
     }
 }
 public function parse(DateTimeParseContext $context, $text, $position)
 {
     // TODO cache formatter
     // new context to avoid overwriting fields like year/month/day
     $minDigits = $this->fractionalDigits < 0 ? 0 : $this->fractionalDigits;
     $maxDigits = $this->fractionalDigits < 0 ? 9 : $this->fractionalDigits;
     $parser = (new DateTimeFormatterBuilder())->append(DateTimeFormatter::ISO_LOCAL_DATE())->appendLiteral('T')->appendValue2(ChronoField::HOUR_OF_DAY(), 2)->appendLiteral(':')->appendValue2(ChronoField::MINUTE_OF_HOUR(), 2)->appendLiteral(':')->appendValue2(ChronoField::SECOND_OF_MINUTE(), 2)->appendFraction(ChronoField::NANO_OF_SECOND(), $minDigits, $maxDigits, true)->appendLiteral('Z')->toFormatter()->toPrinterParser(false);
     $newContext = $context->copy();
     $pos = $parser->parse($newContext, $text, $position);
     if ($pos < 0) {
         return $pos;
     }
     // parser restricts most fields to 2 digits, so definitely int
     // correctly parsed nano is also guaranteed to be valid
     $yearParsed = $newContext->getParsed(ChronoField::YEAR());
     $month = $newContext->getParsed(ChronoField::MONTH_OF_YEAR());
     $day = $newContext->getParsed(ChronoField::DAY_OF_MONTH());
     $hour = $newContext->getParsed(ChronoField::HOUR_OF_DAY());
     $min = $newContext->getParsed(ChronoField::MINUTE_OF_HOUR());
     $secVal = $newContext->getParsed(ChronoField::SECOND_OF_MINUTE());
     $nanoVal = $newContext->getParsed(ChronoField::NANO_OF_SECOND());
     $sec = $secVal !== null ? $secVal : 0;
     $nano = $nanoVal !== null ? $nanoVal : 0;
     $days = 0;
     if ($hour === 24 && $min === 0 && $sec === 0 && $nano === 0) {
         $hour = 0;
         $days = 1;
     } else {
         if ($hour === 23 && $min === 59 && $sec === 60) {
             $context->setParsedLeapSecond();
             $sec = 59;
         }
     }
     $year = $yearParsed % 10000;
     try {
         $ldt = LocalDateTime::of($year, $month, $day, $hour, $min, $sec, 0)->plusDays($days);
         $instantSecs = $ldt->toEpochSecond(ZoneOffset::UTC());
         $instantSecs += Math::multiplyExact(Math::div($yearParsed, 10000), self::SECONDS_PER_10000_YEARS);
     } catch (RuntimeException $ex) {
         // TODO What do we actually catch here and why
         return ~$position;
     }
     $successPos = $pos;
     $successPos = $context->setParsedField(ChronoField::INSTANT_SECONDS(), $instantSecs, $position, $successPos);
     return $context->setParsedField(ChronoField::NANO_OF_SECOND(), $nano, $position, $successPos);
 }
Example #11
0
 /**
  * Converts this instant to the number of milliseconds from the epoch
  * of 1970-01-01T00:00:00Z.
  * <p>
  * If this instant represents a point on the time-line too far in the future
  * or past to fit in a {@code long} milliseconds, then an exception is thrown.
  * <p>
  * If this instant has greater than millisecond precision, then the conversion
  * will drop any excess precision information as though the amount in nanoseconds
  * was subject to integer division by one million.
  *
  * @return int the number of milliseconds since the epoch of 1970-01-01T00:00:00Z
  * @throws ArithmeticException if numeric overflow occurs
  */
 public function toEpochMilli()
 {
     $millis = Math::multiplyExact($this->seconds, 1000);
     return $millis + Math::div($this->nanos, 1000000);
 }
Example #12
0
 public function toEpochDay()
 {
     $y = $this->year;
     $m = $this->month;
     $total = 0;
     $total += 365 * $y;
     if ($y >= 0) {
         $total += Math::div($y + 3, 4) - Math::div($y + 99, 100) + Math::div($y + 399, 400);
     } else {
         $total -= Math::div($y, -4) - Math::div($y, -100) + Math::div($y, -400);
     }
     $total += Math::div(367 * $m - 362, 12);
     $total += $this->day - 1;
     if ($m > 2) {
         $total--;
         if ($this->isLeapYear() == false) {
             $total--;
         }
     }
     return $total - self::DAYS_0000_TO_1970;
 }
Example #13
0
 private function resolveFractional()
 {
     // ensure fractional seconds available as CF requires
     // resolveTimeLenient() will have merged CF::MICRO_OF_SECOND()/MILLI_OF_SECOND to NANO_OF_SECOND
     if ($this->time == null && ($this->fieldValues->has(CF::INSTANT_SECONDS()) || $this->fieldValues->has(CF::SECOND_OF_DAY()) || $this->fieldValues->has(CF::SECOND_OF_MINUTE()))) {
         if ($this->fieldValues->has(CF::NANO_OF_SECOND())) {
             $nos = $this->fieldValues->get(CF::NANO_OF_SECOND());
             $this->fieldValues->put(CF::MICRO_OF_SECOND(), Math::div($nos, 1000));
             $this->fieldValues->put(CF::MILLI_OF_SECOND(), Math::div($nos, 1000000));
         } else {
             $this->fieldValues->put(CF::NANO_OF_SECOND(), 0);
             $this->fieldValues->put(CF::MICRO_OF_SECOND(), 0);
             $this->fieldValues->put(CF::MILLI_OF_SECOND(), 0);
         }
     }
 }
Example #14
0
 private static function buildId($totalSeconds)
 {
     if ($totalSeconds === 0) {
         return "Z";
     } else {
         $absTotalSeconds = Math::abs($totalSeconds);
         $buf = '';
         $absHours = Math::div($absTotalSeconds, LocalTime::SECONDS_PER_HOUR);
         $absMinutes = Math::div($absTotalSeconds, LocalTime::SECONDS_PER_MINUTE) % LocalTime::MINUTES_PER_HOUR;
         $buf .= ($totalSeconds < 0 ? "-" : "+") . ($absHours < 10 ? "0" : "") . $absHours . ($absMinutes < 10 ? ":0" : ":") . $absMinutes;
         $absSeconds = $absTotalSeconds % LocalTime::SECONDS_PER_MINUTE;
         if ($absSeconds !== 0) {
             $buf .= ($absSeconds < 10 ? ":0" : ":") . $absSeconds;
         }
         return $buf;
     }
 }
Example #15
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);
 }
Example #16
0
 /**
  * @expectedException \Celest\ArithmeticException
  */
 public function test_multipliedBy_overflowTooSmall()
 {
     $test = Period::ofYears(Math::div(Long::MIN_VALUE, 2) - 1);
     $test->multipliedBy(2);
 }
 function minusNanos_fromZero()
 {
     $delta = 7500000000;
     $hour = 22;
     $min = 59;
     $sec = 0;
     $nanos = 0;
     $ret = [];
     for ($i = 3660 * 1000000000; $i >= -3660 * 1000000000;) {
         $ret[] = [$i, $hour, $min, $sec, $nanos];
         $i -= $delta;
         $nanos += $delta;
         if ($nanos >= 1000000000) {
             $sec += Math::div($nanos, 1000000000);
             $nanos %= 1000000000;
             if ($sec >= 60) {
                 $min++;
                 $sec %= 60;
                 if ($min == 60) {
                     $hour++;
                     $min = 0;
                     if ($hour == 24) {
                         $hour = 0;
                     }
                 }
             }
         }
     }
     return $ret;
 }
Example #18
0
 /**
  * @param int $dividend
  * @param int $divisor
  * @return int
  */
 public static function floorDiv($dividend, $divisor)
 {
     if (\function_exists('\\intdiv')) {
         $r = \intdiv($dividend, $divisor);
     } else {
         $r = Math::div($dividend, $divisor);
     }
     if (($dividend ^ $divisor) < 0 && $r * $divisor !== $dividend) {
         $r--;
     }
     return $r;
 }
 /**
  * Returns the week number computed from the reference day and reference dayOfWeek.
  *
  * @param int $offset the offset to align a date with the start of week
  *     from {@link #startOfWeekOffset}.
  * @param int $day the day for which to compute the week number
  * @return int the week number where zero is used for a partial week and 1 for the first full week
  */
 private function computeWeek($offset, $day)
 {
     return Math::div(7 + $offset + ($day - 1), 7);
 }
 public function test_minusMonths_long_big()
 {
     $test = YearMonth::of(40, 6);
     $months = 20 + Integer::MAX_VALUE;
     $this->assertEquals($test->minusMonths($months), YearMonth::of(40 - Math::div($months, 12), 6 - $months % 12));
 }
Example #21
0
 /**
  * @expectedException \Celest\ArithmeticException
  */
 public function test_toEpochMilli_tooSmall()
 {
     Instant::ofEpochSecond(Math::div(Long::MIN_VALUE, 1000) - 1)->toEpochMilli();
 }
 function minusNanos_fromZero()
 {
     $delta = 7500000000;
     $date = self::TEST_200707_15_12_30_40_987654321()->toLocalDate()->minusDays(1);
     $hour = 22;
     $min = 59;
     $sec = 0;
     $nanos = 0;
     $ret = [];
     for ($i = 3660 * 1000000000; $i >= -3660 * 1000000000;) {
         $ret[] = [$i, $date, $hour, $min, $sec, $nanos];
         $nanos += $delta;
         $i -= $delta;
         if ($nanos >= 1000000000) {
             $sec += Math::div($nanos, 1000000000);
             $nanos %= 1000000000;
             if ($sec >= 60) {
                 $min++;
                 $sec %= 60;
                 if ($min == 60) {
                     $hour++;
                     $min = 0;
                     if ($hour == 24) {
                         $hour = 0;
                         $date = $date->plusDays(1);
                     }
                 }
             }
         }
     }
     return $ret;
 }
Example #23
0
 /**
  * @internal
  * @param LocalDate $date
  * @return bool|int
  */
 public static function getWeek(LocalDate $date)
 {
     $dow0 = $date->getDayOfWeek()->getValue() - 1;
     $doy0 = $date->getDayOfYear() - 1;
     $doyThu0 = $doy0 + (3 - $dow0);
     // adjust to mid-week Thursday (which is 3 indexed from zero)
     $alignedWeek = Math::div($doyThu0, 7);
     $firstThuDoy0 = $doyThu0 - $alignedWeek * 7;
     $firstMonDoy0 = $firstThuDoy0 - 3;
     if ($firstMonDoy0 < -3) {
         $firstMonDoy0 += 7;
     }
     if ($doy0 < $firstMonDoy0) {
         return self::getWeekRange($date->withDayOfYear(180)->minusYears(1))->getMaximum();
     }
     $week = Math::div($doy0 - $firstMonDoy0, 7) + 1;
     if ($week == 53) {
         if (($firstMonDoy0 == -3 || $firstMonDoy0 == -2 && $date->isLeapYear()) == false) {
             $week = 1;
         }
     }
     return $week;
 }
 public function test_factory_ofInstant_maxWithMaxOffset()
 {
     $days_0000_to_1970 = 146097 * 5 - (30 * 365 + 7);
     $year = Year::MAX_VALUE;
     $days = $year * 365 + (Math::div($year, 4) - Math::div($year, 100) + Math::div($year, 400)) + 365 - $days_0000_to_1970;
     $instant = Instant::ofEpochSecond(($days + 1) * 24 * 60 * 60 - 1 - self::OFFSET_MAX()->getTotalSeconds());
     $test = ZonedDateTime::ofInstant($instant, self::OFFSET_MAX());
     $this->assertEquals($test->getYear(), Year::MAX_VALUE);
     $this->assertEquals($test->getMonth()->getValue(), 12);
     $this->assertEquals($test->getDayOfMonth(), 31);
     $this->assertEquals($test->getOffset(), self::OFFSET_MAX());
     $this->assertEquals($test->getHour(), 23);
     $this->assertEquals($test->getMinute(), 59);
     $this->assertEquals($test->getSecond(), 59);
     $this->assertEquals($test->getNano(), 0);
 }
 public function test_plusMonths_long_big()
 {
     $months = 20 + Integer::MAX_VALUE;
     $test = LocalDate::of(-40, 6, 1)->plusMonths($months);
     $this->assertEquals($test, LocalDate::of(-40 + Math::div($months, 12), 6 + $months % 12, 1));
 }
Example #26
0
 /**
  * Outputs this time as a {@code String}, such as {@code 10:15}.
  * <p>
  * The output will be one of the following ISO-8601 formats:
  * <ul>
  * <li>{@code HH:mm}</li>
  * <li>{@code HH:mm:ss}</li>
  * <li>{@code HH:mm:ss.SSS}</li>
  * <li>{@code HH:mm:ss.SSSSSS}</li>
  * <li>{@code HH:mm:ss.SSSSSSSSS}</li>
  * </ul>
  * The format used will be the shortest that outputs the full value of
  * the time where the omitted parts are implied to be zero.
  *
  * @return string a string representation of this time, not null
  */
 public function __toString()
 {
     $buf = "";
     $hourValue = $this->hour;
     $minuteValue = $this->minute;
     $secondValue = $this->second;
     $nanoValue = $this->nano;
     $buf .= ($hourValue < 10 ? "0" : "") . $hourValue . ($minuteValue < 10 ? ":0" : ":") . $minuteValue;
     if ($secondValue > 0 || $nanoValue > 0) {
         $buf .= ($secondValue < 10 ? ":0" : ":") . $secondValue;
         if ($nanoValue > 0) {
             $buf .= '.';
             if ($nanoValue % 1000000 == 0) {
                 $buf .= substr(Math::div($nanoValue, 1000000) + 1000, 1);
             } else {
                 if ($nanoValue % 1000 == 0) {
                     $buf .= substr(Math::div($nanoValue, 1000) + 1000000, 1);
                 } else {
                     $buf .= substr($nanoValue + 1000000000, 1);
                 }
             }
         }
     }
     return $buf;
 }
Example #27
0
 public function between(Temporal $temporal1Inclusive, Temporal $temporal2Exclusive)
 {
     if (get_class($temporal1Inclusive) !== get_class($temporal2Exclusive)) {
         return $temporal1Inclusive->until($temporal2Exclusive, $this);
     }
     switch ($this) {
         case self::WEEK_BASED_YEARS():
             return Math::subtractExact($temporal2Exclusive->getLong(IsoFields::WEEK_BASED_YEAR()), $temporal1Inclusive->getLong(IsoFields::WEEK_BASED_YEAR()));
         case self::QUARTER_YEARS():
             return Math::div($temporal1Inclusive->until($temporal2Exclusive, ChronoUnit::MONTHS()), 3);
         default:
             throw new IllegalStateException("Unreachable");
     }
 }
Example #28
0
 /**
  * Returns a copy of this period with the years and months normalized.
  * <p>
  * This normalizes the years and months units, leaving the days unit unchanged.
  * The months unit is adjusted to have an absolute value less than 11,
  * with the years unit being adjusted to compensate. For example, a period of
  * "1 Year and 15 months" will be normalized to "2 years and 3 months".
  * <p>
  * The sign of the years and months units will be the same after normalization.
  * For example, a period of "1 year and -25 months" will be normalized to
  * "-1 year and -1 month".
  * <p>
  * This instance is immutable and unaffected by this method call.
  *
  * @return Period a {@code Period} based on this period with excess months normalized to years, not null
  * @throws ArithmeticException if numeric overflow occurs
  */
 public function normalized()
 {
     $totalMonths = $this->toTotalMonths();
     $splitYears = Math::div($totalMonths, 12);
     $splitMonths = $totalMonths % 12;
     // no overflow
     if ($splitYears === $this->years && $splitMonths === $this->months) {
         return $this;
     }
     return $this->create(Math::toIntExact($splitYears), $splitMonths, $this->days);
 }
 private function plusWithOverflow(ChronoLocalDate $newDate, $hours, $minutes, $seconds, $nanos)
 {
     // 9223372036854775808 long, 2147483648 int
     if (($hours | $minutes | $seconds | $nanos) === 0) {
         return $this->_with($newDate, $this->time);
     }
     $totDays = Math::div($nanos, self::NANOS_PER_DAY) + Math::div($seconds, self::SECONDS_PER_DAY) + Math::div($minutes, self::MINUTES_PER_DAY) + Math::div($hours, self::HOURS_PER_DAY);
     //   max/24
     $totNanos = ${$nanos} % self::NANOS_PER_DAY + $seconds % self::SECONDS_PER_DAY * self::NANOS_PER_SECOND + $minutes % self::MINUTES_PER_DAY * self::NANOS_PER_MINUTE + $hours % self::HOURS_PER_DAY * self::NANOS_PER_HOUR;
     //   max  86400000000000
     $curNoD = $this->time->toNanoOfDay();
     //   max  86400000000000
     $totNanos = $totNanos + $curNoD;
     // total 432000000000000
     $totDays += Math::floorDiv($totNanos, self::NANOS_PER_DAY);
     $newNoD = Math::floorMod($totNanos, self::NANOS_PER_DAY);
     $newTime = $newNoD === $curNoD ? $this->time : LocalTime::ofNanoOfDay($newNoD);
     return $this->_with($newDate->plus($totDays, ChronoUnit::DAYS()), $newTime);
 }