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; }
/** * @group long */ public function test_loop() { // loop round at least one 400 $year cycle, including before 1970 $date = LocalDate::of(1960, 1, 5); // Tuseday of $week 1 1960 $year = 1960; $wby = 1960; $weekLen = 52; $week = 1; while ($date->getYear() < 2400) { $loopDow = $date->getDayOfWeek(); if ($date->getYear() != $year) { $year = $date->getYear(); } if ($loopDow == DayOfWeek::MONDAY()) { $week++; if ($week == 53 && $weekLen == 52 || $week == 54) { $week = 1; $firstDayOfWeekBasedYear = $date->plusDays(14)->withDayOfYear(1); $firstDay = $firstDayOfWeekBasedYear->getDayOfWeek(); $weekLen = $firstDay == DayOfWeek::THURSDAY() || $firstDay == DayOfWeek::WEDNESDAY() && $firstDayOfWeekBasedYear->isLeapYear() ? 53 : 52; $wby++; } } $this->assertEquals(IsoFields::WEEK_OF_WEEK_BASED_YEAR()->rangeRefinedBy($date), ValueRange::of(1, $weekLen), "Failed on " . $date . " " . $date->getDayOfWeek()); $this->assertEquals(IsoFields::WEEK_OF_WEEK_BASED_YEAR()->getFrom($date), $week, "Failed on " . $date . " " . $date->getDayOfWeek()); $this->assertEquals($date->get(IsoFields::WEEK_OF_WEEK_BASED_YEAR()), $week, "Failed on " . $date . " " . $date->getDayOfWeek()); $this->assertEquals(IsoFields::WEEK_BASED_YEAR()->getFrom($date), $wby, "Failed on " . $date . " " . $date->getDayOfWeek()); $this->assertEquals($date->get(IsoFields::WEEK_BASED_YEAR()), $wby, "Failed on " . $date . " " . $date->getDayOfWeek()); $date = $date->plusDays(1); } }
public function test_nullIsoFields_week_based_year() { TestHelper::assertNullException($this, function () { IsoFields::WEEK_OF_WEEK_BASED_YEAR()->getDisplayName(null); }); }
public static function ISO_WEEK_DATE() { return self::$ISO_WEEK_DATE = (new DateTimeFormatterBuilder())->parseCaseInsensitive()->appendValue3(IsoFields::WEEK_BASED_YEAR(), 4, 10, SignStyle::EXCEEDS_PAD())->appendLiteral2("-W")->appendValue2(IsoFields::WEEK_OF_WEEK_BASED_YEAR(), 2)->appendLiteral('-')->appendValue2(ChronoField::DAY_OF_WEEK(), 1)->optionalStart()->appendOffsetId()->toFormatter3(ResolverStyle::STRICT(), IsoChronology::INSTANCE()); }
public function test_parse_weekDate_largeYear() { $parsed = DateTimeFormatter::ISO_WEEK_DATE()->parseUnresolved("+123456-W04-5", new ParsePosition(0)); $this->assertEquals($parsed->getLong(IsoFields::WEEK_BASED_YEAR()), 123456); $this->assertEquals($parsed->getLong(IsoFields::WEEK_OF_WEEK_BASED_YEAR()), 4); $this->assertEquals($parsed->getLong(ChronoField::DAY_OF_WEEK()), 5); }