/** * @dataProvider provider_pad */ public function test_pad_ALWAYS($minPad, $maxPad, $value, $result) { try { $this->getFormatterWidth(ChronoField::DAY_OF_MONTH(), $minPad, $maxPad, SignStyle::ALWAYS())->formatTo(new MockFieldValue(ChronoField::DAY_OF_MONTH(), $value), $buf); if ($result === null) { $this->fail("Expected exception"); } $this->assertEquals($buf, $value < 0 ? "-" . $result : "+" . $result); } catch (DateTimeException $ex) { if ($result !== null) { throw $ex; } $this->assertEquals(strpos($ex->getMessage(), ChronoField::DAY_OF_MONTH()->__toString()) !== false, true); } }
public function data_signStyle() { return [[LocalDate::of(0, 10, 2), SignStyle::ALWAYS(), null, "+00"], [LocalDate::of(2001, 10, 2), SignStyle::ALWAYS(), null, "+2001"], [LocalDate::of(-2001, 10, 2), SignStyle::ALWAYS(), null, "-2001"], [LocalDate::of(2001, 10, 2), SignStyle::NORMAL(), null, "2001"], [LocalDate::of(-2001, 10, 2), SignStyle::NORMAL(), null, "-2001"], [LocalDate::of(2001, 10, 2), SignStyle::NEVER(), null, "2001"], [LocalDate::of(-2001, 10, 2), SignStyle::NEVER(), null, "2001"], [LocalDate::of(2001, 10, 2), SignStyle::NOT_NEGATIVE(), null, "2001"], [LocalDate::of(-2001, 10, 2), SignStyle::NOT_NEGATIVE(), DateTimeException::class, ""], [LocalDate::of(0, 10, 2), SignStyle::EXCEEDS_PAD(), null, "00"], [LocalDate::of(1, 10, 2), SignStyle::EXCEEDS_PAD(), null, "01"], [LocalDate::of(-1, 10, 2), SignStyle::EXCEEDS_PAD(), null, "-01"], [LocalDate::of(20001, 10, 2), SignStyle::ALWAYS(), DateTimeException::class, ""], [LocalDate::of(20001, 10, 2), SignStyle::NORMAL(), DateTimeException::class, ""], [LocalDate::of(20001, 10, 2), SignStyle::NEVER(), DateTimeException::class, ""], [LocalDate::of(20001, 10, 2), SignStyle::EXCEEDS_PAD(), DateTimeException::class, ""], [LocalDate::of(20001, 10, 2), SignStyle::NOT_NEGATIVE(), DateTimeException::class, ""]]; }
public function parse(DateTimeParseContext $context, $text, $position) { $length = strlen($text); if ($position === $length) { return ~$position; } if ($position < 0 || $position >= $length) { throw new \OutOfRangeException(); } $sign = $text[$position]; $negative = false; $positive = false; if ($sign === $context->getDecimalStyle()->getPositiveSign()) { if ($this->signStyle->parse(true, $context->isStrict(), $this->minWidth === $this->maxWidth) === false) { return ~$position; } $positive = true; $position++; } else { if ($sign === $context->getDecimalStyle()->getNegativeSign()) { if ($this->signStyle->parse(false, $context->isStrict(), $this->minWidth === $this->maxWidth) === false) { return ~$position; } $negative = true; $position++; } else { if ($this->signStyle == SignStyle::ALWAYS() && $context->isStrict()) { return ~$position; } } } $effMinWidth = $context->isStrict() || $this->isFixedWidth($context) ? $this->minWidth : 1; $minEndPos = $position + $effMinWidth; if ($minEndPos > $length) { return ~$position; } $effMaxWidth = ($context->isStrict() || $this->isFixedWidth($context) ? $this->maxWidth : 9) + Math::max($this->subsequentWidth, 0); $total = 0; $totalBig = null; $pos = $position; for ($pass = 0; $pass < 2; $pass++) { $maxEndPos = Math::min($pos + $effMaxWidth, $length); while ($pos < $maxEndPos) { $ch = $text[$pos++]; $digit = $context->getDecimalStyle()->convertToDigit($ch); if ($digit < 0) { $pos--; if ($pos < $minEndPos) { return ~$position; // need at least min width digits } break; } if ($pos - $position > 18) { if ($totalBig === null) { $totalBig = \gmp_init($total); } $totalBig = \gmp_add(\gmp_mul($totalBig, "10"), \gmp_init($digit)); } else { $total = $total * 10 + $digit; } } if ($this->subsequentWidth > 0 && $pass === 0) { // re-parse now we know the correct width $parseLen = $pos - $position; $effMaxWidth = Math::max($effMinWidth, $parseLen - $this->subsequentWidth); $pos = $position; $total = 0; $totalBig = null; } else { break; } } if ($negative) { if ($totalBig !== null) { if (\gmp_cmp($totalBig, "0") === 0 && $context->isStrict()) { return ~($position - 1); // minus zero not allowed } $totalBig = \gmp_neg($totalBig); } else { if ($total === 0 && $context->isStrict()) { return ~($position - 1); // minus zero not allowed } $total = -$total; } } else { if ($this->signStyle == SignStyle::EXCEEDS_PAD() && $context->isStrict()) { $parseLen = $pos - $position; if ($positive) { if ($parseLen <= $this->minWidth) { return ~($position - 1); // '+' only parsed if minWidth exceeded } } else { if ($parseLen > $this->minWidth) { return ~$position; // '+' must be parsed if minWidth exceeded } } } } if ($totalBig !== null) { if (gmp_cmp($totalBig, "-9223372036854775808") < 0 || gmp_cmp($totalBig, "9223372036854775807") > 0) { // overflow, parse 1 less digit $totalBig = gmp_div($totalBig, "10"); $pos--; } return $this->setValue($context, gmp_intval($totalBig), $position, $pos); } return $this->setValue($context, $total, $position, $pos); }
public function provider_parseDigitsLenient() { return [["5", 1, 2, SignStyle::NEVER(), 1, 5], ["5", 2, 2, SignStyle::NEVER(), 1, 5], ["54", 1, 3, SignStyle::NEVER(), 2, 54], ["54", 2, 3, SignStyle::NEVER(), 2, 54], ["54", 3, 3, SignStyle::NEVER(), 2, 54], ["543", 1, 3, SignStyle::NEVER(), 3, 543], ["543", 2, 3, SignStyle::NEVER(), 3, 543], ["543", 3, 3, SignStyle::NEVER(), 3, 543], ["5432", 1, 3, SignStyle::NEVER(), 4, 5432], ["5432", 2, 3, SignStyle::NEVER(), 4, 5432], ["5432", 3, 3, SignStyle::NEVER(), 4, 5432], ["5AAA", 2, 3, SignStyle::NEVER(), 1, 5], ["5", 1, 2, SignStyle::NOT_NEGATIVE(), 1, 5], ["5", 2, 2, SignStyle::NOT_NEGATIVE(), 1, 5], ["54", 1, 3, SignStyle::NOT_NEGATIVE(), 2, 54], ["54", 2, 3, SignStyle::NOT_NEGATIVE(), 2, 54], ["54", 3, 3, SignStyle::NOT_NEGATIVE(), 2, 54], ["543", 1, 3, SignStyle::NOT_NEGATIVE(), 3, 543], ["543", 2, 3, SignStyle::NOT_NEGATIVE(), 3, 543], ["543", 3, 3, SignStyle::NOT_NEGATIVE(), 3, 543], ["5432", 1, 3, SignStyle::NOT_NEGATIVE(), 4, 5432], ["5432", 2, 3, SignStyle::NOT_NEGATIVE(), 4, 5432], ["5432", 3, 3, SignStyle::NOT_NEGATIVE(), 4, 5432], ["5AAA", 2, 3, SignStyle::NOT_NEGATIVE(), 1, 5], ["5", 1, 2, SignStyle::NORMAL(), 1, 5], ["5", 2, 2, SignStyle::NORMAL(), 1, 5], ["54", 1, 3, SignStyle::NORMAL(), 2, 54], ["54", 2, 3, SignStyle::NORMAL(), 2, 54], ["54", 3, 3, SignStyle::NORMAL(), 2, 54], ["543", 1, 3, SignStyle::NORMAL(), 3, 543], ["543", 2, 3, SignStyle::NORMAL(), 3, 543], ["543", 3, 3, SignStyle::NORMAL(), 3, 543], ["5432", 1, 3, SignStyle::NORMAL(), 4, 5432], ["5432", 2, 3, SignStyle::NORMAL(), 4, 5432], ["5432", 3, 3, SignStyle::NORMAL(), 4, 5432], ["5AAA", 2, 3, SignStyle::NORMAL(), 1, 5], ["5", 1, 2, SignStyle::ALWAYS(), 1, 5], ["5", 2, 2, SignStyle::ALWAYS(), 1, 5], ["54", 1, 3, SignStyle::ALWAYS(), 2, 54], ["54", 2, 3, SignStyle::ALWAYS(), 2, 54], ["54", 3, 3, SignStyle::ALWAYS(), 2, 54], ["543", 1, 3, SignStyle::ALWAYS(), 3, 543], ["543", 2, 3, SignStyle::ALWAYS(), 3, 543], ["543", 3, 3, SignStyle::ALWAYS(), 3, 543], ["5432", 1, 3, SignStyle::ALWAYS(), 4, 5432], ["5432", 2, 3, SignStyle::ALWAYS(), 4, 5432], ["5432", 3, 3, SignStyle::ALWAYS(), 4, 5432], ["5AAA", 2, 3, SignStyle::ALWAYS(), 1, 5], ["5", 1, 2, SignStyle::EXCEEDS_PAD(), 1, 5], ["5", 2, 2, SignStyle::EXCEEDS_PAD(), 1, 5], ["54", 1, 3, SignStyle::EXCEEDS_PAD(), 2, 54], ["54", 2, 3, SignStyle::EXCEEDS_PAD(), 2, 54], ["54", 3, 3, SignStyle::EXCEEDS_PAD(), 2, 54], ["543", 1, 3, SignStyle::EXCEEDS_PAD(), 3, 543], ["543", 2, 3, SignStyle::EXCEEDS_PAD(), 3, 543], ["543", 3, 3, SignStyle::EXCEEDS_PAD(), 3, 543], ["5432", 1, 3, SignStyle::EXCEEDS_PAD(), 4, 5432], ["5432", 2, 3, SignStyle::EXCEEDS_PAD(), 4, 5432], ["5432", 3, 3, SignStyle::EXCEEDS_PAD(), 4, 5432], ["5AAA", 2, 3, SignStyle::EXCEEDS_PAD(), 1, 5]]; }