this part irrelevant - question was edited
Because of the timezone difference. $start is calculated in the 'Rainy River timezone', while $middle and $end are in UTC time. The 'Rainy River timezone has a -06:00 hour offset from UTC (exactly the difference in hours between the first with the second and third results).
update 1 - solution
It seems the problem lies somewhere around strtotime. For some reason it yields a result with an offset of one day (further explanation needed). A simple solution, is to subtract one second from that date and it will produce the correct result.
$timezone = new DateTimeZone('UTC');
$start = new DateTime('0:00 first day of previous month', $timezone );
$middle = DateTime::createFromFormat('U', strtotime('first day of last month',($start ->format('U'))-1),$timezone);
echo $middle->format('Y-m-d')."\n";
Result:
2013-05-01
update 2 - reason for problem
Eventually I find out that the problem originates from the instantiation of the fisrt date object. Here is an illustration.
This will give a correct result:
$original = new DateTime('2013-05-01');
echo $original->format('Y-m-d')."\n";
$previous= DateTime::createFromFormat('U', strtotime('first day of last month',($original->format('U'))),new DateTimeZone('UTC'));
echo $previous->format('Y-m-d')."\n";
Result (OK):
2013-05-01
2013-04-01 <--- OK
However, this will not (only first line different, as in the original code):
$original = new DateTime('0:00 first day of previous month', new DateTimeZone('UTC'));
echo $original->format('Y-m-d')."\n";
$previous= DateTime::createFromFormat('U', strtotime('first day of last month',($original->format('U'))),new DateTimeZone('UTC'));
echo $previous->format('Y-m-d')."\n";
Result:
2013-07-01
2013-05-02 <--- BAD