示例#1
0
 protected function resolveYearOfEra(FieldValues $fieldValues, ResolverStyle $resolverStyle)
 {
     $yoeLong = $fieldValues->remove(CF::YEAR_OF_ERA());
     if ($yoeLong !== null) {
         if ($resolverStyle != ResolverStyle::LENIENT()) {
             CF::YEAR_OF_ERA()->checkValidValue($yoeLong);
         }
         $era = $fieldValues->remove(CF::ERA());
         if ($era === null) {
             $year = $fieldValues->get(CF::YEAR());
             if ($resolverStyle == ResolverStyle::STRICT()) {
                 // do not invent era if strict, but do cross-check with year
                 if ($year !== null) {
                     $this->addFieldValue($fieldValues, CF::YEAR(), $year > 0 ? $yoeLong : Math::subtractExact(1, $yoeLong));
                 } else {
                     // reinstate the field removed earlier, no cross-check issues
                     $fieldValues->put(CF::YEAR_OF_ERA(), $yoeLong);
                 }
             } else {
                 // invent era
                 $this->addFieldValue($fieldValues, CF::YEAR(), $year === null || $year > 0 ? $yoeLong : Math::subtractExact(1, $yoeLong));
             }
         } else {
             if ($era === 1) {
                 $this->addFieldValue($fieldValues, CF::YEAR(), $yoeLong);
             } else {
                 if ($era === 0) {
                     $this->addFieldValue($fieldValues, CF::YEAR(), Math::subtractExact(1, $yoeLong));
                 } else {
                     throw new DateTimeException("Invalid value for era: " . $era);
                 }
             }
         }
     } else {
         if ($fieldValues->has(CF::ERA())) {
             CF::ERA()->checkValidValue($fieldValues->get(CF::ERA()));
             // always validated
         }
     }
     return null;
 }
 protected function resolveYAD(FieldValues $fieldValues, ResolverStyle $resolverStyle)
 {
     $y = $this->range(ChronoField::YEAR())->checkValidIntValue($fieldValues->remove(ChronoField::YEAR()), ChronoField::YEAR());
     if ($resolverStyle == ResolverStyle::LENIENT()) {
         $weeks = Math::subtractExact($fieldValues->remove(ChronoField::ALIGNED_WEEK_OF_YEAR()), 1);
         $dow = Math::subtractExact($fieldValues->remove(ChronoField::DAY_OF_WEEK()), 1);
         return $this->resolveAligned($this->dateYearDay($y, 1), 0, $weeks, $dow);
     }
     $aw = $this->range(ChronoField::ALIGNED_WEEK_OF_YEAR())->checkValidIntValue($fieldValues->remove(ChronoField::ALIGNED_WEEK_OF_YEAR()), ChronoField::ALIGNED_WEEK_OF_YEAR());
     $dow = $this->range(ChronoField::DAY_OF_WEEK())->checkValidIntValue($fieldValues->remove(ChronoField::DAY_OF_WEEK()), ChronoField::DAY_OF_WEEK());
     $date = $this->dateYearDay($y, 1)->plus(($aw - 1) * 7, ChronoUnit::DAYS())->adjust(TemporalAdjusters::nextOrSame(DayOfWeek::of($dow)));
     if ($resolverStyle == ResolverStyle::STRICT() && $date->get(ChronoField::YEAR()) != $y) {
         throw new DateTimeException("Strict mode rejected resolved date as it is in a different year");
     }
     return $date;
 }
 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;
 }
 /**
  * @dataProvider data_parseLenientWeek
  * @expectedException \Celest\DateTimeParseException
  */
 public function test_parse_parseLenientWeek_STRICT($str, LocalDate $expected, $smart)
 {
     $f = (new DateTimeFormatterBuilder())->appendValue(IsoFields::WEEK_BASED_YEAR())->appendLiteral(':')->appendValue(IsoFields::WEEK_OF_WEEK_BASED_YEAR())->appendLiteral(':')->appendValue(CF::DAY_OF_WEEK())->toFormatter()->withResolverStyle(ResolverStyle::STRICT());
     LocalDate::parseWith($str, $f);
 }
