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); }
/** * @dataProvider data_parseLenientWeek */ public function test_parse_parseLenientWeek_SMART($str, LocalDate $expected, $smart) { $f = (new DateTimeFormatterBuilder())->appendValue(IsoFields::WEEK_BASED_YEAR())->appendLiteral(':')->appendValue(IsoFields::WEEK_OF_WEEK_BASED_YEAR())->appendLiteral(':')->appendValue(CF::DAY_OF_WEEK())->toFormatter()->withResolverStyle(ResolverStyle::SMART()); if ($smart) { $parsed = LocalDate::parseWith($str, $f); $this->assertEquals($parsed, $expected); } else { try { LocalDate::parseWith($str, $f); $this->fail("Should have failed"); } catch (DateTimeParseException $ex) { // $expected } } }
protected function resolveYMD(FieldValues $fieldValues, ResolverStyle $resolverStyle) { $y = $this->range(ChronoField::YEAR())->checkValidIntValue($fieldValues->remove(ChronoField::YEAR()), ChronoField::YEAR()); if ($resolverStyle == ResolverStyle::LENIENT()) { $months = Math::subtractExact($fieldValues->remove(ChronoField::MONTH_OF_YEAR()), 1); $days = Math::subtractExact($fieldValues->remove(ChronoField::DAY_OF_MONTH()), 1); return $this->date($y, 1, 1)->plus($months, ChronoUnit::MONTHS())->plus($days, ChronoUnit::DAYS()); } $moy = $this->range(ChronoField::MONTH_OF_YEAR())->checkValidIntValue($fieldValues->remove(ChronoField::MONTH_OF_YEAR()), ChronoField::MONTH_OF_YEAR()); $domRange = $this->range(ChronoField::DAY_OF_MONTH()); $dom = $domRange->checkValidIntValue($fieldValues->remove(ChronoField::DAY_OF_MONTH()), ChronoField::DAY_OF_MONTH()); if ($resolverStyle == ResolverStyle::SMART()) { // previous valid try { return $this->date($y, $moy, $dom); } catch (DateTimeException $ex) { return $this->date($y, $moy, 1)->adjust(TemporalAdjusters::lastDayOfMonth()); } } return $this->date($y, $moy, $dom); }
/** * @dataProvider data_weekFields * @group long */ public function test_parse_resolve_localizedWom(DayOfWeek $firstDayOfWeek, $minDays) { $date = LocalDate::of(2012, 12, 15); $week = WeekFields::of($firstDayOfWeek, $minDays); $womField = $week->weekOfMonth(); for ($i = 1; $i <= 60; $i++) { $f = (new DateTimeFormatterBuilder())->appendValue(CF::YEAR())->appendLiteral(':')->appendValue(CF::MONTH_OF_YEAR())->appendLiteral(':')->appendValue($womField)->appendLiteral(':')->appendValue(CF::DAY_OF_WEEK())->toFormatter()->withResolverStyle(ResolverStyle::SMART()); $str = $date->getYear() . ":" . $date->getMonthValue() . ":" . $date->get($womField) . ":" . $date->get(CF::DAY_OF_WEEK()); $parsed = LocalDate::parseWith($str, $f); $this->assertEquals($parsed, $date, " ::" . $str . "::" . $i); $date = $date->plusDays(1); } }
public static function RFC_1123_DATE_TIME() { // manually code maps to ensure correct data always used // (locale data can be changed by application code) $dow = [1 => "Mon", 2 => "Tue", 3 => "Wed", 4 => "Thu", 5 => "Fri", 6 => "Sat", 7 => "Sun"]; $moy = [1 => "Jan", 2 => "Feb", 3 => "Mar", 4 => "Apr", 5 => "May", 6 => "Jun", 7 => "Jul", 8 => "Aug", 9 => "Sep", 10 => "Oct", 11 => "Nov", 12 => "Dec"]; return self::$RFC_1123_DATE_TIME = (new DateTimeFormatterBuilder())->parseCaseInsensitive()->parseLenient()->optionalStart()->appendText3(ChronoField::DAY_OF_WEEK(), $dow)->appendLiteral2(", ")->optionalEnd()->appendValue3(ChronoField::DAY_OF_MONTH(), 1, 2, SignStyle::NOT_NEGATIVE())->appendLiteral(' ')->appendText3(ChronoField::MONTH_OF_YEAR(), $moy)->appendLiteral(' ')->appendValue2(ChronoField::YEAR(), 4)->appendLiteral(' ')->appendValue2(ChronoField::HOUR_OF_DAY(), 2)->appendLiteral(':')->appendValue2(ChronoField::MINUTE_OF_HOUR(), 2)->optionalStart()->appendLiteral(':')->appendValue2(ChronoField::SECOND_OF_MINUTE(), 2)->optionalEnd()->appendLiteral(' ')->appendOffset("+HHMM", "GMT")->toFormatter3(ResolverStyle::SMART(), IsoChronology::INSTANCE()); }
/** * @dataProvider data_resolve_ymaa */ public function test_resolve_ymaa_smart($y, $m, $w, $d, $expected, $smar, $strict) { $fieldValues = new FieldValues(); $fieldValues->put(ChronoField::YEAR(), $y); $fieldValues->put(ChronoField::MONTH_OF_YEAR(), $m); $fieldValues->put(ChronoField::ALIGNED_WEEK_OF_MONTH(), $w); $fieldValues->put(ChronoField::ALIGNED_DAY_OF_WEEK_IN_MONTH(), $d); if ($smar) { $date = IsoChronology::INSTANCE()->resolveDate($fieldValues, ResolverStyle::SMART()); $this->assertEquals($date, $expected); $this->assertEquals($fieldValues->size(), 0); } else { try { IsoChronology::INSTANCE()->resolveDate($fieldValues, ResolverStyle::SMART()); $this->fail("Should have failed"); } catch (DateTimeException $ex) { // $expected } } }
private function resolveTime($hod, $moh, $som, $nos) { if ($this->resolverStyle == ResolverStyle::LENIENT()) { $totalNanos = Math::multiplyExact($hod, 3600000000000); $totalNanos = Math::addExact($totalNanos, Math::multiplyExact($moh, 60000000000)); $totalNanos = Math::addExact($totalNanos, Math::multiplyExact($som, 1000000000)); $totalNanos = Math::addExact($totalNanos, $nos); $excessDays = (int) Math::floorDiv($totalNanos, 86400000000000); // safe int cast $nod = Math::floorMod($totalNanos, 86400000000000); $this->updateCheckConflict(LocalTime::ofNanoOfDay($nod), Period::ofDays($excessDays)); } else { // STRICT or SMART $mohVal = CF::MINUTE_OF_HOUR()->checkValidIntValue($moh); $nosVal = CF::NANO_OF_SECOND()->checkValidIntValue($nos); // handle 24:00 end of day if ($this->resolverStyle == ResolverStyle::SMART() && $hod == 24 && $mohVal == 0 && $som == 0 && $nosVal == 0) { $this->updateCheckConflict(LocalTime::MIDNIGHT(), Period::ofDays(1)); } else { $hodVal = CF::HOUR_OF_DAY()->checkValidIntValue($hod); $somVal = CF::SECOND_OF_MINUTE()->checkValidIntValue($som); $this->updateCheckConflict(LocalTime::of($hodVal, $mohVal, $somVal, $nosVal), Period::ZERO()); } } }
function data_resolveAmPm() { return [[ResolverStyle::STRICT(), 0, 0], [ResolverStyle::STRICT(), 1, 1], [ResolverStyle::STRICT(), -1, null], [ResolverStyle::STRICT(), 2, null], [ResolverStyle::SMART(), 0, 0], [ResolverStyle::SMART(), 1, 1], [ResolverStyle::SMART(), -1, null], [ResolverStyle::SMART(), 2, null], [ResolverStyle::LENIENT(), 0, 0], [ResolverStyle::LENIENT(), 1, 1], [ResolverStyle::LENIENT(), -1, -1], [ResolverStyle::LENIENT(), 2, 2]]; }
/** * @dataProvider data_samples */ public function test_samples_parse_SMART(TemporalField $field, LocalDate $date, $value) { $f = (new DateTimeFormatterBuilder())->appendValue($field)->toFormatter()->withResolverStyle(ResolverStyle::SMART()); $parsed = LocalDate::parseWith(strval($value), $f); $this->assertEquals($parsed, $date); }
public function data_resolverStyle() { return [["2000/15/30", ResolverStyle::LENIENT(), null, 2001, 3, 30], ["2000/02/30", ResolverStyle::SMART(), null, 2000, 2, 29], ["2000/02/29", ResolverStyle::STRICT(), null, 2000, 2, 29], ["2000/15/30 CE", ResolverStyle::LENIENT(), null, 2001, 3, 30], ["2000/02/30 CE", ResolverStyle::SMART(), null, 2000, 2, 29], ["5/02/29 BCE", ResolverStyle::STRICT(), null, 5, 2, 29], ["4/02/29 BCE", ResolverStyle::STRICT(), DateTimeException::class, -1, -1, -1], ["2000/02/30 CE", ResolverStyle::STRICT(), DateTimeException::class, -1, -1, -1]]; }
public function test_rfc1123_basics() { $this->assertEquals(DateTimeFormatter::RFC_1123_DATE_TIME()->getChronology(), IsoChronology::INSTANCE()); $this->assertEquals(DateTimeFormatter::RFC_1123_DATE_TIME()->getZone(), null); $this->assertEquals(DateTimeFormatter::RFC_1123_DATE_TIME()->getResolverStyle(), ResolverStyle::SMART()); }
/** * Completes this builder by creating the {@code DateTimeFormatter} * using the specified locale. * <p> * This will create a formatter with the specified locale. * Numbers will be printed and parsed using the standard DecimalStyle. * The resolver style will be {@link ResolverStyle#SMART SMART}. * <p> * Calling this method will end any open optional sections by repeatedly * calling {@link #optionalEnd()} before creating the formatter. * <p> * This builder can still be used after creating the formatter if desired, * although the state may have been changed by calls to {@code optionalEnd}. * * @param Locale $locale the locale to use for formatting, not null * @return DateTimeFormatter the created formatter, not null */ public function toFormatter2(Locale $locale) { return $this->toFormatter4($locale, ResolverStyle::SMART(), null); }