function data_fieldBased() { return [[CF::DAY_OF_WEEK(), true, false], [CF::ALIGNED_DAY_OF_WEEK_IN_MONTH(), true, false], [CF::ALIGNED_DAY_OF_WEEK_IN_YEAR(), true, false], [CF::DAY_OF_MONTH(), true, false], [CF::DAY_OF_YEAR(), true, false], [CF::EPOCH_DAY(), true, false], [CF::ALIGNED_WEEK_OF_MONTH(), true, false], [CF::ALIGNED_WEEK_OF_YEAR(), true, false], [CF::MONTH_OF_YEAR(), true, false], [CF::PROLEPTIC_MONTH(), true, false], [CF::YEAR_OF_ERA(), true, false], [CF::YEAR(), true, false], [CF::ERA(), true, false], [CF::AMPM_OF_DAY(), false, true], [CF::CLOCK_HOUR_OF_DAY(), false, true], [CF::HOUR_OF_DAY(), false, true], [CF::CLOCK_HOUR_OF_AMPM(), false, true], [CF::HOUR_OF_AMPM(), false, true], [CF::MINUTE_OF_DAY(), false, true], [CF::MINUTE_OF_HOUR(), false, true], [CF::SECOND_OF_DAY(), false, true], [CF::SECOND_OF_MINUTE(), false, true], [CF::MILLI_OF_DAY(), false, true], [CF::MILLI_OF_SECOND(), false, true], [CF::MICRO_OF_DAY(), false, true], [CF::MICRO_OF_SECOND(), false, true], [CF::NANO_OF_DAY(), false, true], [CF::NANO_OF_SECOND(), false, true]]; }
/** * Calculates the amount of time until another year in terms of the specified unit. * <p> * This calculates the amount of time between two {@code Year} * objects in terms of a single {@code TemporalUnit}. * The start and end points are {@code this} and the specified year. * The result will be negative if the end is before the start. * The {@code Temporal} passed to this method is converted to a * {@code Year} using {@link #from(TemporalAccessor)}. * For example, the amount in decades between two year can be calculated * using {@code startYear.until(endYear, DECADES)}. * <p> * The calculation returns a whole number, representing the number of * complete units between the two years. * For example, the amount in decades between 2012 and 2031 * will only be one decade as it is one year short of two decades. * <p> * There are two equivalent ways of using this method. * The first is to invoke this method. * The second is to use {@link TemporalUnit#between(Temporal, Temporal)}: * <pre> * // these two lines are equivalent * amount = start.until(end, YEARS); * amount = YEARS.between(start, end); * </pre> * The choice should be made based on which makes the code more readable. * <p> * The calculation is implemented in this method for {@link ChronoUnit}. * The units {@code YEARS}, {@code DECADES}, {@code CENTURIES}, * {@code MILLENNIA} and {@code ERAS} are supported. * Other {@code ChronoUnit} values will throw an exception. * <p> * If the unit is not a {@code ChronoUnit}, then the result of this method * is obtained by invoking {@code TemporalUnit.between(Temporal, Temporal)} * passing {@code this} as the first argument and the converted input temporal * as the second argument. * <p> * This instance is immutable and unaffected by this method call. * * @param Temporal $endExclusive the end date, exclusive, which is converted to a {@code Year}, not null * @param TemporalUnit $unit the unit to measure the amount in, not null * @return int the amount of time between this year and the end year * @throws DateTimeException if the amount cannot be calculated, or the end * temporal cannot be converted to a {@code Year} * @throws UnsupportedTemporalTypeException if the unit is not supported * @throws ArithmeticException if numeric overflow occurs */ public function until(Temporal $endExclusive, TemporalUnit $unit) { $end = Year::from($endExclusive); if ($unit instanceof ChronoUnit) { $yearsUntil = $end->year - $this->year; // no overflow switch ($unit) { case ChronoUnit::YEARS(): return $yearsUntil; case ChronoUnit::DECADES(): return Math::div($yearsUntil, 10); case ChronoUnit::CENTURIES(): return Math::div($yearsUntil, 100); case ChronoUnit::MILLENNIA(): return Math::div($yearsUntil, 1000); case ChronoUnit::ERAS(): return $end->getLong(ChronoField::ERA()) - $this->getLong(ChronoField::ERA()); } throw new UnsupportedTemporalTypeException("Unsupported unit: " . $unit); } return $unit->between($this, $end); }
protected function resolveYearOfEra(FieldValues $fieldValues, ResolverStyle $resolverStyle) { $yoeLong = $fieldValues->remove(ChronoField::YEAR_OF_ERA()); if ($yoeLong != null) { $eraLong = $fieldValues->remove(ChronoField::ERA()); if ($resolverStyle != ResolverStyle::LENIENT()) { $yoe = $this->range(ChronoField::YEAR_OF_ERA())->checkValidIntValue($yoeLong, ChronoField::YEAR_OF_ERA()); } else { $yoe = Math::toIntExact($yoeLong); } if ($eraLong != null) { $eraObj = $this->eraOf($this->range(ChronoField::ERA())->checkValidIntValue($eraLong, ChronoField::ERA())); self::addFieldValue($fieldValues, ChronoField::YEAR(), $this->prolepticYear($eraObj, $yoe)); } else { if ($fieldValues->has(ChronoField::YEAR())) { $year = $this->range(ChronoField::YEAR())->checkValidIntValue($fieldValues[ChronoField::YEAR()->__toString()][1], ChronoField::YEAR()); $chronoDate = $this->dateYearDay($year, 1); self::addFieldValue($fieldValues, ChronoField::YEAR(), $this->prolepticYear($chronoDate->getEra(), $yoe)); } else { if ($resolverStyle == ResolverStyle::STRICT()) { // do not invent era if strict // reinstate the field removed earlier, no cross-check issues $fieldValues[ChronoField::YEAR_OF_ERA()->__toString()][1] = $yoeLong; } else { $eras = $this->eras(); if (empty($eras)) { self::addFieldValue($fieldValues, ChronoField::YEAR(), $yoe); } else { $eraObj = $eras[count($eras) - 1]; $this->addFieldValue($fieldValues, ChronoField::YEAR(), $this->prolepticYear($eraObj, $yoe)); } } } } } else { if ($fieldValues->has(ChronoField::ERA())) { $this->range(ChronoField::ERA())->checkValidValue($fieldValues[ChronoField::ERA()->__toString()][1], ChronoField::ERA()); // always validated } } return null; }
public function test_getLong_TemporalField() { $test = LocalDate::of(2008, 6, 30); $this->assertEquals($test->getLong(CF::YEAR()), 2008); $this->assertEquals($test->getLong(CF::MONTH_OF_YEAR()), 6); $this->assertEquals($test->getLong(CF::YEAR_OF_ERA()), 2008); $this->assertEquals($test->getLong(CF::ERA()), 1); $this->assertEquals($test->getLong(CF::PROLEPTIC_MONTH()), 2008 * 12 + 6 - 1); $this->assertEquals($test->getLong(CF::DAY_OF_MONTH()), 30); $this->assertEquals($test->getLong(CF::DAY_OF_WEEK()), 1); $this->assertEquals($test->getLong(CF::DAY_OF_YEAR()), 182); }
public function test_isSupported_TemporalField() { // TODO $this->assertEquals($this->TEST_DATE_TIME->isSupported(null), false); $this->assertEquals($this->TEST_DATE_TIME->isSupported(CF::NANO_OF_SECOND()), true); $this->assertEquals($this->TEST_DATE_TIME->isSupported(CF::NANO_OF_DAY()), true); $this->assertEquals($this->TEST_DATE_TIME->isSupported(CF::MICRO_OF_SECOND()), true); $this->assertEquals($this->TEST_DATE_TIME->isSupported(CF::MICRO_OF_DAY()), true); $this->assertEquals($this->TEST_DATE_TIME->isSupported(CF::MILLI_OF_SECOND()), true); $this->assertEquals($this->TEST_DATE_TIME->isSupported(CF::MILLI_OF_DAY()), true); $this->assertEquals($this->TEST_DATE_TIME->isSupported(CF::SECOND_OF_MINUTE()), true); $this->assertEquals($this->TEST_DATE_TIME->isSupported(CF::SECOND_OF_DAY()), true); $this->assertEquals($this->TEST_DATE_TIME->isSupported(CF::MINUTE_OF_HOUR()), true); $this->assertEquals($this->TEST_DATE_TIME->isSupported(CF::MINUTE_OF_DAY()), true); $this->assertEquals($this->TEST_DATE_TIME->isSupported(CF::HOUR_OF_AMPM()), true); $this->assertEquals($this->TEST_DATE_TIME->isSupported(CF::CLOCK_HOUR_OF_AMPM()), true); $this->assertEquals($this->TEST_DATE_TIME->isSupported(CF::HOUR_OF_DAY()), true); $this->assertEquals($this->TEST_DATE_TIME->isSupported(CF::CLOCK_HOUR_OF_DAY()), true); $this->assertEquals($this->TEST_DATE_TIME->isSupported(CF::AMPM_OF_DAY()), true); $this->assertEquals($this->TEST_DATE_TIME->isSupported(CF::DAY_OF_WEEK()), true); $this->assertEquals($this->TEST_DATE_TIME->isSupported(CF::ALIGNED_DAY_OF_WEEK_IN_MONTH()), true); $this->assertEquals($this->TEST_DATE_TIME->isSupported(CF::ALIGNED_DAY_OF_WEEK_IN_YEAR()), true); $this->assertEquals($this->TEST_DATE_TIME->isSupported(CF::DAY_OF_MONTH()), true); $this->assertEquals($this->TEST_DATE_TIME->isSupported(CF::DAY_OF_YEAR()), true); $this->assertEquals($this->TEST_DATE_TIME->isSupported(CF::EPOCH_DAY()), true); $this->assertEquals($this->TEST_DATE_TIME->isSupported(CF::ALIGNED_WEEK_OF_MONTH()), true); $this->assertEquals($this->TEST_DATE_TIME->isSupported(CF::ALIGNED_WEEK_OF_YEAR()), true); $this->assertEquals($this->TEST_DATE_TIME->isSupported(CF::MONTH_OF_YEAR()), true); $this->assertEquals($this->TEST_DATE_TIME->isSupported(CF::PROLEPTIC_MONTH()), true); $this->assertEquals($this->TEST_DATE_TIME->isSupported(CF::YEAR()), true); $this->assertEquals($this->TEST_DATE_TIME->isSupported(CF::YEAR_OF_ERA()), true); $this->assertEquals($this->TEST_DATE_TIME->isSupported(CF::ERA()), true); $this->assertEquals($this->TEST_DATE_TIME->isSupported(CF::INSTANT_SECONDS()), true); $this->assertEquals($this->TEST_DATE_TIME->isSupported(CF::OFFSET_SECONDS()), true); }
public static function init() { self::$FIELD_MAP = ['G' => ChronoField::ERA(), 'y' => ChronoField::YEAR_OF_ERA(), 'u' => ChronoField::YEAR(), 'Q' => IsoFields::QUARTER_OF_YEAR(), 'q' => IsoFields::QUARTER_OF_YEAR(), 'M' => ChronoField::MONTH_OF_YEAR(), 'L' => ChronoField::MONTH_OF_YEAR(), 'D' => ChronoField::DAY_OF_YEAR(), 'd' => ChronoField::DAY_OF_MONTH(), 'F' => ChronoField::ALIGNED_DAY_OF_WEEK_IN_MONTH(), 'E' => ChronoField::DAY_OF_WEEK(), 'c' => ChronoField::DAY_OF_WEEK(), 'e' => ChronoField::DAY_OF_WEEK(), 'a' => ChronoField::AMPM_OF_DAY(), 'H' => ChronoField::HOUR_OF_DAY(), 'k' => ChronoField::CLOCK_HOUR_OF_DAY(), 'K' => ChronoField::HOUR_OF_AMPM(), 'h' => ChronoField::CLOCK_HOUR_OF_AMPM(), 'm' => ChronoField::MINUTE_OF_HOUR(), 's' => ChronoField::SECOND_OF_MINUTE(), 'S' => ChronoField::NANO_OF_SECOND(), 'A' => ChronoField::MILLI_OF_DAY(), 'n' => ChronoField::NANO_OF_SECOND(), 'N' => ChronoField::NANO_OF_DAY()]; }
/** * @dataProvider data_resolve_yearOfEra */ public function test_resolve_yearOfEra(ResolverStyle $style, $e, $yoe, $y, $field, $expected) { $fieldValues = new FieldValues(); if ($e !== null) { $fieldValues->put(ChronoField::ERA(), $e); } if ($yoe !== null) { $fieldValues->put(ChronoField::YEAR_OF_ERA(), $yoe); } if ($y !== null) { $fieldValues->put(ChronoField::YEAR(), $y); } if ($field !== null) { $date = IsoChronology::INSTANCE()->resolveDate($fieldValues, $style); $this->assertEquals($date, null); $this->assertEquals($fieldValues->get($field), $expected); $this->assertEquals($fieldValues->size(), 1); } else { try { IsoChronology::INSTANCE()->resolveDate($fieldValues, $style); $this->{$this}->fail("Should have failed"); } catch (DateTimeException $ex) { // $expected } } }
public function test_getLong_TemporalField() { $this->assertEquals(self::TEST_2008_06()->getLong(CF::YEAR()), 2008); $this->assertEquals(self::TEST_2008_06()->getLong(CF::MONTH_OF_YEAR()), 6); $this->assertEquals(self::TEST_2008_06()->getLong(CF::YEAR_OF_ERA()), 2008); $this->assertEquals(self::TEST_2008_06()->getLong(CF::ERA()), 1); $this->assertEquals(self::TEST_2008_06()->getLong(CF::PROLEPTIC_MONTH()), 2008 * 12 + 6 - 1); }
function data_resolveTwoToDate() { return [[ChronoField::YEAR(), 2012, ChronoField::DAY_OF_YEAR(), 32, LocalDate::of(2012, 2, 1)], [ChronoField::YEAR_OF_ERA(), 2012, ChronoField::DAY_OF_YEAR(), 32, LocalDate::of(2012, 2, 1)], [ChronoField::PROLEPTIC_MONTH(), 2012 * 12 + (2 - 1), ChronoField::DAY_OF_MONTH(), 25, LocalDate::of(2012, 2, 25)], [ChronoField::PROLEPTIC_MONTH(), 2012 * 12 + (2 - 1), ChronoField::DAY_OF_YEAR(), 56, LocalDate::of(2012, 2, 25)], [ChronoField::EPOCH_DAY(), 32, ChronoField::ERA(), 1, LocalDate::of(1970, 2, 2)], [ChronoField::EPOCH_DAY(), -146097 * 5, ChronoField::ERA(), 0, LocalDate::of(1970 - 400 * 5, 1, 1)], [ChronoField::EPOCH_DAY(), 32, ChronoField::YEAR(), 1970, LocalDate::of(1970, 2, 2)], [ChronoField::EPOCH_DAY(), -146097 * 5, ChronoField::YEAR(), 1970 - 400 * 5, LocalDate::of(1970 - 400 * 5, 1, 1)], [ChronoField::EPOCH_DAY(), 32, ChronoField::YEAR_OF_ERA(), 1970, LocalDate::of(1970, 2, 2)], [ChronoField::EPOCH_DAY(), -146097 * 5, ChronoField::YEAR_OF_ERA(), 1 - (1970 - 400 * 5), LocalDate::of(1970 - 400 * 5, 1, 1)], [ChronoField::EPOCH_DAY(), 32, ChronoField::MONTH_OF_YEAR(), 2, LocalDate::of(1970, 2, 2)], [ChronoField::EPOCH_DAY(), 32, ChronoField::DAY_OF_YEAR(), 33, LocalDate::of(1970, 2, 2)], [ChronoField::EPOCH_DAY(), 32, ChronoField::DAY_OF_MONTH(), 2, LocalDate::of(1970, 2, 2)], [ChronoField::EPOCH_DAY(), 32, ChronoField::DAY_OF_WEEK(), 1, LocalDate::of(1970, 2, 2)]]; }
function data_localeDisplayNames() { return [[ChronoField::ERA()], [ChronoField::YEAR()], [ChronoField::MONTH_OF_YEAR()], [ChronoField::DAY_OF_WEEK()], [ChronoField::DAY_OF_MONTH()], [ChronoField::AMPM_OF_DAY()], [ChronoField::HOUR_OF_DAY()], [ChronoField::MINUTE_OF_HOUR()], [ChronoField::SECOND_OF_MINUTE()]]; }
/** * Gets the text for the specified field, locale and style * for the purpose of formatting. * <p> * The text associated with the value is returned. * The null return value should be used if there is no applicable text, or * if the text would be a numeric representation of the value. * * @param TemporalField $field the field to get text for, not null * @param int $value the field value to get text for, not null * @param TextStyle $style the style to get text for, not null * @param Locale $locale the locale to get text for, not null * @return string|null the text for the field value, null if no text found */ public function getText(TemporalField $field, $value, TextStyle $style, Locale $locale) { if ($field == ChronoField::DAY_OF_WEEK()) { if ($value === 7) { $value = 0; } return self::tryFetch('dayNames', $value, $style, $locale); } if ($field == ChronoField::MONTH_OF_YEAR()) { return self::tryFetch('monthNames', $value - 1, $style, $locale); } if ($field == ChronoField::AMPM_OF_DAY()) { $bundle = new ResourceBundle($locale->getLocale(), null); return $bundle['calendar']['gregorian']['AmPmMarkers'][$value]; } if ($field == ChronoField::ERA()) { return self::tryFetch('eras', $value, $style, $locale); } if ($field == IsoFields::QUARTER_OF_YEAR()) { return self::tryFetch('quarters', $value - 1, $style, $locale); } return null; }
/** * @dataProvider data_resolverStyle */ public function test_resolverStyle($str, ResolverStyle $style, $expectedEx, $year, $month, $day) { $builder = new DateTimeFormatterBuilder(); $builder->appendValue(ChronoField::YEAR_OF_ERA()); $builder->appendLiteral("/"); $builder->appendValue(ChronoField::MONTH_OF_YEAR()); $builder->appendLiteral("/"); $builder->appendValue(ChronoField::DAY_OF_MONTH()); $eraMap = [1 => "CE", 0 => "BCE"]; $optionalFormatter = (new DateTimeFormatterBuilder())->appendLiteral(" ")->appendText3(ChronoField::ERA(), $eraMap)->toFormatter(); $formatter = $builder->appendOptional($optionalFormatter)->toFormatter(); $formatter = $formatter->withResolverStyle($style); if ($expectedEx == null) { $accessor = $formatter->parse($str); $this->assertEquals($accessor->get(ChronoField::YEAR_OF_ERA()), $year); $this->assertEquals($accessor->get(ChronoField::MONTH_OF_YEAR()), $month); $this->assertEquals($accessor->get(ChronoField::DAY_OF_MONTH()), $day); } else { try { $formatter->parse($str); $this->fail(); } catch (\Exception $ex) { $this->assertInstanceOf($expectedEx, $ex); } } }
public function test_with() { $base = Year::of(5); $result = $base->with(ChronoField::ERA(), 0); $ad = $base->adjust(IsoEra::of(0)); $this->assertEquals($result, $ad); $prolepticYear = IsoChronology::INSTANCE()->prolepticYear(IsoEra::of(0), 5); $this->assertEquals($result->get(ChronoField::ERA()), 0); $this->assertEquals($result->get(ChronoField::YEAR()), $prolepticYear); $this->assertEquals($result->get(ChronoField::YEAR_OF_ERA()), 5); $result = $base->with(ChronoField::YEAR(), 10); $this->assertEquals($result->get(ChronoField::ERA()), $base->get(ChronoField::ERA())); $this->assertEquals($result->get(ChronoField::YEAR()), 10); $this->assertEquals($result->get(ChronoField::YEAR_OF_ERA()), 10); $result = $base->with(ChronoField::YEAR_OF_ERA(), 20); $this->assertEquals($result->get(ChronoField::ERA()), $base->get(ChronoField::ERA())); $this->assertEquals($result->get(ChronoField::YEAR()), 20); $this->assertEquals($result->get(ChronoField::YEAR_OF_ERA()), 20); }
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; }
public function with(TemporalField $field, $newValue) { if ($field instanceof ChronoField) { $f = $field; if ($this->getLong($f) === $newValue) { return $this; } switch ($f) { case ChronoField::PROLEPTIC_MONTH(): $this->getChronology()->range($f)->checkValidValue($newValue, $f); return $this->plusMonths($newValue - $this->getProlepticMonth()); case ChronoField::YEAR_OF_ERA(): case ChronoField::YEAR(): case ChronoField::ERA(): $nvalue = $this->getChronology()->range($f)->checkValidIntValue($newValue, $f); switch ($f) { case ChronoField::YEAR_OF_ERA(): return $this->withDate($this->isoDate->withYear($this->getProlepticYear() >= 1 ? $nvalue + MinguoChronology::YEARS_DIFFERENCE : 1 - $nvalue + MinguoChronology::YEARS_DIFFERENCE)); case ChronoField::YEAR(): return $this->withDate($this->isoDate->withYear($nvalue + MinguoChronology::YEARS_DIFFERENCE)); case ERA: return $this->withDate($this->isoDate->withYear(1 - $this->getProlepticYear() + MinguoChronology::YEARS_DIFFERENCE)); } } return $this->withDate($this->isoDate->with($field, $newValue)); } return parent::with($field, $newValue); }
public function until(Temporal $endExclusive, TemporalUnit $unit) { $end = $this->getChronology()->dateFrom($endExclusive); if ($unit instanceof ChronoUnit) { switch ($unit) { case CU::DAYS(): return $this->daysUntil($end); case CU::WEEKS(): return $this->daysUntil($end) / 7; case CU::MONTHS(): return $this->monthsUntil($end); case CU::YEARS(): return $this->monthsUntil($end) / 12; case CU::DECADES(): return $this->monthsUntil($end) / 120; case CU::CENTURIES(): return $this->monthsUntil($end) / 1200; case CU::MILLENNIA(): return $this->monthsUntil($end) / 12000; case CU::ERAS(): return $end->getLong(CF::ERA()) - $this->getLong(CF::ERA()); } throw new UnsupportedTemporalTypeException("Unsupported unit: " . $unit); } return $unit->between($this, $end); }
function provider_japaneseEra() { return [[ChronoField::ERA(), TextStyle::FULL(), 2, "Heisei"], [ChronoField::ERA(), TextStyle::SHORT(), 2, "Heisei"], [ChronoField::ERA(), TextStyle::NARROW(), 2, "H"]]; }
public function getLong(TemporalField $field) { if ($field instanceof ChronoField) { switch ($field) { case CF::PROLEPTIC_MONTH(): return $this->getProlepticMonth(); case CF::YEAR_OF_ERA(): $prolepticYear = $this->getProlepticYear(); return $prolepticYear >= 1 ? $prolepticYear : 1 - $prolepticYear; case CF::YEAR(): return $this->getProlepticYear(); case CF::ERA(): return $this->getProlepticYear() >= 1 ? 1 : 0; } return $this->isoDate->getLong($field); } return $field->getFrom($this); }
/** * @inheritdoc */ public function getEra() { return $this->getChronology()->eraOf($this->get(ChronoField::ERA())); }
/** * Calculates the amount of time until another date in terms of the specified unit. * <p> * This calculates the amount of time between two {@code LocalDate} * objects in terms of a single {@code TemporalUnit}. * 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 {@code Temporal} passed to this method is converted to a * {@code LocalDate} using {@link #from(TemporalAccessor)}. * For example, the amount in days between two dates can be calculated * using {@code startDate.until(endDate, DAYS)}. * <p> * The calculation returns a whole number, representing the number of * complete units between the two dates. * For example, the amount in months between 2012-06-15 and 2012-08-14 * will only be one month as it is one day short of two months. * <p> * There are two equivalent ways of using this method. * The first is to invoke this method. * The second is to use {@link TemporalUnit#between(Temporal, Temporal)}: * <pre> * // these two lines are equivalent * amount = start.until(end, MONTHS); * amount = MONTHS.between(start, end); * </pre> * The choice should be made based on which makes the code more readable. * <p> * The calculation is implemented in this method for {@link ChronoUnit}. * The units {@code DAYS}, {@code WEEKS}, {@code MONTHS}, {@code YEARS}, * {@code DECADES}, {@code CENTURIES}, {@code MILLENNIA} and {@code ERAS} * are supported. Other {@code ChronoUnit} values will throw an exception. * <p> * If the unit is not a {@code ChronoUnit}, then the result of this method * is obtained by invoking {@code TemporalUnit.between(Temporal, Temporal)} * passing {@code this} as the first argument and the converted input temporal * as the second argument. * <p> * This instance is immutable and unaffected by this method call. * * @param Temporal $endExclusive the end date, exclusive, which is converted to a {@code LocalDate}, not null * @param TemporalUnit $unit the unit to measure the amount in, not null * @return int the amount of time between this date and the end date * @throws DateTimeException if the amount cannot be calculated, or the end * temporal cannot be converted to a {@code LocalDate} * @throws UnsupportedTemporalTypeException if the unit is not supported * @throws ArithmeticException if numeric overflow occurs */ public function until(Temporal $endExclusive, TemporalUnit $unit) { $end = LocalDate::from($endExclusive); if ($unit instanceof ChronoUnit) { switch ($unit) { case ChronoUnit::DAYS(): return $this->daysUntil($end); case ChronoUnit::WEEKS(): return Math::div($this->daysUntil($end), 7); case ChronoUnit::MONTHS(): return $this->monthsUntil($end); case ChronoUnit::YEARS(): return Math::div($this->monthsUntil($end), 12); case ChronoUnit::DECADES(): return Math::div($this->monthsUntil($end), 120); case ChronoUnit::CENTURIES(): return Math::div($this->monthsUntil($end), 1200); case ChronoUnit::MILLENNIA(): return Math::div($this->monthsUntil($end), 12000); case ChronoUnit::ERAS(): return $end->getLong(ChronoField::ERA()) - $this->getLong(ChronoField::ERA()); } throw new UnsupportedTemporalTypeException("Unsupported unit: " . $unit); } return $unit->between($this, $end); }
/** * @inheritdoc */ public function getDisplayName(TextStyle $style, Locale $locale) { return (new DateTimeFormatterBuilder())->appendText2(ChronoField::ERA(), $style)->toFormatter2($locale)->format($this); }