Ordering an un-ambiguous scrambled date A date is un-ambiguous when each number may be
    decided to be day or month or year given the range
    limitation of these numbers.

For example


\$14\$ cannot be a month number
\$2008\$ cannot be a day number


@param un_ambiguous_date: an un-ambiguous scrambled date,
    of the format X/Y/Z where X, Y, Z correspond to
    day, month, year but not necessarily in this order.

@return The date in the order 'DAY/MONTH/YEAR'.

I am particularly interested in full input validation and nice error producing, so tell me any lack of clarity/corner case missed.

For example usage see the doctests included with the function:

def order_date(un_ambiguous_date):
    """
    @param un_ambiguous_date: an un-ambiguous scrambled date,
    of the format X/Y/Z where X, Y, Z correspond to
    day, month, year but not necessarily in this order.

    @return: The date in the order 'DAY/MONTH/YEAR'.

    A date is un-ambiguous when each number may be
    decided to be day or month or year given the range
    limitation of this numbers.
    (For example 14 cannot be a month number, and
    2008 cannot be a day number)

    &gt;&gt;&gt; order_date('3/2015/13')
    '13/3/2015'

    &gt;&gt;&gt; order_date('2012/20/4')
    '20/4/2012'

    # Here both 3/4/1000 and 4/3/1000 are possible.
    &gt;&gt;&gt; order_date('3/4/1000')
    Traceback (most recent call last):
    ...
    ValueError: Ambiguous date was given

    &gt;&gt;&gt; order_date('3/3/2050')
    '3/3/2050'

    &gt;&gt;&gt; order_date('1/1/1')
    Traceback (most recent call last):
    ...
    ValueError: The date cannot be valid

    &gt;&gt;&gt; order_date('12/6')
    Traceback (most recent call last):
    ...
    ValueError: The date is too short, format should be X/Y/Z

    &gt;&gt;&gt; order_date('2000/2000')
    Traceback (most recent call last):
    ...
    ValueError: The date is too short, format should be X/Y/Z

    &gt;&gt;&gt; order_date('Foo/Bar/Baz')
    Traceback (most recent call last):
    ...
    TypeError: The date should be made up of '/' separated INTEGERS

    """
    try:
        x, y, z = un_ambiguous_date.split('/')
    except ValueError:
        raise ValueError("The date is too short, format should be X/Y/Z")

    try:
        x, y, z = map(int, (x, y, z))
    except ValueError:
        raise TypeError("The date should be made up of '/' separated INTEGERS")

    day = [i for i in (x,y,z) if i &lt; 31]
    month = list(set(i for i in (x,y,z) if i &lt; 12))
    year = [i for i in (x,y,z) if i &gt; 31]
    day = list(set(day) - set(month))
    if not day:
        day = month
    # print(day, month, year)
    if any(len(x) &gt; 1 for x in (day, month, year)):
        raise ValueError("Ambiguous date was given")
    try:
        return '/'.join(map(str, (day[0], month[0], year[0])))
    except IndexError:
        raise ValueError("The date cannot be valid")
Wrong bounds

Your filters on your day/month aren't right:

day = [i for i in (x,y,z) if i &lt; 31]
month = list(set(i for i in (x,y,z) if i &lt; 12))


31 is a valid day and 12 is a valid month, so those should be &lt;=. Additionally, you're not excluding negative numbers - so you'll want 1 &lt;= i &lt;= 31 for the first filter and 1 &lt;= i &lt;= 12 for the second.

Dealing with the tuple

Since just about everywhere you deal with (x,y,z) as a tuple, I would just keep it as a tuple the whole way and not unpack it. You only unpack it to check the length, so we can just make that check explicit. Also, if I passed in something like 1/2/3/4/5, you'd tell me that my date was too short, so this can get both right:

elems = un_ambiguous_date.split('/')
if len(elems) != 3:
    raise ValueError("The date is too {}, format should be X/Y/Z".format(
        'short' if len(elems) &lt; 3 else 'long'))

try:
    elems = map(int, elems)
except ValueError:
    raise ...

day = [i for i in elems if 1 &lt;= i &lt;= 31]    
# etc.


The last join

Instead of:

return '/'.join(map(str, (day[0], month[0], year[0])))


I would just use format:

return '{}/{}/{}'.format(day[0], month[0], year[0])


It's shorter and more readable. 

Combine the last two checks

I would write a helper function that returns the first element of a single-element list:

def front(lst):
    if not lst:
        raise ValueError("The date cannot be valid")
    if len(lst) &gt; 1:
        raise ValueError("Ambiguous date was given")

    return lst[0]


And then you can just write:

return '{}/{}/{}'.format(front(day), front(month), front(year))