parse method

  1. @override
FlexiDate parse(
  1. String toParse
)
override

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");
  }
}