from datetime import datetime
from typing import Union


def time_diff(end_time: datetime, start_time: datetime, as_type: str = 'string') -> Union[tuple, str]:
    """Computes the difference between two datetimes and returns it in hours, minutes, seconds and microseconds

    Args:
        end_time: endtime of the operation
        start_time: starttime of the operation
        as_type: whether to return as a parsed string or as a tuple

    Returns:
        Tuple or String: Difference of time as (hours, minutes, seconds, microseconds) or
            "[hours}h {minutes}m {seconds}s {microseconds}μs"

    Examples:
        >>> start_time = datetime(2021, 4, 17, 23, 11, 22, 829688)
        >>> end_time = datetime(2021, 4, 18, 18, 15, 22, 100)
        >>> time_diff(end_time, start_time)
        '19h 3m 59s 170412μs'

        >>> time_diff(end_time, start_time, as_type='tuple')
        (19, 3, 59, 170412)
    """
    t_diff = (end_time - start_time).total_seconds()

    # convert anything above hours into hours
    hours, rem = int(t_diff // 3600), t_diff % 3600
    minutes, rem = int(rem // 60), rem % 60
    seconds = int(rem)
    microseconds = int(round((rem - seconds) * 1e6))

    return (hours, minutes, seconds, microseconds) if as_type == 'tuple' else \
        f'{hours}h {minutes}m {seconds}s {microseconds}\u03BCs'