Days and months make years Today's date is quite an interesting one. Let's take a look at why. The date 07/12/2017 (in DD/MM/YYYY date format) can be split into the year (2017) and the rest (07/12). You may notice that the digits in the year can be rearranged to match the digits in the rest of the date, which is the basis of this challenge.
The task
Given an valid integer (e.g. no leading zeros) representing a year, consisting of exactly four digits, output all unique possible valid dates that can be made from those digits. You may take the number as a list of digits, or a string representing the input if you want. Each number in the input must be used exactly once in each of the final outputs. As leading 0s aren't used in integers, the input will be in the range 1000 &lt;= input &lt;= 9999.
A valid date is one in which the date exists on the Gregorian Calendar, such as 17/05/2000. The only corner case is February 29th, which is only a valid date when the year is a leap year. You can (but don't have to) assume that leap years are years that are divisible by 4.
You have to output a separator between the day and the month (e.g. /) and a different separator between different dates. You may optionally output the year with each date, but this must be consistent between dates.
Finally, you may choose between the date format order, i.e. you can output as any of DD/MM/YYYY, MM/DD/YYYY etc. but leading 0s are required when the input contains at least one 0.
Essentially, you may output in any obviously understandable format, such as an array of strings, one concatenated string etc.
This is a code-golf so shortest code wins!
Test cases
input
outputs

2017
07/12, 12/07, 17/02, 21/07, 27/01, 27/10

2092
22/09, 29/02

2029
22/09

1000
Nothing

8502
25/08, 28/05

Reference Implementation
Japt, 31 30 26 24 23 22 17 bytes
Locale dependent. Outputs a 2D-array of the format [[&quot;MM&quot;,&quot;DD&quot;],...].
á â mò fÈÎ-ÐNcX)Î

Try it or Try It Online! (to avoid the locale dependency)
Explanation
If it wasn't for JavaScript's Date object wrapping invalid dates, I'd be able to get this down to about 20 18 16 bytes. Even when providing its argument as a single string, which the spec says shouldn't lead to wrapping, dates up to 31 still do for months that don't have 31 days. However, as the month's can only wrap over by one, we can take advantage of the fact that string arguments use 1-based months to simply filter by subtraction - if the month rolls over then the result of that subtraction will be 0.
á â mò fÈÎ-ÐNcX)Î     :Implicit input of N=[U=&quot;YYYY&quot;]
á                     :Permutations of U
  â                   :Deduplicate
    m                 :Map
     ò                :  Partitions of length 2 (=[[&quot;MM&quot;,&quot;DD&quot;],...])
       f              :Filter
        È             :By passing each X through the following function
         Î            :  First element of X
          -           :  Subtract
           Ð          :  Create new Date from
            NcX       :    N concatenated with X (=[&quot;YYYY&quot;,&quot;MM&quot;,&quot;DD&quot;], which gets coerced to &quot;YYYY-MM-DD&quot;, with MM being 1-based)
               )      :  End date creation
                Î     :  0-based month (=NaN for invalid dates, n-NaN=NaN)


Original, 22 bytes
Preserving this, 'cause I really liked the setwise union trick.
á
â¡ÐNcXòÃfÈÎ-2îUvÃms7

Try it (footer formats the output to match the examples in the challenge)Or Try it online! to somewhat mitigate the locale dependency - TIO's locale doesn't include leading 0s for dates &amp; months, so they're added back in in the footer.
Explanation
á\nâ¡ÐNcXòÃfÈÎ-2îUvÃms7     :Implicit input of N=[U=&quot;YYYY&quot;]
á                           :Permutations of U
 \n                         :Reassign to U, leaving the value in N unchanged
   â                        :Setwise union with
    ¡                       :Map each X in U
     Ð                      :  New Date from
      Nc                    :  N concatenated with
        Xò                  :  Partitions of X of length 2 (=[&quot;YYYY&quot;,&quot;MM&quot;,&quot;DD&quot;], which gets coerced to &quot;YYYY-MM-DD&quot;, with MM being 1-based)
          Ã                 :End map
           f                :Filter by
            È               :Passing each through the following function
             Î              :  Get 0-based month (=NaN for invalid date)
              -             :  Subtract (NaN-n=NaN)
               2î           :  First 2 characters of
                 Uv         :  Remove and return first element of U
                   Ã        :End filter
                    m       :Map
                     s7     :  To locale date string (=&quot;DD/MM/YYYY&quot;)

The reason the setwise union doesn't include any elements from the first array is because v modifies that array so the filter ends up removing all elements from it.
In the 16 byte version, which assumes a way to avoid dates wrapping over, we don't need to reassign the array of possible dates to U and instead filter by using Í to try to subtract the timestamp from 2, which will result in NaN if the date is invalid. We can't use the setwise union trick, though, so â get tacked on the end to deduplicate the final array.