示例#5
0
 public function resolve(FieldValues $fieldValues, TemporalAccessor $partialTemporal, ResolverStyle $resolverStyle)
 {
     $yearLong = $fieldValues->get(ChronoField::YEAR());
     $qoyLong = $fieldValues->get(IsoFields::QUARTER_OF_YEAR());
     if ($yearLong === null || $qoyLong === null) {
         return null;
     }
     $y = ChronoField::YEAR()->checkValidIntValue($yearLong);
     // always validate
     $doq = $fieldValues->get(IsoFields::DAY_OF_QUARTER());
     IsoFields::ensureIso($partialTemporal);
     if ($resolverStyle == ResolverStyle::LENIENT()) {
         $date = LocalDate::of($y, 1, 1)->plusMonths(Math::multiplyExact(Math::subtractExact($qoyLong, 1), 3));
         $doq = Math::subtractExact($doq, 1);
     } else {
         $qoy = IsoFields::QUARTER_OF_YEAR()->range()->checkValidIntValue($qoyLong, IsoFields::QUARTER_OF_YEAR());
         // validated
         $date = LocalDate::of($y, ($qoy - 1) * 3 + 1, 1);
         if ($doq < 1 || $doq > 90) {
             if ($resolverStyle == ResolverStyle::STRICT()) {
                 $this->rangeRefinedBy($date)->checkValidValue($doq, $this);
                 // only allow exact range
             } else {
                 // SMART
                 $this->range()->checkValidValue($doq, $this);
                 // allow 1-92 rolling into next quarter
             }
         }
         $doq--;
     }
     $fieldValues->remove($this);
     $fieldValues->remove(ChronoField::YEAR());
     $fieldValues->remove(IsoFields::QUARTER_OF_YEAR());
     return $date->plusDays($doq);
 }
 /**
  * @dataProvider data_weekFields
  */
 public function test_parse_resolve_localizedWoWBY_strict(DayOfWeek $firstDayOfWeek, $minDays)
 {
     $week = WeekFields::of($firstDayOfWeek, $minDays);
     $wowbyField = $week->weekOfWeekBasedYear();
     $yowbyField = $week->weekBasedYear();
     $f = (new DateTimeFormatterBuilder())->appendValue($yowbyField)->appendLiteral(':')->appendValue($wowbyField)->appendLiteral(':')->appendValue(CF::DAY_OF_WEEK())->toFormatter()->withResolverStyle(ResolverStyle::STRICT());
     $str = "2012:0:1";
     try {
         $date = LocalDate::parseWith($str, $f);
         $this->assertEquals($date->get($yowbyField), 2012);
         $this->assertEquals($date->get($wowbyField), 0);
         $this->assertEquals($date->get(CF::DAY_OF_WEEK()), 1);
     } catch (DateTimeException $ex) {
         // expected
     }
 }
 public static function BASIC_ISO_DATE()
 {
     return self::$BASIC_ISO_DATE = (new DateTimeFormatterBuilder())->parseCaseInsensitive()->appendValue2(ChronoField::YEAR(), 4)->appendValue2(ChronoField::MONTH_OF_YEAR(), 2)->appendValue2(ChronoField::DAY_OF_MONTH(), 2)->optionalStart()->appendOffset("+HHMMss", "Z")->toFormatter3(ResolverStyle::STRICT(), IsoChronology::INSTANCE());
 }
 /**
  * @dataProvider data_resolve_ymaa
  */
 public function test_resolve_ymaa_strict($y, $m, $w, $d, $expected, $smar, $strict)
 {
     $fieldValues = new FieldValues();
     $fieldValues->put(ChronoField::YEAR(), $y);
     $fieldValues->put(ChronoField::MONTH_OF_YEAR(), $m);
     $fieldValues->put(ChronoField::ALIGNED_WEEK_OF_MONTH(), $w);
     $fieldValues->put(ChronoField::ALIGNED_DAY_OF_WEEK_IN_MONTH(), $d);
     if ($strict) {
         $date = IsoChronology::INSTANCE()->resolveDate($fieldValues, ResolverStyle::STRICT());
         $this->assertEquals($date, $expected);
         $this->assertEquals($fieldValues->size(), 0);
     } else {
         try {
             IsoChronology::INSTANCE()->resolveDate($fieldValues, ResolverStyle::STRICT());
             $this->fail("Should have failed");
         } catch (DateTimeException $ex) {
             // $expected
         }
     }
 }
