Q:

Why does this insert to SQL Server fail when using file Mtime (PHP), but not when using Ctime?

I am attempting to walk a directory (using PHP) and get the modified and created time of the files, updating or inserting as needed to an SQL Server 2003 table. 
I am using PHP's DirectoryIterator in order to do this, and it works flawlessly if I only use the object's getCTime() function. If I move to include or instead use the objects getMTime() method, SQL Server throws out an error at me on insert/update: 

22003 : [Microsoft][SQL Server Native Client 10.0][SQL Server]Arithmetic overflow error converting expression to data type smalldatetime.

This error ONLY occurs when using the object getMTime() method. Testdir has two files in it, solely for testing obviously.
I have searched for help with this via Google, and especially on Stackoverflow (One, Two, Three). Those StackOverflow questions are for a SELECT statement however, and say to use CONVERT function of SQL. The only semi-relevant item I have found was a blog post which says to ensure the SQL user has the default language set appropriately. In my user case, it is set properly to 'English'. 
Here is the entire function and subsequent call:
function fillArrayWithFileNodes( DirectoryIterator $dir )
{
  $data = array();
  require('connecttodbfile');
  clearstatcache();

  foreach ( $dir as $node )
  {
    if ( $node->isDir() && !$node->isDot() )
    {
      $data[$node->getFilename()] = fillArrayWithFileNodes( new DirectoryIterator( $node->getPathname() ) );
    }
    else if ( $node->isFile() )
    {

        $filename = $node->getFilename();
        //Comment this out below and use CTime, Update works!

        //$file_time = date('Y-d-m H:i:s', $node->getMTime());

        //Comment this out and use MTime, Update DOES NOT WORK!
        $file_time = date('Y-d-m H:i:s', $node->getCTime()); 

        //Debug here, make sure I'm getting expected values 

        echo sprintf("Mtime (%s): %s - %s<br />Ctime (%s):  %s - %s<br /> <br />", gettype($node->getMTime()), $node->getMTime(), gettype($node->getMTime()), date('Y-d-m H:i:s', $node->getMTime()), $node->getCTime(), date('Y-d-m H:i:s', $node->getCTime()));

        $data[] = array('time'=>$file_time);

        try {

        $sQuery = <<<EOD
BEGIN TRAN
UPDATE files SET file_time=:ftime WHERE file_name=:fname

IF @@ROWCOUNT = 0 and @@ERROR = 0
   BEGIN
    INSERT INTO files (file_name,file_time) VALUES (:f_name, :f_time)
   END
COMMIT TRAN
EOD;

        $statm = $conn->prepare($sQuery);

        //PDO doesn't like it if we name repeat variables the same. So even if you use the same variable more than once in your query, PDO says you need the exact number of variables in the execute array as is in your statement, all unique names.

        $statm->execute(array(':ftime'=> $file_time, ':fname'=>$filename,':f_time'=> $file_time, ':f_name'=>$filename));

    } catch(PDOException $err) {//SQL got mad at us. Figure out why.
        echo $statm->errorCode() . " : ";
        $error = $statm->errorInfo();
        print_r( $error[2]);
        exit(1);
     }
    }
  }
  return $data;
}

$fileData = fillArrayWithFileNodes( new DirectoryIterator( 'C:\testdir' ) );

echo "<pre>";

print_r($fileData);

echo "</pre>";

When this code is run with mtime as the $file_time (through web browser) I get the following output:
Mtime (integer): 1311599068 - 2011-25-07 08:04:28 
Ctime (integer): 1346941012 - 2012-06-09 09:16:52

22003 : [Microsoft][SQL Server Native Client 10.0][SQL Server]Arithmetic overflow error converting expression to data type smalldatetime.

If I change out $file_time to use getCTime() instead, the output completes with no errors:
Mtime (integer): 1311599068 - 2011-25-07 08:04:28 
Ctime (integer): 1346941012 - 2012-06-09 09:16:52
Mtime (integer): 1265983000 - 2010-12-02 07:56:40 
Ctime (integer): 1346941018 - 2012-06-09 09:16:58

Array (
    [0] => Array
        (
            [time] => 2012-06-09 09:16:52
        )

    [1] => Array
        (
            [time] => 2012-06-09 09:16:58
        )

)

Even if that method specified in the StackOverflow question (linked above) work to have both cases of mtime and ctime upload properly, my question is still Why does using ctime work without any modification but mtime does not?

A:

Because SQL Server wants YYYY-MM-DD and in your case, your are sending YYYY-DD-MM.
mdate gives you 2011-25-07, which isn't a valid date for YYYY-MM-DD, as 25 is not a valid month.  It's just by chance that cdate is working because it's returning 2012-06-09 and 06 is a valid month.  You either need to change your formatting or change the date localization on the server.

