import math


def _convert_julian_day(julian_day, mode="julian"):
    """Converts a Julian Day number to its (proleptic) Julian or Gregorian calendar equivalent

    Adapted from: https://en.wikipedia.org/wiki/Julian_day#Julian_or_Gregorian_calendar_from_Julian_day_number

    Note that the algorithm is only valid for Julian Day numbers greater than or
    equal to zero. Negative arguments for julian_day will raise a ValueError.

    Args:
        julian_day (int): Julian Day number to convert, must be greater than or
            equal to 0
        mode (str): The target calendar to convert to, either 'julian' or
            'gregorian'. Defaults to 'julian'.

    Returns:
        A (day, month, year) tuple representing the day, month, and year in the
            target calendar.
    """
    if julian_day < 0:
        raise ValueError(
            "Algorithm only valid for Julian Day greater than or equal to zero"
        )
    julian_day = math.ceil(julian_day)

    # algorithm parameters
    y = 4716
    j = 1401
    m = 2
    n = 12
    r = 4
    p = 1461
    v = 3
    u = 5
    s = 153
    w = 2
    B = 274277
    C = -38

    # intermediate calculations
    if mode == "julian":
        f = julian_day + j
    elif mode == "gregorian":
        f = julian_day + j + (((4 * julian_day + B) // 146097) * 3) // 4 + C
    else:
        raise ValueError("Unrecognized mode - supports 'julian' or 'gregorian'")

    e = r * f + v
    g = (e % p) // r
    h = u * g + w

    day = (h % s) // u + 1  # day in target calendar
    month = ((h // s + m) % n) + 1  # month in target calendar
    year = (e // p) - y + ((n + m - month) // n)  # year in target calendar

    return day, month, year