public function test__print_fullDateTime()
 {
     $buf = '';
     $this->builder->padNext2(3, '-')->appendLiteral('Z');
     $this->getFormatter()->formatTo(LocalDate::of(2008, 12, 3), $buf);
     $this->assertEquals($buf, "--Z");
 }
 /**
  * The base date for reduced value parsing.
  * @return LocalDate
  */
 public static function BASE_DATE()
 {
     if (self::$BASE_DATE === null) {
         self::$BASE_DATE = LocalDate::of(2000, 1, 1);
     }
     return self::$BASE_DATE;
 }
 public function adjustToFowards($year)
 {
     if ($this->adjustForwards === false && $this->dayOfMonth > 0) {
         $adjustedDate = LocalDate::ofMonth($year, $this->month, $this->dayOfMonth)->minusDays(6);
         $this->dayOfMonth = $adjustedDate->getDayOfMonth();
         $this->month = $adjustedDate->getMonth();
         $this->adjustForwards = true;
     }
 }
 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;
 }
 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);
 }
Exemple #6
0
 private function toDateTime($year)
 {
     $this->adjustToFowards($year);
     if ($this->dayOfMonth === -1) {
         $dayOfMonth = $this->month->length(Year::isLeapYear($year));
         $date = LocalDate::ofMonth($year, $this->month, $dayOfMonth);
         if ($this->dayOfWeek !== null) {
             $date = $date->adjust(TemporalAdjusters::previousOrSame($this->dayOfWeek));
         }
     } else {
         $date = LocalDate::ofMonth($year, $this->month, $this->dayOfMonth);
         if ($this->dayOfWeek !== null) {
             $date = $date->adjust(TemporalAdjusters::nextOrSame($this->dayOfWeek));
         }
     }
     $ldt = LocalDateTime::ofDateAndTime($date, $this->time);
     if ($this->endOfDay) {
         $ldt = $ldt->plusDays(1);
     }
     return $ldt;
 }
 /**
  * @group long
  */
 public function test_comparisons()
 {
     $this->comparisons_LocalDateTime([LocalDate::of(Year::MIN_VALUE, 1, 1), LocalDate::of(Year::MIN_VALUE, 12, 31), LocalDate::of(-1, 1, 1), LocalDate::of(-1, 12, 31), LocalDate::of(0, 1, 1), LocalDate::of(0, 12, 31), LocalDate::of(1, 1, 1), LocalDate::of(1, 12, 31), LocalDate::of(2008, 1, 1), LocalDate::of(2008, 2, 29), LocalDate::of(2008, 12, 31), LocalDate::of(Year::MAX_VALUE, 1, 1), LocalDate::of(Year::MAX_VALUE, 12, 31)]);
 }
 function data_atEndOfMonth()
 {
     return [[YearMonth::of(2008, 1), LocalDate::of(2008, 1, 31)], [YearMonth::of(2008, 2), LocalDate::of(2008, 2, 29)], [YearMonth::of(2008, 3), LocalDate::of(2008, 3, 31)], [YearMonth::of(2008, 4), LocalDate::of(2008, 4, 30)], [YearMonth::of(2008, 5), LocalDate::of(2008, 5, 31)], [YearMonth::of(2008, 6), LocalDate::of(2008, 6, 30)], [YearMonth::of(2008, 12), LocalDate::of(2008, 12, 31)], [YearMonth::of(2009, 1), LocalDate::of(2009, 1, 31)], [YearMonth::of(2009, 2), LocalDate::of(2009, 2, 28)], [YearMonth::of(2009, 3), LocalDate::of(2009, 3, 31)], [YearMonth::of(2009, 4), LocalDate::of(2009, 4, 30)], [YearMonth::of(2009, 5), LocalDate::of(2009, 5, 31)], [YearMonth::of(2009, 6), LocalDate::of(2009, 6, 30)], [YearMonth::of(2009, 12), LocalDate::of(2009, 12, 31)]];
 }
 /**
  * Compares this date to another date, including the chronology.
  * <p>
  * Compares this {@code ThaiBuddhistDate} with another ensuring that the date is the same.
  * <p>
  * Only objects of type {@code ThaiBuddhistDate} are compared, other types return false.
  * To compare the dates of two {@code TemporalAccessor} instances, including dates
  * in two different chronologies, use {@link ChronoField#EPOCH_DAY} as a comparator.
  *
  * @param mixed $obj the object to check, null returns false
  * @return true if this is equal to the other date
  */
 public function equals($obj)
 {
     if ($this === $obj) {
         return true;
     }
     if ($obj instanceof ThaiBuddhistDate) {
         return $this->isoDate->equals($obj->isoDate);
     }
     return false;
 }
 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);
 }
 function resolveYMD(FieldValues $fieldValues, ResolverStyle $resolverStyle)
 {
     $y = CF::YEAR()->checkValidIntValue($fieldValues->remove(CF::YEAR()));
     if ($resolverStyle == ResolverStyle::LENIENT()) {
         $months = Math::subtractExact($fieldValues->remove(CF::MONTH_OF_YEAR()), 1);
         $days = Math::subtractExact($fieldValues->remove(CF::DAY_OF_MONTH()), 1);
         return LocalDate::of($y, 1, 1)->plusMonths($months)->plusDays($days);
     }
     $moy = CF::MONTH_OF_YEAR()->checkValidIntValue($fieldValues->remove(CF::MONTH_OF_YEAR()));
     $dom = CF::DAY_OF_MONTH()->checkValidIntValue($fieldValues->remove(CF::DAY_OF_MONTH()));
     if ($resolverStyle == ResolverStyle::SMART()) {
         // previous valid
         if ($moy == 4 || $moy == 6 || $moy == 9 || $moy == 11) {
             $dom = Math::min($dom, 30);
         } else {
             if ($moy == 2) {
                 $dom = Math::min($dom, Month::FEBRUARY()->length(Year::isLeapYear($y)));
             }
         }
     }
     return LocalDate::of($y, $moy, $dom);
 }
