def parse(value, preserve_original_tz=False):
    """
    Parse a date string and return a time-zone aware datetime object.

    :param value: Date in ISO8601 format.
    :type value: ``str``

    :param preserve_original_tz: True to preserve the original timezone - by default result is
                                 converted into UTC.
    :type preserve_original_tz: ``boolean``

    :rtype: ``datetime.datetime``
    """
    # We use ciso8601 since it's much faster than non-C alternatives
    # For compatibility reasons we still fall back to datetutil, but this should rarely happen
    # rfc3339 covers 90% of the iso8601 (it's a subset of it)
    original_value = value

    try:
        dt = ciso8601.parse_datetime(str(value))
    except Exception:
        dt = dateutil.parser.parse(str(original_value))

    if not dt.tzinfo:
        dt = add_utc_tz(dt)

    if not preserve_original_tz:
        dt = convert_to_utc(dt)

    return dt

    Parse a date string and return a time-zone aware datetime object.

    :param value: Date in ISO8601 format.
    :type value: ``str``

    :param preserve_original_tz: True to preserve the original timezone - by default result is
                                 converted into UTC.
    :type preserve_original_tz: ``boolean``

    :rtype: ``datetime.datetime``
    
st2common/st2common/util/date.py