Perform a Pluto flyby
JavaScript (ES6), 237 bytes

f=(n)=&gt;(t=new Date('201'+n[3],n[4]+n[5],n[6]+n[7])/864e5-403805/24,r=484/(t*t+10),(g=(i)=&gt;(++i&lt;8?(h=(j)=&gt;(i*i+j*j&lt;=r?r&gt;30.25&amp;!~i&amp;&amp;'(^_^)'[j+3]||'#':~'p-3-5p62p-56p21p7-2'.indexOf('p'+j+i)?'.':' ')+(++j&lt;8?h(j):''))(-7)+'\n'+g(i):''))(-8))


Live demo. Run in Firefox.

Original version

f=function(n) {
    t = (new Date('201'+n[3],''+n[4]+n[5],''+n[6]+n[7]) // Find the time difference in milliseconds,
    - new Date(2015,12,25)) / 864e5;                    // then divide by 86400000 to convert to days.

    r=22 / Math.sqrt(t*t+10);                           // Calculate the radius.

    s=[]; // s is the array that contains each line as a string.

    for(i=-7;i&lt;8;i++)               // Loop through rows.
        for(j=-7,s[i+7]='';j&lt;8;j++) // Loop through columns, appending one character per column.
                                    // s is zero based, so add 7 to the row.
            s[i+7]+=i*i+j*j&lt;=r*r ?  // Choose which character to add to s. 
            (r&gt;5.5&amp;i==-1&amp;&amp;'(^_^)'[j+3]||'#') :  // Add a '#' if the position is inside the radius.
                                                // If distance &lt; 4, then the radius &gt; 5.5
                                                // Then add the face at the right position.
            {'-3-5':1,'62':1,'-56':1,'21':1,'7-2':1} // Add the stars if outside. Create an associative array.
            [j+''+i]?'.':' ';                        // If i concat j is in the array, the expression will be 1, 
                                                     // which is truthy, else it will be undefined, which is falsey.
    return s.join`\n` // Join all the rows with a new-line.
}


Golfing

This was fun to golf.

I don't need to create a Date object, so I hardcoded the value in milliseconds to save 13 bytes:

t=(new Date('201'+n[3],n[4]+n[5],n[6]+n[7])-new Date(2015,12,25))/864e5 // Before
t=new Date('201'+n[3],n[4]+n[5],n[6]+n[7])/864e5-403805/24 // After


Replace the associative array with a delimited string to eliminate 9 bytes:

{'-3-5':1,'62':1,'-56':1,'21':1,'7-2':1}[j+''+i]?'.':' ' // Before
~'p-3-5p62p-56p21p7-2'.indexOf('p'+j+i)?'.':' ' // After


The biggest refactor was replacing the for loops with nested, recursive IIFEs to knock off 10 bytes:

s=[];for(i=-7;i&lt;8;i++)for(j=-7,s[i+7]='';j&lt;8;j++)s[i+7]+= /* Chooses char at i,j */ ;return s.join`\n` // Before
(g=(i)=&gt;(++i&lt;8?(h=(j)=&gt;( /* Chooses char at i,j */ )+(++j&lt;8?h(j):''))(-7)+'\n'+g(i):''))(-8) // After


I also got rid of Math.sqrt for 8 more bytes.

r=22/Math.sqrt(t*t+10),(g=(i)=&gt;(++i&lt;8?(h=(j)=&gt;(i*i+j*j&lt;=r*r?r&gt;5.5 // Before
r=484/(t*t+10),(g=(i)=&gt;(++i&lt;8?(h=(j)=&gt;(i*i+j*j&lt;=r?r&gt;30.25 // After


Issues

I could only get the correct photograph for the test cases by changing the closest date to 2015/12/24, and I don't know if the problem lies in my code or the question. Please clarify and I will update my answer.

Here is my output using the differences from 2015/12/25.

Edit: Updated answer to use Christmas as the closest date.

Photograph for "20151215":

                   

        .          


           #      .
          ###      
         #####     
          ###.     
           #     . 



      .            
                   

Photograph for "20151225":

                   
        #######    
       #########   
      ###########  
     ############# 
     #############.
     ###(^_^)##### 
     ############# 
     ############# 
     ############# 
     ############# 
      ###########  
       #########   
      . #######