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); }
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; }
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; }
private function resolveInstant() { // add instant seconds if we have date, time and zone if ($this->date !== null && $this->time !== null) { if ($this->zone !== null) { $instant = $this->date->atTime($this->time)->atZone($this->zone)->getLong(CF::INSTANT_SECONDS()); $this->fieldValues->put(CF::INSTANT_SECONDS(), $instant); } else { $offsetSecs = $this->fieldValues->get(CF::OFFSET_SECONDS()); if ($offsetSecs !== null) { $offset = ZoneOffset::ofTotalSeconds($offsetSecs); $instant = $this->date->atTime($this->time)->atZone($offset)->getLong(CF::INSTANT_SECONDS()); $this->fieldValues->put(CF::INSTANT_SECONDS(), $instant); } } } }
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; }
public function getLong(TemporalField $field) { $val = $this->fields->get($field); if ($val === null) { throw new DateTimeException("Field missing: " . $field); } return $val; }