This bug continues to exist in 5.3.2RC2.
DateTime::diff() / date_diff() chokes on dates starting in January if the interval is greater than 28 days (during non-leap years).
It is happening because of a bug in do_range_limit_days_relative() in ext/date/lib/tm2unixtime.c. At the end of the function if *d > days_next_month, the code subtracts the days and adds a month. So when the starting month is January, the days_next_month is 28 or 29, mistakenly triggering the month/day swapping behavior.
Patch:
http://www.analysisandsolutions.com/php/bug49081.diff
Test:
http://www.analysisandsolutions.com/php/bug49081.phpt

Here is an updated patch against PHP_5_3. It removes all of the "next_month" code in
do_range_limit_days_relative().
http://www.analysisandsolutions.com/php/bug49081v2.53.diff
As with the earlier patch, PHP built fine with it and all of the ext/date tests that passed under
the unpached PHP_5_3 build continued to pass under the patched version.
Grepping the entire PHP_5_3 code base indicates the only place do_range_limit_days_relative() gets
called is in timelib_do_rel_normalize(), and the only place that gets called is timelib_diff().
It is unclear what purpose the "next_month" functionality served. Perhaps it was there in case the
"base_y" and "base_m" parameters were later than the "y"/"m"/"d" parameters? But that doesn't apply
becausetimelib_diff() always passes the earlier date to timelib_do_rel_normalize() as "one" and on to
do_range_limit_days_relative() as "base_*".

This bug has been fixed in SVN.
Snapshots of the sources are packaged every three hours; this change
will be in the next snapshot. You can grab the snapshot at
http://snaps.php.net/.
Thank you for the report, and for helping us make PHP better.