# parse method

DateTime parse (String formattedString)

Constructs a new DateTime instance based on `formattedString`.

Throws a FormatException if the input cannot be parsed.

The function parses a subset of ISO 8601 which includes the subset accepted by RFC 3339.

The accepted inputs are currently:

- A date: A signed four-to-six digit year, two digit month and two digit day, optionally separated by `-` characters. Examples: "19700101", "-0004-12-24", "81030-04-01".
- An optional time part, separated from the date by either `T` or a space. The time part is a two digit hour, then optionally a two digit minutes value, then optionally a two digit seconds value, and then optionally a '.' followed by a one-to-six digit second fraction. The minutes and seconds may be separated from the previous parts by a ':'. Examples: "12", "12:30:24.124", "123010.50".
- An optional time-zone offset part, possibly separated from the previous by a space. The time zone is either 'z' or 'Z', or it is a signed two digit hour part and an optional two digit minute part. The sign must be either "+" or "-", and can not be omitted. The minutes may be separated from the hours by a ':'. Examples: "Z", "-10", "01:30", "1130".

This includes the output of both toString and toIso8601String, which will be parsed back into a `DateTime` object with the same time as the original.

The result is always in either local time or UTC. If a time zone offset other than UTC is specified, the time is converted to the equivalent UTC time.

Examples of accepted strings:

- `"2012-02-27 13:27:00"`
- `"2012-02-27 13:27:00.123456z"`
- `"20120227 13:27:00"`
- `"20120227T132700"`
- `"20120227"`
- `"+20120227"`
- `"2012-02-27T14Z"`
- `"2012-02-27T14+00:00"`
- `"-123450101 00:00:00 Z"`: in the year -12345.
- `"2002-02-27T14:00:00-0500"`: Same as `"2002-02-27T19:00:00Z"`

## Implementation

    // TODO(lrn): restrict incorrect values like  2003-02-29T50:70:80.
    // Or not, that may be a breaking change.
    static DateTime parse(String formattedString) {
      var re = _parseFormat;
      Match match = re.firstMatch(formattedString);
      if (match != null) {
        int parseIntOrZero(String matched) {
          if (matched == null) return 0;
          return int.parse(matched);
        }

        // Parses fractional second digits of '.(\d{1,6})' into the combined
        // microseconds.
        int parseMilliAndMicroseconds(String matched) {
          if (matched == null) return 0;
          int length = matched.length;
          assert(length >= 1);
          assert(length <= 6);

          int result = 0;
          for (int i = 0; i < 6; i++) {
            result *= 10;
            if (i < matched.length) {
              result += matched.codeUnitAt(i) ^ 0x30;
            }
          }
          return result;
        }

        int years = int.parse(match[1]);
        int month = int.parse(match[2]);
        int day = int.parse(match[3]);
        int hour = parseIntOrZero(match[4]);
        int minute = parseIntOrZero(match[5]);
        int second = parseIntOrZero(match[6]);
        bool addOneMillisecond = false;
        int milliAndMicroseconds = parseMilliAndMicroseconds(match[7]);
        int millisecond =
            milliAndMicroseconds ~/ Duration.microsecondsPerMillisecond;
        int microsecond =
            milliAndMicroseconds.remainder(Duration.microsecondsPerMillisecond);
        bool isUtc = false;
        if (match[8] != null) {
          // timezone part
          isUtc = true;
          if (match[9] != null) {
            // timezone other than 'Z' and 'z'.
            int sign = (match[9] == '-') ? -1 : 1;
            int hourDifference = int.parse(match[10]);
            int minuteDifference = parseIntOrZero(match[11]);
            minuteDifference += 60 * hourDifference;
            minute -= sign * minuteDifference;
          }
        }
        int value = _brokenDownDateToValue(years, month, day, hour, minute,
            second, millisecond, microsecond, isUtc);
        if (value == null) {
          throw new FormatException("Time out of range", formattedString);
        }
        return new DateTime._withValue(value, isUtc: isUtc);
      } else {
        throw new FormatException("Invalid date format", formattedString);
      }
    }