Created attachment 166294 [details]
% date -j -f %Y-%m 2015-02 '+%B %Y'
In the code, a tm structure is initially created with the current time. If input_fmt and new_date are supplied, then the appropriate values in that tm structure are overwritten. The problem is that this can lead to invalid dates when only a partial input_fmt/new_date are supplied like above. In the example above, the tm_mday is left as is (today is the 29th day of the month), but the tm_mon is overwritten with 01 (February) leading to an invalid date.
The attached patch fixes the above issue by setting the default tm_mday to 1, when an input_fmt is supplied.
The behaviour is indeed strange, but I don't think resetting the day of the month to 1 whenever -j and -f are used together is correct. Commands like date -j -f %H:%M:%S 00:00:00 should still print midnight of the current day, not of the first of the month. Likewise, the date(1) man page (by referring to strftime(3)) seems to suggest that nonexistent days like 30 February are converted to something in March.
You can specify the day of the month (%d) as 1 in your script.
(In reply to Jilles Tjoelker from comment #1)
The fixed first day of the month should only have an effect if the user doesn't specify a day. I don't think this is any less arbitrary than using the current day of the month when the user doesn't specify one. The only difference is that using the first day doesn't produce the strange behaviour.
I replied too quickly and I see what you are saying and it makes sense.