def parse_line(self, text):
        """
        Parse the given `text` and return either a :class:`~taxi.timesheet.lines.DateLine`, an
        :class:`~taxi.timesheet.lines.Entry`, or a :class:`~taxi.timesheet.lines.TextLine`, or raise
        :exc:`taxi.exceptions.ParseError` if the line can't be parser. See the transformation methods
        :meth:`create_date_from_text` and :meth:`create_entry_line_from_text` for details about the format the line is
        expected to have.
        """
        text = text.strip().replace('\t', ' ' * 4)

        # The logic is: if the line starts with a #, consider it's a comment (TextLine), otherwise try to parse it as a
        # date and if this fails, try to parse it as an entry. If this fails too, the line is not valid
        if len(text) == 0 or text.startswith('#'):
            parsed_line = TextLine(text)
        else:
            try:
                date = self.create_date_from_text(text)
            except ValueError:
                parsed_line = self.create_entry_line_from_text(text)
            else:
                parsed_line = DateLine(date, text)

        return parsed_line