parse method
Implementation
@override
FlexiDate parse(String toParse) {
if (toParse.isEmpty) {
throw Exception("Empty date cannot be parsed");
}
final parseAttempt = DateTime.tryParse(toParse.trim());
if (parseAttempt != null) {
return FlexiDate.ofDateTime(parseAttempt);
}
final input = "$toParse";
final tokenized = tokenizeString(input, splitAll: true);
try {
final parts = [
for (var token in tokenized)
if (token.isNumeric)
DatePart(token.toInt())
else
DatePart(
DateFormat.MMMM(locale.toLanguageTag()).parseLoose(token).month,
Period.month),
];
final sortedParts = DateParts.of(parts);
final year = sortedParts.year;
final month = sortedParts.month;
final day = sortedParts.day;
if (sortedParts.invalid.isNotEmpty) {
throw Exception(
"Invalid tokens found within date: ${sortedParts.invalid}");
}
if (year != null && month != null && day != null) {
return FlexiDate.of(
day: day,
month: month,
year: year,
);
} else if (year != null && month != null) {
return FlexiDate.of(
day: sortedParts.others.firstOr(),
month: sortedParts.month,
year: sortedParts.year);
} else if (year != null) {
/// This case has ambigious month/day, like 1-2
switch (sortedParts.others.length) {
case 2:
return FlexiDate.of(
year: sortedParts.year,
month: sortedParts.others[0],
day: sortedParts.others[1],
isAmbiguous: true);
case 1:
return FlexiDate.of(
year: sortedParts.year,
month: sortedParts.others.firstOr(),
);
case 0:
return FlexiDate.of(year: sortedParts.year);
default:
throw Exception(
"Unable to extract date parameters from '$toParse'");
}
} else if (month != null && day != null) {
return FlexiDate.of(
month: month, day: day, year: sortedParts.others.firstOr());
} else if (month != null) {
/// In this case, we know there is no unambiguous year or day
switch (sortedParts.others.length) {
case 2:
return FlexiDate.of(
month: month,
day: sortedParts.others.firstOr(),
year: sortedParts.others.lastOr(),
isAmbiguous: true,
);
case 1:
/// I don't like this case, it seems like we shouldn't guess.
return FlexiDate.of(
month: month,
day: sortedParts.others.firstOr(),
isAmbiguous: true);
case 0:
/// Month only. Weird, but okay
return FlexiDate.of(month: month);
default:
throw Exception(
"Found a month ($month) but had too many other parts to create a date");
}
} else if (day != null) {
switch (sortedParts.others.length) {
case 2:
return FlexiDate.of(
month: sortedParts.others.lastOr(),
day: day,
year: sortedParts.others.firstOr(),
isAmbiguous: true);
case 1:
return FlexiDate.of(month: sortedParts.others.firstOr(), day: day);
case 0:
/// Day only. Weird, but okay
return FlexiDate.of(day: day);
default:
throw Exception(
"Found a month ($month) but had too many other parts to create a date");
}
} else {
switch (sortedParts.others.length) {
case 2:
return sortedParts.others.first > 12
? FlexiDate.of(
month: sortedParts.others.lastOr(),
day: sortedParts.others.firstOr(),
isAmbiguous: true)
: FlexiDate.of(
month: sortedParts.others.firstOr(),
day: sortedParts.others.lastOr(),
isAmbiguous: true);
default:
throw Exception(
"Unable to extract date parameters from '$toParse'");
}
}
} catch (e) {
_log.finer("Error parsing date: $e");
return FlexiDate.unparsed(input, "Error $e");
}
}