class ActiveSupport::Duration::ISO8601Parser

def parse!

def parse!
  while !finished?
    case mode
      when :start
        if scan(SIGN_MARKER)
          self.sign = (scanner.matched == '-') ? -1 : 1
          self.mode = :sign
        else
          raise_parsing_error
        end
      when :sign
        if scan(DATE_MARKER)
          self.mode = :date
        else
          raise_parsing_error
        end
      when :date
        if scan(TIME_MARKER)
          self.mode = :time
        elsif scan(DATE_COMPONENT)
          parts[DATE_TO_PART[scanner[2]]] = number * sign
        else
          raise_parsing_error
        end
      when :time
        if scan(TIME_COMPONENT)
          parts[TIME_TO_PART[scanner[2]]] = number * sign
        else
          raise_parsing_error
        end
    end
  end
  validate!
  parts
end