public function adjustInto(Temporal $temporal, $newValue) { if ($this->isSupportedBy($temporal) === false) { throw new UnsupportedTemporalTypeException("Unsupported field: WeekBasedYear"); } $newWby = $this->range()->checkValidIntValue($newValue, IsoFields::WEEK_BASED_YEAR()); // strict check $date = LocalDate::from($temporal); $dow = $date->get(ChronoField::DAY_OF_WEEK()); $week = IsoFields::getWeek($date); if ($week == 53 && IsoFields::getWeekRangeInt($newWby) == 52) { $week = 52; } $resolved = LocalDate::of($newWby, 1, 4); // 4th is guaranteed to be in week one $days = $dow - $resolved->get(ChronoField::DAY_OF_WEEK()) + ($week - 1) * 7; $resolved = $resolved->plusDays($days); return $temporal->adjust($resolved); }
public function test_format_withChronology_nonChronoFieldMapLink() { $temporal = new format_withChronology_nonChronoFieldMapLink(); $test = (new DateTimeFormatterBuilder())->appendValue2(IsoFields::WEEK_BASED_YEAR(), 4)->toFormatter2(Locale::ENGLISH())->withChronology(IsoChronology::INSTANCE()); $result = $test->format($temporal); $this->assertEquals($result, "2345"); }
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 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()); }
/** * The unit that represents week-based-years for the purpose of addition and subtraction. * <p> * This allows a number of week-based-years to be added to, or subtracted from, a date. * The unit is equal to either 52 or 53 weeks. * The estimated duration of a week-based-year is the same as that of a standard ISO * year at {@code 365.2425 Days}. * <p> * The rules for addition add the number of week-based-years to the existing value * for the week-based-year field retaining the week-of-week-based-year * and day-of-week, unless the week number it too large for the target year. * In that case, the week is set to the last week of the year * with the same day-of-week. * <p> * This unit is an immutable and thread-safe singleton. * @return TemporalUnit */ public static function WEEK_BASED_YEARS() { return IsoFields::WEEK_BASED_YEAR(); }
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); }
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"); } }