| Index: lib/src/intl/date_format_field.dart
|
| diff --git a/lib/src/intl/date_format_field.dart b/lib/src/intl/date_format_field.dart
|
| index 47a9d7bcc4d85e4328c0c3dca254d941cff9120f..4b8b12e927d289e36f4de9dc8dbb06550b806fc1 100644
|
| --- a/lib/src/intl/date_format_field.dart
|
| +++ b/lib/src/intl/date_format_field.dart
|
| @@ -39,6 +39,13 @@ abstract class _DateFormatField {
|
| /** Abstract method for subclasses to implementing parsing for their format.*/
|
| void parse(_Stream input, _DateBuilder dateFields);
|
|
|
| + /**
|
| + * Abstract method for subclasses to implementing 'loose' parsing for
|
| + * their format, accepting input case-insensitively, and allowing some
|
| + * delimiters to be skipped.
|
| + */
|
| + void parseLoose(_Stream input, _DateBuilder dateFields);
|
| +
|
| /** Parse a literal field. We just look for the exact input. */
|
| void parseLiteral(_Stream input) {
|
| var found = input.read(width);
|
| @@ -47,6 +54,20 @@ abstract class _DateFormatField {
|
| }
|
| }
|
|
|
| + /**
|
| + * Parse a literal field. We accept either an exact match, or an arbitrary
|
| + * amount of whitespace.
|
| + */
|
| + void parseLiteralLoose(_Stream input) {
|
| + var found = input.peek(width);
|
| + if (found == pattern) {
|
| + input.read(width);
|
| + }
|
| + while (!input.atEnd() && input.peek().trim().isEmpty) {
|
| + input.read();
|
| + }
|
| + }
|
| +
|
| /** Throw a format exception with an error message indicating the position.*/
|
| void throwFormatException(_Stream stream) {
|
| throw new FormatException("Trying to read $this from ${stream.contents} "
|
| @@ -64,8 +85,11 @@ class _DateFormatLiteralField extends _DateFormatField {
|
| _DateFormatLiteralField(pattern, parent): super(pattern, parent);
|
|
|
| parse(_Stream input, _DateBuilder dateFields) {
|
| - return parseLiteral(input);
|
| + parseLiteral(input);
|
| }
|
| +
|
| + parseLoose(_Stream input, _DateBuilder dateFields) =>
|
| + parseLiteralLoose(input);
|
| }
|
|
|
| /**
|
| @@ -84,9 +108,12 @@ class _DateFormatQuotedField extends _DateFormatField {
|
| }
|
|
|
| parse(_Stream input, _DateBuilder dateFields) {
|
| - return parseLiteral(input);
|
| + parseLiteral(input);
|
| }
|
|
|
| + parseLoose(_Stream input, _DateBuilder dateFields) =>
|
| + parseLiteralLoose(input);
|
| +
|
| void patchQuotes() {
|
| if (pattern == "''") {
|
| pattern = "'";
|
| @@ -98,6 +125,110 @@ class _DateFormatQuotedField extends _DateFormatField {
|
| }
|
| }
|
|
|
| +/**
|
| + * A field that parses "loosely", meaning that we'll accept input that is
|
| + * missing delimiters, has upper/lower case mixed up, and might not strictly
|
| + * conform to the pattern, e.g. the pattern calls for Sep we might accept
|
| + * sep, september, sEPTember. Doesn't affect numeric fields.
|
| + */
|
| +class _LoosePatternField extends _DateFormatPatternField {
|
| + _LoosePatternField(String pattern, parent) : super(pattern, parent);
|
| +
|
| + /**
|
| + * Parse from a list of possibilities, but case-insensitively.
|
| + * Assumes that input is lower case.
|
| + */
|
| + int parseEnumeratedString(_Stream input, List possibilities) {
|
| + var lowercasePossibilities = possibilities
|
| + .map((x) => x.toLowerCase())
|
| + .toList();
|
| + try {
|
| + return super.parseEnumeratedString(input, lowercasePossibilities);
|
| + } on FormatException {
|
| + return -1;
|
| + }
|
| + }
|
| +
|
| + /**
|
| + * Parse a month name, case-insensitively, and set it in [dateFields].
|
| + * Assumes that [input] is lower case.
|
| + */
|
| + void parseMonth(input, dateFields) {
|
| + if (width <= 2) {
|
| + handleNumericField(input, dateFields.setMonth);
|
| + return;
|
| + }
|
| + var possibilities =
|
| + [symbols.MONTHS, symbols.SHORTMONTHS];
|
| + for (var monthNames in possibilities) {
|
| + var month = parseEnumeratedString(input, monthNames);
|
| + if (month != -1) {
|
| + dateFields.month = month + 1;
|
| + return;
|
| + }
|
| + }
|
| + }
|
| +
|
| + /**
|
| + * Parse a standalone day name, case-insensitively.
|
| + * Assumes that input is lower case. Doesn't do anything
|
| + */
|
| + void parseStandaloneDay(input) {
|
| + // This is ignored, but we still have to skip over it the correct amount.
|
| + if (width <= 2) {
|
| + handleNumericField(input, (x) => x);
|
| + return;
|
| + }
|
| + var possibilities =
|
| + [symbols.STANDALONEWEEKDAYS, symbols.STANDALONESHORTWEEKDAYS];
|
| + for (var dayNames in possibilities) {
|
| + var day = parseEnumeratedString(input, dayNames);
|
| + if (day != -1) {
|
| + return;
|
| + }
|
| + }
|
| + }
|
| +
|
| + /**
|
| + * Parse a standalone month name, case-insensitively.
|
| + * Assumes that input is lower case. Doesn't do anything
|
| + */
|
| + void parseStandaloneMonth(input, dateFields) {
|
| + if (width <= 2) {
|
| + handleNumericField(input, (x) => x);
|
| + return;
|
| + }
|
| + var possibilities =
|
| + [symbols.STANDALONEMONTHS, symbols.STANDALONESHORTMONTHS];
|
| + for (var monthNames in possibilities) {
|
| + var month = parseEnumeratedString(input, monthNames);
|
| + if (month != -1) {
|
| + dateFields.month = month + 1;
|
| + return;
|
| + }
|
| + }
|
| + }
|
| +
|
| + /**
|
| + * Parse a day of the week name, case-insensitively.
|
| + * Assumes that input is lower case. Doesn't do anything
|
| + */
|
| + void parseDayOfWeek(_Stream input) {
|
| + // This is IGNORED, but we still have to skip over it the correct amount.
|
| + if (width <= 2) {
|
| + handleNumericField(input, (x) => x);
|
| + return;
|
| + }
|
| + var possibilities = [symbols.WEEKDAYS, symbols.SHORTWEEKDAYS];
|
| + for (var dayNames in possibilities) {
|
| + var day = parseEnumeratedString(input, dayNames);
|
| + if (day != -1) {
|
| + return;
|
| + }
|
| + }
|
| + }
|
| +}
|
| +
|
| /*
|
| * Represents a field in the pattern that formats some aspect of the
|
| * date. Consists primarily of a switch on the particular pattern characters
|
| @@ -120,6 +251,16 @@ class _DateFormatPatternField extends _DateFormatField {
|
| parseField(input, dateFields);
|
| }
|
|
|
| +
|
| + /**
|
| + * Parse the date according to our specification and put the result
|
| + * into the correct place in dateFields. Allow looser parsing, accepting
|
| + * case-insensitive input and skipped delimiters.
|
| + */
|
| + void parseLoose(_Stream input, _DateBuilder dateFields) {
|
| + new _LoosePatternField(pattern, parent).parse(input, dateFields);
|
| + }
|
| +
|
| /**
|
| * Parse a field representing part of a date pattern. Note that we do not
|
| * return a value, but rather build up the result in [builder].
|
|
|