/** * Adds rules to make the last rules all start from the same year. * Also add one more year to avoid weird case where penultimate year has odd offset. * * @param int $windowStartYear the window start year * @throws \LogicException if there is only one rule defined as being forever */ function tidy($windowStartYear) { if (count($this->lastRuleList) === 1) { throw new \LogicException("Cannot have only one rule defined as being forever"); } // handle last rules if ($this->windowEnd->equals(LocalDateTime::MAX())) { // setup at least one real rule, which closes off other windows nicely $this->maxLastRuleStartYear = Math::max($this->maxLastRuleStartYear, $windowStartYear) + 1; foreach ($this->lastRuleList as $lastRule) { $this->addRule($lastRule->year, $this->maxLastRuleStartYear, $lastRule->month, $lastRule->dayOfMonthIndicator, $lastRule->dayOfWeek, $lastRule->time, $lastRule->timeEndOfDay, $lastRule->timeDefinition, $lastRule->savingAmountSecs); $lastRule->year = $this->maxLastRuleStartYear + 1; } if ($this->maxLastRuleStartYear == Year::MAX_VALUE) { $this->lastRuleList = []; } else { $this->maxLastRuleStartYear++; } } else { // convert all within the endYear limit $endYear = $this->windowEnd->getYear(); foreach ($this->lastRuleList as $lastRule) { $this->addRule($lastRule->year, $endYear + 1, $lastRule->month, $lastRule->dayOfMonthIndicator, $lastRule->dayOfWeek, $lastRule->time, $lastRule->timeEndOfDay, $lastRule->timeDefinition, $lastRule->savingAmountSecs); } $this->lastRuleList = []; $this->maxLastRuleStartYear = Year::MAX_VALUE; } // ensure lists are sorted usort($this->ruleList, [TZRule::class, 'compareTo']); usort($this->lastRuleList, [TZRule::class, 'compareTo']); // default fixed savings to zero if (count($this->ruleList) === 0 && $this->fixedSavingAmountSecs === null) { $this->fixedSavingAmountSecs = 0; } }
/** * Gets the year field. * <p> * This method returns the primitive {@code int} value for the year. * <p> * The year returned by this method is proleptic as per {@code get(YEAR)}. * To obtain the year-of-era, use {@code get(YEAR_OF_ERA)}. * * @return int the year, from MIN_YEAR to MAX_YEAR */ public function getYear() { return $this->dateTime->getYear(); }
/** * Adds a single transition rule to the current window. * <p> * This adds a rule such that the offset, expressed as a daylight savings amount, * changes at the specified date-time. * * @param LocalDateTime $transitionDateTime the date-time that the transition occurs as defined by timeDefintion, not null * @param TimeDefinition $timeDefinition the definition of how to convert local to actual time, not null * @param int $savingAmountSecs the amount of saving from the standard offset after the transition in seconds * @return ZoneRulesBuilder $this, for chaining * @throws \LogicException if no window has yet been added * @throws \LogicException if the window already has fixed savings * @throws \LogicException if the window has reached the maximum capacity of 2000 rules */ public function addRuleToWindow(LocalDateTime $transitionDateTime, TimeDefinition $timeDefinition, $savingAmountSecs) { return $this->addRuleToWindow9($transitionDateTime->getYear(), $transitionDateTime->getYear(), $transitionDateTime->getMonth(), $transitionDateTime->getDayOfMonth(), null, $transitionDateTime->toLocalTime(), false, $timeDefinition, $savingAmountSecs); }
private function check(LocalDateTime $test, $y, $m, $d, $h, $mi, $s, $n) { $this->assertEquals($test->getYear(), $y); $this->assertEquals($test->getMonth()->getValue(), $m); $this->assertEquals($test->getDayOfMonth(), $d); $this->assertEquals($test->getHour(), $h); $this->assertEquals($test->getMinute(), $mi); $this->assertEquals($test->getSecond(), $s); $this->assertEquals($test->getNano(), $n); $this->assertEquals($test, $test); //$this->assertEquals($test->hashCode(), $test->hashCode()); $this->assertEquals(LocalDateTime::of($y, $m, $d, $h, $mi, $s, $n), $test); }
/** * @param LocalDateTime|null $dt * @return null|ZoneOffsetTransition|ZoneOffset * @throws IllegalArgumentException */ private function getOffsetInfo($dt) { if (empty($this->savingsInstantTransitions)) { return $this->standardOffsets[0]; } // check if using last rules if (!empty($this->lastRules) && $dt->isAfter($this->savingsLocalTransitions[count($this->savingsLocalTransitions) - 1])) { /** @var ZoneOffsetTransition[] $transArray */ $transArray = $this->findTransitionArray($dt->getYear()); $info = null; foreach ($transArray as $trans) { $info = $this->findOffsetInfo($dt, $trans); if ($info instanceof ZoneOffsetTransition || $info->equals($trans->getOffsetBefore())) { return $info; } } return $info; } // using historic rules $index = Math::binarySearch($this->savingsLocalTransitions, $dt); if ($index === -1) { // before first transition return $this->wallOffsets[0]; } if ($index < 0) { // switch negative insert position to start of matched range $index = -$index - 2; } else { if ($index < count($this->savingsLocalTransitions) - 1 && $this->savingsLocalTransitions[$index]->equals($this->savingsLocalTransitions[$index + 1])) { // handle overlap immediately following gap $index++; } } if (($index & 1) === 0) { // gap or overlap $dtBefore = $this->savingsLocalTransitions[$index]; $dtAfter = $this->savingsLocalTransitions[$index + 1]; $offsetBefore = $this->wallOffsets[(int) ($index / 2)]; $offsetAfter = $this->wallOffsets[(int) ($index / 2) + 1]; if ($offsetAfter->getTotalSeconds() > $offsetBefore->getTotalSeconds()) { // gap return ZoneOffsetTransition::of($dtBefore, $offsetBefore, $offsetAfter); } else { // overlap return ZoneOffsetTransition::of($dtAfter, $offsetBefore, $offsetAfter); } } else { // normal (neither gap or overlap) return $this->wallOffsets[(int) ($index / 2) + 1]; } }
public function setFieldsDateTime(LocalDateTime $dt) { if ($dt !== null) { $this->fields->put(ChronoField::YEAR(), $dt->getYear()); $this->fields->put(ChronoField::MONTH_OF_YEAR(), $dt->getMonthValue()); $this->fields->put(ChronoField::DAY_OF_MONTH(), $dt->getDayOfMonth()); $this->fields->put(ChronoField::DAY_OF_YEAR(), $dt->getDayOfYear()); $this->fields->put(ChronoField::DAY_OF_WEEK(), $dt->getDayOfWeek()->getValue()); $this->fields->put(IsoFields::WEEK_BASED_YEAR(), $dt->getLong(IsoFields::WEEK_BASED_YEAR())); $this->fields->put(IsoFields::WEEK_OF_WEEK_BASED_YEAR(), $dt->getLong(IsoFields::WEEK_OF_WEEK_BASED_YEAR())); $this->fields->put(ChronoField::HOUR_OF_DAY(), $dt->getHour()); $this->fields->put(ChronoField::MINUTE_OF_HOUR(), $dt->getMinute()); $this->fields->put(ChronoField::SECOND_OF_MINUTE(), $dt->getSecond()); $this->fields->put(ChronoField::NANO_OF_SECOND(), $dt->getNano()); } }