from datetime import datetime


def calc_date_params(backdate, setdate):
    """
    Returns the calculated date given user's request

    Tests frequently need to mock times, this returns the calculated time,
    either by adjusting from utcnow (via backdate), using the given value
    (in setdate) or using the value of now if neither of those are available.

    :param backdate: a relative timedelta to move from now
    :param setdate: a specific datetime value
    :return: best date given parameters

    """
    if setdate and backdate:
        raise ValueError("set ONE, `backdate` OR `setdate`")

    if setdate:
        acceptance_date = setdate
    elif backdate:
        # Guard against associative problems with backdating by
        # months.
        if backdate.months:
            raise ValueError(
                "moving dates by month values is non-associative; use"
                "`associative_backdate` and pass in `setdate` param")
        acceptance_date = datetime.utcnow() - backdate
    else:
        acceptance_date = datetime.utcnow()
    return acceptance_date