There are some options.
First, as you say, inserting a colon in zone offset is not that difficult. After you’ve done that, getting a ZonedDateTime is straightforward:
ZonedDateTime zdt = ZonedDateTime.parse("2017-01-11T09:38:41+01:00");
System.out.println(zdt);
This prints:
2017-01-11T09:38:41+01:00
Alternatively, funnily, while ZonedDateTime.parse(String) needs a colon in the offset, ZoneId.of() does not, so you may split off the offset and do:
ZoneId zi = ZoneId.of("+0100");
LocalDateTime ldt = LocalDateTime.parse("2017-01-11T09:38:41");
ZonedDateTime zdt = ldt.atZone(zi);
The result is the same as before.
If you prefer not to modify your string prior to parsing it, there is also:
DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ssZ");
ZonedDateTime zdt = ZonedDateTime.parse("2017-01-11T09:38:41+0100", dtf);
Also this gives the same result.
Edit: Note: I am using ZonedDateTime since you asked for this in your question. You may consider it more correct to use OffsetDateTime. Most of the code is practically the same. The version that splits off the offset would go like this:
ZoneOffset zo = ZoneOffset.of("+0100");
LocalDateTime ldt = LocalDateTime.parse("2017-01-11T09:38:41");
OffsetDateTime odt = ldt.atOffset(zo);
To convert to UTC, as mentioned at end of Question, apply another ZoneOffset, the constant ZoneOffset.UTC.
OffsetDateTime odtUtc = odt.withOffsetSameInstant( ZoneOffset.UTC );