Correction to my above summary: bitcoind does use gmtime to get the correct UTC time, but the problem was that Windows still tries to put the local timezone for %Z rather than UTC as is being encoded.
Actually, according to the RFC, numeric timezones should be used (not names). So rather than force TZ to UTC, the buffer should be extended and %z used instead of %Z. I do not have any idea if Windows complies with %z better than %Z, so I am leaving the temporarily-set-TZ hack in. Otherwise, my branch now uses %z.
Please note that the timezone is not the only issue here. The locale must also be forced to POSIX to get the usual weekday (Sun-Sat) and month (Jan-Dec) abbreviations, rather than some local variant.