Skip to content

Commit

Permalink
Fix #483
Browse files Browse the repository at this point in the history
  • Loading branch information
mosuem committed Aug 10, 2023
1 parent 3c5a4fa commit 74641d7
Show file tree
Hide file tree
Showing 2 changed files with 36 additions and 18 deletions.
49 changes: 31 additions & 18 deletions pkgs/intl/lib/src/intl/date_builder.dart
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ class DateBuilder {
/// Ignored if `year < 0` or `year >= 100`.
bool _hasAmbiguousCentury = false;

bool get hasCentury => !_hasAmbiguousCentury || year < 0 || year >= 100;

/// The locale, kept for logging purposes when there's an error.
final String _locale;

Expand Down Expand Up @@ -140,7 +142,7 @@ class DateBuilder {
// We have the day of the month, compare directly.
_verify(day, date.day, date.day, 'day', s, date);
}
_verify(year, date.year, date.year, 'year', s, date);
_verify(getEstimatedYear(), date.year, date.year, 'year', s, date);
}

void _verify(int value, int min, int max, String desc, String originalInput,
Expand Down Expand Up @@ -181,12 +183,31 @@ class DateBuilder {
// TODO(alanknight): Validate the date, especially for things which
// can crash the VM, e.g. large month values.
if (_date != null) return _date!;
int estimatedYear = getEstimatedYear();
DateTime preliminaryResult = _dateTimeConstructor(estimatedYear, month,
dayOrDayOfYear, hour24, minute, second, fractionalSecond, utc);
if (utc && hasCentury) {
_date = preliminaryResult;
} else {
_date = _correctForErrors(preliminaryResult, retries);
}
return _date!;
}

DateTime preliminaryResult;
final hasCentury = !_hasAmbiguousCentury || year < 0 || year >= 100;
int getEstimatedYear() {
DateTime preliminaryResult(int year) => _dateTimeConstructor(
year,
month,
dayOrDayOfYear,
hour24,
minute,
second,
fractionalSecond,
utc,
);
int estimatedYear;
if (hasCentury) {
preliminaryResult = _dateTimeConstructor(year, month, dayOrDayOfYear,
hour24, minute, second, fractionalSecond, utc);
estimatedYear = year;
} else {
var now = clock.now();
if (utc) {
Expand All @@ -198,8 +219,7 @@ class DateBuilder {
var upperDate = _offsetYear(now, 100 - lookBehindYears);
var lowerCentury = (lowerDate.year ~/ 100) * 100;
var upperCentury = (upperDate.year ~/ 100) * 100;
preliminaryResult = _dateTimeConstructor(upperCentury + year, month,
dayOrDayOfYear, hour24, minute, second, fractionalSecond, utc);
estimatedYear = upperCentury + year;

// Our interval must be half-open since there otherwise could be ambiguity
// for a date that is exactly 20 years in the future or exactly 80 years
Expand All @@ -211,21 +231,14 @@ class DateBuilder {
// the upper-bound date.
//
// We don't actually need to check both bounds.
if (preliminaryResult.compareTo(upperDate) <= 0) {
if (preliminaryResult(upperCentury + year).compareTo(upperDate) <= 0) {
// Within range.
assert(preliminaryResult.compareTo(lowerDate) > 0);
assert(preliminaryResult(upperCentury + year).compareTo(lowerDate) > 0);
} else {
preliminaryResult = _dateTimeConstructor(lowerCentury + year, month,
dayOrDayOfYear, hour24, minute, second, fractionalSecond, utc);
estimatedYear = lowerCentury + year;
}
}

if (utc && hasCentury) {
_date = preliminaryResult;
} else {
_date = _correctForErrors(preliminaryResult, retries);
}
return _date!;
return estimatedYear;
}

/// Given a local DateTime, check for errors and try to compensate for them if
Expand Down
5 changes: 5 additions & 0 deletions pkgs/intl/test/date_time_strict_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -162,4 +162,9 @@ void main() {
expect(format.tryParseStrict('14:0:59'), DateTime(1970, 1, 1, 14, 0, 59));
});
});

test('Year in yy format', () {
expect(DateFormat('yy').parseStrict('23'), DateTime(2023));
expect(DateFormat('yyyy').parseStrict('2023'), DateTime(2023));
});
}

0 comments on commit 74641d7

Please sign in to comment.