Exemple #12
0
 /**
  * Calculates the period between this date and another date as a {@code Period}.
  * <p>
  * This calculates the period between two dates in terms of years, months and days.
  * The start and end points are {@code this} and the specified date.
  * The result will be negative if the end is before the start.
  * The negative sign will be the same in each of year, month and day.
  * <p>
  * The calculation is performed using the ISO calendar system.
  * If necessary, the input date will be converted to ISO.
  * <p>
  * The start date is included, but the end date is not.
  * The period is calculated by removing complete months, then calculating
  * the remaining number of days, adjusting to ensure that both have the same sign.
  * The number of months is then normalized into years and months based on a 12 month year.
  * A month is considered to be complete if the end day-of-month is greater
  * than or equal to the start day-of-month.
  * For example, from {@code 2010-01-15} to {@code 2011-03-18} is "1 year, 2 months and 3 days".
  * <p>
  * There are two equivalent ways of using this method.
  * The first is to invoke this method.
  * The second is to use {@link Period#between(LocalDate, LocalDate)}:
  * <pre>
  *   // these two lines are equivalent
  *   period = start.until(end);
  *   period = Period.between(start, end);
  * </pre>
  * The choice should be made based on which makes the code more readable.
  *
  * @param ChronoLocalDate $endDateExclusive the end date, exclusive, which may be in any chronology, not null
  * @return Period the period between this date and the end date, not null
  */
 public function untilDate(ChronoLocalDate $endDateExclusive)
 {
     $end = LocalDate::from($endDateExclusive);
     $totalMonths = $end->getProlepticMonth() - $this->getProlepticMonth();
     // safe
     $days = $end->day - $this->day;
     if ($totalMonths > 0 && $days < 0) {
         $totalMonths--;
         $calcDate = $this->plusMonths($totalMonths);
         $days = (int) ($end->toEpochDay() - $calcDate->toEpochDay());
         // safe
     } else {
         if ($totalMonths < 0 && $days > 0) {
             $totalMonths++;
             $days -= $end->lengthOfMonth();
         }
     }
     $years = Math::div($totalMonths, 12);
     // safe
     $months = (int) ($totalMonths % 12);
     // safe
     return Period::of(Math::toIntExact($years), $months, $days);
 }
 public function test_parseBest_secondOption()
 {
     $test = DateTimeFormatter::ofPattern("yyyy-MM-dd[ HH:mm[XXX]]");
     $result = $test->parseBest("2011-06-30", TemporalQueries::fromCallable([ZonedDateTime::class, "from"]), TemporalQueries::fromCallable([LocalDate::class, 'from']));
     $this->assertEquals($result, LocalDate::of(2011, 6, 30));
 }
 /**
  * @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 dateFrom(TemporalAccessor $temporal)
 {
     if ($temporal instanceof ThaiBuddhistDate) {
         return $temporal;
     }
     return ThaiBuddhistDate::ofIsoDate(LocalDate::from($temporal));
 }
 public function test_range()
 {
     $this->assertEquals(CF::MONTH_OF_YEAR()->range(), ValueRange::of(1, 12));
     $this->assertEquals(CF::MONTH_OF_YEAR()->rangeRefinedBy(LocalDate::of(2000, 2, 29)), ValueRange::of(1, 12));
     $this->assertEquals(CF::DAY_OF_MONTH()->range(), ValueRange::ofVariable(1, 28, 31));
     $this->assertEquals(CF::DAY_OF_MONTH()->rangeRefinedBy(LocalDate::of(2000, 2, 29)), ValueRange::of(1, 29));
 }
 public function test_withNanoOfSecond_normal()
 {
     $base = OffsetDateTime::ofDateAndTime(LocalDate::of(2008, 6, 30), LocalTime::of(11, 30, 59, 1), self::OFFSET_PONE());
     $test = $base->withNano(15);
     $this->assertEquals($test, OffsetDateTime::ofDateAndTime(LocalDate::of(2008, 6, 30), LocalTime::of(11, 30, 59, 15), self::OFFSET_PONE()));
 }
 private function date($year, $month, $day)
 {
     return LocalDate::of($year, $month, $day);
 }
Exemple #19
0
 /**
  * @internal
  * @param LocalDate $date
  * @return int
  */
 public static function getWeekBasedYear(LocalDate $date)
 {
     $year = $date->getYear();
     $doy = $date->getDayOfYear();
     if ($doy <= 3) {
         $dow = $date->getDayOfWeek()->getValue() - 1;
         if ($doy - $dow < -2) {
             $year--;
         }
     } else {
         if ($doy >= 363) {
             $dow = $date->getDayOfWeek()->getValue() - 1;
             $doy = $doy - 363 - ($date->isLeapYear() ? 1 : 0);
             if ($doy - $dow >= 0) {
                 $year++;
             }
         }
     }
     return $year;
 }
 public function dateNowOf(Clock $clock)
 {
     return $this->dateFrom(LocalDate::nowOf($clock));
 }
 /**
  * A query for {@code LocalDate} returning null if not found.
  * @param TemporalAccessor $temporal
  * @return null|LocalDate
  */
 public static function _localDate(TemporalAccessor $temporal)
 {
     if ($temporal->isSupported(ChronoField::EPOCH_DAY())) {
         return LocalDate::ofEpochDay($temporal->getLong(ChronoField::EPOCH_DAY()));
     }
     return null;
 }
 public function test_atYear_int_leapYearAdjust()
 {
     $test = MonthDay::of(2, 29);
     $this->assertEquals($test->atYear(2005), LocalDate::of(2005, 2, 28));
 }
 public function test_until_parisLondon()
 {
     $midnightLondon = LocalDate::of(2012, 6, 28)->atStartOfDayWithZone(self::ZONE_LONDON());
     $midnightParis1 = LocalDate::of(2012, 6, 29)->atStartOfDayWithZone(self::ZONE_PARIS());
     $oneAm1 = LocalDateTime::of(2012, 6, 29, 1, 0)->atZone(self::ZONE_PARIS());
     $midnightParis2 = LocalDate::of(2012, 6, 30)->atStartOfDayWithZone(self::ZONE_PARIS());
     $this->assertEquals($midnightLondon->until($midnightParis1, CU::HOURS()), 23);
     $this->assertEquals($midnightLondon->until($oneAm1, CU::HOURS()), 24);
     $this->assertEquals($midnightLondon->until($midnightParis2, CU::HOURS()), 23 + 24);
     $this->assertEquals($midnightLondon->until($midnightParis1, CU::DAYS()), 0);
     $this->assertEquals($midnightLondon->until($oneAm1, CU::DAYS()), 1);
     $this->assertEquals($midnightLondon->until($midnightParis2, CU::DAYS()), 1);
 }
 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 test_print_append()
 {
     $buf = "EXISTING";
     $this->getFormatterWidth(ChronoField::DAY_OF_MONTH(), 1, 2, SignStyle::NEVER())->formatTo(LocalDate::of(2012, 1, 3), $buf);
     $this->assertEquals($buf, "EXISTING3");
 }
 /**
  * @expectedException \Celest\DateTimeException
  */
 public function test_factory_between_TemporalTemporal_invalidMixedTypes()
 {
     $start = Instant::ofEpochSecond(1);
     $end = LocalDate::of(2010, 6, 20);
     Duration::between($start, $end);
 }
 public function test_Apia_jumpForwardOverInternationalDateLine_P12_to_M12()
 {
     // transition occurred at 1879-07-04T00:00+12:33:04
     $test = $this->pacificApia();
     $instantBefore = LocalDate::of(1879, 7, 2)->atStartOfDayWithZone(ZoneOffset::UTC())->toInstant();
     $trans = $test->nextTransition($instantBefore);
     $this->assertEquals($trans->getDateTimeBefore(), LocalDateTime::of(1879, 7, 5, 0, 0));
     $this->assertEquals($trans->getDateTimeAfter(), LocalDateTime::of(1879, 7, 4, 0, 0));
     $this->assertEquals($trans->isGap(), false);
     $this->assertEquals($trans->isOverlap(), true);
     $this->assertEquals($trans->isValidOffset(ZoneOffset::ofHoursMinutesSeconds(+12, 33, 4)), true);
     $this->assertEquals($trans->isValidOffset(ZoneOffset::ofHoursMinutesSeconds(-11, -26, -56)), true);
     $this->assertEquals($trans->getDuration(), Duration::ofHours(-24));
     $this->assertEquals($trans->getInstant(), LocalDateTime::of(1879, 7, 4, 0, 0)->toInstant(ZoneOffset::ofHoursMinutesSeconds(-11, -26, -56)));
     $zdt = ZonedDateTime::of(1879, 7, 4, 23, 0, 0, 0, ZoneId::of("Pacific/Apia"));
     $this->assertEquals($zdt->plusHours(2)->toLocalDateTime(), LocalDateTime::of(1879, 7, 4, 1, 0, 0));
 }
 function provider_patternLocalWeekBasedYearDate()
 {
     return [["e w Y", "6 29 2012", LocalDate::of(2012, 7, 20)], ["'Date: 'Y', day-of-week: 'e', week-of-year: 'w", "Date: 2012, day-of-week: 6, week-of-year: 29", LocalDate::of(2012, 7, 20)], ["Y-ww-ee", "2008-01-01", LocalDate::of(2007, 12, 30)], ["Y-w-e", "2008-52-1", LocalDate::of(2008, 12, 21)], ["Y-w-e", "2008-52-7", LocalDate::of(2008, 12, 27)], ["Y-ww-e", "2009-01-1", LocalDate::of(2008, 12, 28)], ["Y-w-e", "2009-1-4", LocalDate::of(2008, 12, 31)], ["Y-w-e", "2009-1-5", LocalDate::of(2009, 1, 1)], ["YYYYYYYYY-w-e", "000002009-1-5", LocalDate::of(2009, 1, 1)]];
 }
 /**
  * @expectedException \Celest\DateTimeException
  */
 public function test_adjustInto_dateOnly()
 {
     $base = ZoneOffset::ofHoursMinutesSeconds(1, 1, 1);
     $base->adjustInto(LocalDate::of(1909, 2, 2));
 }
Exemple #30
0
 /**
  * Combines this year with a day-of-year to create a {@code LocalDate}.
  * <p>
  * This returns a {@code LocalDate} formed from this year and the specified day-of-year.
  * <p>
  * The day-of-year value 366 is only valid in a leap year.
  *
  * @param int $dayOfYear the day-of-year to use, from 1 to 365-366
  * @return LocalDate the local date formed from this year and the specified date of year, not null
  * @throws DateTimeException if the day of year is zero or less, 366 or greater or equal
  *  to 366 and this is not a leap year
  */
 public function atDay($dayOfYear)
 {
     return LocalDate::ofYearDay($this->year, $dayOfYear);
 }