示例#9
0
 private function resolveTimeFields()
 {
     // simplify fields
     if ($this->fieldValues->has(CF::CLOCK_HOUR_OF_DAY())) {
         // lenient allows anything, smart allows 0-24, strict allows 1-24
         $ch = $this->fieldValues->remove(CF::CLOCK_HOUR_OF_DAY());
         if ($this->resolverStyle == ResolverStyle::STRICT() || $this->resolverStyle == ResolverStyle::SMART() && $ch != 0) {
             CF::CLOCK_HOUR_OF_DAY()->checkValidValue($ch);
         }
         $this->updateCheckConflict3(CF::CLOCK_HOUR_OF_DAY(), CF::HOUR_OF_DAY(), $ch == 24 ? 0 : $ch);
     }
     if ($this->fieldValues->has(CF::CLOCK_HOUR_OF_AMPM())) {
         // lenient allows anything, smart allows 0-12, strict allows 1-12
         $ch = $this->fieldValues->remove(CF::CLOCK_HOUR_OF_AMPM());
         if ($this->resolverStyle == ResolverStyle::STRICT() || $this->resolverStyle == ResolverStyle::SMART() && $ch != 0) {
             CF::CLOCK_HOUR_OF_AMPM()->checkValidValue($ch);
         }
         $this->updateCheckConflict3(CF::CLOCK_HOUR_OF_AMPM(), CF::HOUR_OF_AMPM(), $ch == 12 ? 0 : $ch);
     }
     if ($this->fieldValues->has(CF::AMPM_OF_DAY()) && $this->fieldValues->has(CF::HOUR_OF_AMPM())) {
         $ap = $this->fieldValues->remove(CF::AMPM_OF_DAY());
         $hap = $this->fieldValues->remove(CF::HOUR_OF_AMPM());
         if ($this->resolverStyle == ResolverStyle::LENIENT()) {
             $this->updateCheckConflict3(CF::AMPM_OF_DAY(), CF::HOUR_OF_DAY(), Math::addExact(Math::multiplyExact($ap, 12), $hap));
         } else {
             // STRICT or SMART
             CF::AMPM_OF_DAY()->checkValidValue($ap);
             CF::HOUR_OF_AMPM()->checkValidValue($ap);
             $this->updateCheckConflict3(CF::AMPM_OF_DAY(), CF::HOUR_OF_DAY(), $ap * 12 + $hap);
         }
     }
     if ($this->fieldValues->has(CF::NANO_OF_DAY())) {
         $nod = $this->fieldValues->remove(CF::NANO_OF_DAY());
         if ($this->resolverStyle != ResolverStyle::LENIENT()) {
             CF::NANO_OF_DAY()->checkValidValue($nod);
         }
         $this->updateCheckConflict3(CF::NANO_OF_DAY(), CF::HOUR_OF_DAY(), Math::div($nod, 3600000000000));
         $this->updateCheckConflict3(CF::NANO_OF_DAY(), CF::MINUTE_OF_HOUR(), Math::div($nod, 60000000000) % 60);
         $this->updateCheckConflict3(CF::NANO_OF_DAY(), CF::SECOND_OF_MINUTE(), Math::div($nod, 1000000000) % 60);
         $this->updateCheckConflict3(CF::NANO_OF_DAY(), CF::NANO_OF_SECOND(), $nod % 1000000000);
     }
     if ($this->fieldValues->has(CF::MICRO_OF_DAY())) {
         $cod = $this->fieldValues->remove(CF::MICRO_OF_DAY());
         if ($this->resolverStyle != ResolverStyle::LENIENT()) {
             CF::MICRO_OF_DAY()->checkValidValue($cod);
         }
         $this->updateCheckConflict3(CF::MICRO_OF_DAY(), CF::SECOND_OF_DAY(), Math::div($cod, 1000000));
         $this->updateCheckConflict3(CF::MICRO_OF_DAY(), CF::MICRO_OF_SECOND(), $cod % 1000000);
     }
     if ($this->fieldValues->has(CF::MILLI_OF_DAY())) {
         $lod = $this->fieldValues->remove(CF::MILLI_OF_DAY());
         if ($this->resolverStyle != ResolverStyle::LENIENT()) {
             CF::MILLI_OF_DAY()->checkValidValue($lod);
         }
         $this->updateCheckConflict3(CF::MILLI_OF_DAY(), CF::SECOND_OF_DAY(), Math::div($lod, 1000));
         $this->updateCheckConflict3(CF::MILLI_OF_DAY(), CF::MILLI_OF_SECOND(), $lod % 1000);
     }
     if ($this->fieldValues->has(CF::SECOND_OF_DAY())) {
         $sod = $this->fieldValues->remove(CF::SECOND_OF_DAY());
         if ($this->resolverStyle != ResolverStyle::LENIENT()) {
             CF::SECOND_OF_DAY()->checkValidValue($sod);
         }
         $this->updateCheckConflict3(CF::SECOND_OF_DAY(), CF::HOUR_OF_DAY(), Math::div($sod, 3600));
         $this->updateCheckConflict3(CF::SECOND_OF_DAY(), CF::MINUTE_OF_HOUR(), Math::div($sod, 60) % 60);
         $this->updateCheckConflict3(CF::SECOND_OF_DAY(), CF::SECOND_OF_MINUTE(), $sod % 60);
     }
     if ($this->fieldValues->has(CF::MINUTE_OF_DAY())) {
         $mod = $this->fieldValues->remove(CF::MINUTE_OF_DAY());
         if ($this->resolverStyle != ResolverStyle::LENIENT()) {
             CF::MINUTE_OF_DAY()->checkValidValue($mod);
         }
         $this->updateCheckConflict3(CF::MINUTE_OF_DAY(), CF::HOUR_OF_DAY(), Math::div($mod, 60));
         $this->updateCheckConflict3(CF::MINUTE_OF_DAY(), CF::MINUTE_OF_HOUR(), $mod % 60);
     }
     // combine partial second fields strictly, leaving lenient expansion to later
     if ($this->fieldValues->has(CF::NANO_OF_SECOND())) {
         $nos = $this->fieldValues->get(CF::NANO_OF_SECOND());
         if ($this->resolverStyle != ResolverStyle::LENIENT()) {
             CF::NANO_OF_SECOND()->checkValidValue($nos);
         }
         if ($this->fieldValues->has(CF::MICRO_OF_SECOND())) {
             $cos = $this->fieldValues->remove(CF::MICRO_OF_SECOND());
             if ($this->resolverStyle != ResolverStyle::LENIENT()) {
                 CF::MICRO_OF_SECOND()->checkValidValue($cos);
             }
             $nos = $cos * 1000 + $nos % 1000;
             $this->updateCheckConflict3(CF::MICRO_OF_SECOND(), CF::NANO_OF_SECOND(), $nos);
         }
         if ($this->fieldValues->has(CF::MILLI_OF_SECOND())) {
             $los = $this->fieldValues->remove(CF::MILLI_OF_SECOND());
             if ($this->resolverStyle != ResolverStyle::LENIENT()) {
                 CF::MILLI_OF_SECOND()->checkValidValue($los);
             }
             $this->updateCheckConflict3(CF::MILLI_OF_SECOND(), CF::NANO_OF_SECOND(), $los * 1000000 + $nos % 1000000);
         }
     }
     // convert to time if all four fields available (optimization)
     if ($this->fieldValues->has(CF::HOUR_OF_DAY()) && $this->fieldValues->has(CF::MINUTE_OF_HOUR()) && $this->fieldValues->has(CF::SECOND_OF_MINUTE()) && $this->fieldValues->has(CF::NANO_OF_SECOND())) {
         $hod = $this->fieldValues->remove(CF::HOUR_OF_DAY());
         $moh = $this->fieldValues->remove(CF::MINUTE_OF_HOUR());
         $som = $this->fieldValues->remove(CF::SECOND_OF_MINUTE());
         $nos = $this->fieldValues->remove(CF::NANO_OF_SECOND());
         $this->resolveTime($hod, $moh, $som, $nos);
     }
 }
 function data_resolveAmPm()
 {
     return [[ResolverStyle::STRICT(), 0, 0], [ResolverStyle::STRICT(), 1, 1], [ResolverStyle::STRICT(), -1, null], [ResolverStyle::STRICT(), 2, null], [ResolverStyle::SMART(), 0, 0], [ResolverStyle::SMART(), 1, 1], [ResolverStyle::SMART(), -1, null], [ResolverStyle::SMART(), 2, null], [ResolverStyle::LENIENT(), 0, 0], [ResolverStyle::LENIENT(), 1, 1], [ResolverStyle::LENIENT(), -1, -1], [ResolverStyle::LENIENT(), 2, 2]];
 }
 private function resolveWBY(FieldValues $fieldValues, Chronology $chrono, $localDow, ResolverStyle $resolverStyle)
 {
     $yowby = $this->weekDef->weekBasedYear->range()->checkValidIntValue($fieldValues->get($this->weekDef->weekBasedYear), $this->weekDef->weekBasedYear);
     if ($resolverStyle == ResolverStyle::LENIENT()) {
         $date = $this->ofWeekBasedYear($chrono, $yowby, 1, $localDow);
         $wowby = $fieldValues->get($this->weekDef->weekOfWeekBasedYear);
         $weeks = Math::subtractExact($wowby, 1);
         $date = $date->plus($weeks, ChronoUnit::WEEKS());
     } else {
         $wowby = $this->weekDef->weekOfWeekBasedYear->range()->checkValidIntValue($fieldValues->get($this->weekDef->weekOfWeekBasedYear), $this->weekDef->weekOfWeekBasedYear);
         // validate
         $date = $this->ofWeekBasedYear($chrono, $yowby, $wowby, $localDow);
         if ($resolverStyle == ResolverStyle::STRICT() && $this->localizedWeekBasedYear($date) != $yowby) {
             throw new DateTimeException("Strict mode rejected resolved date as it is in a different week-based-year");
         }
     }
     $fieldValues->remove($this);
     $fieldValues->remove($this->weekDef->weekBasedYear);
     $fieldValues->remove($this->weekDef->weekOfWeekBasedYear);
     $fieldValues->remove(CF::DAY_OF_WEEK());
     return $date;
 }
 /**
  * @dataProvider data_samples
  */
 public function test_samples_parse_STRICT(TemporalField $field, LocalDate $date, $value)
 {
     $f = (new DateTimeFormatterBuilder())->appendValue($field)->toFormatter()->withResolverStyle(ResolverStyle::STRICT());
     $parsed = LocalDate::parseWith(strval($value), $f);
     $this->assertEquals($parsed, $date);
 }
 public function data_resolverStyle()
 {
     return [["2000/15/30", ResolverStyle::LENIENT(), null, 2001, 3, 30], ["2000/02/30", ResolverStyle::SMART(), null, 2000, 2, 29], ["2000/02/29", ResolverStyle::STRICT(), null, 2000, 2, 29], ["2000/15/30 CE", ResolverStyle::LENIENT(), null, 2001, 3, 30], ["2000/02/30 CE", ResolverStyle::SMART(), null, 2000, 2, 29], ["5/02/29 BCE", ResolverStyle::STRICT(), null, 5, 2, 29], ["4/02/29 BCE", ResolverStyle::STRICT(), DateTimeException::class, -1, -1, -1], ["2000/02/30 CE", ResolverStyle::STRICT(), DateTimeException::class, -1, -1, -1]];
 }
 public function test_isoInstant_basics()
 {
     $this->assertEquals(DateTimeFormatter::ISO_INSTANT()->getChronology(), null);
     $this->assertEquals(DateTimeFormatter::ISO_INSTANT()->getZone(), null);
     $this->assertEquals(DateTimeFormatter::ISO_INSTANT()->getResolverStyle(), ResolverStyle::STRICT());
 }