tl;dr
OffsetDateTime
.parse(
"2020-12-16T19:20:30+01:00 UTC"
.replace( " UTC" , "" )
)
.withZoneSameInstant(
ZoneId.of( "America/Edmonton" )
)
ISO 8601
Your input string:
2020-12-16T19:20:30+01:00 UTC
… nearly complies with the ISO 8601 standard for data-exchange date-time formats. To fully comply, delete the SPACE and UTC from the end. The +01:00 at the end means “one hour ahead of UTC", so the UTC at the end is redundant.
String input = "2020-12-16T19:20:30+01:00 UTC".replace( " UTC" , "" ) ;
Offset versus time zone
Parse as an OffsetDateTime because your input indicates small offset from UTC, not a time zone.
An offset is merely a number of hours-minutes-seconds ahead/behind the prime meridian of UTC. A time zone is much more. A time zone is a history of the past, present, and future changes to the offset used by the people of a particular region as decided by their politicians. A time zone has a name in format of Continent/Region, such as Europe/Paris and Africa/Tunis.
OffsetDateTime
So the other Answer’s suggestion to use ZonedDateTime for parsing is misguided as no time zone is indicated. Your input has only an offset, therefore use OffsetDateTime.
No need to specify a formatting pattern. Our modified input complies with ISO 8601, and the java.time classes use those standard formats by default when parsing/generating strings.
OffsetDateTime odt = OffsetDateTime.parse( input ) ;
LocalDateTime
You asked how to get a LocalDateTime. That class lacks any concept of offset or time zone. So beware, if you convert from OffsetDateTime, you are discarding valuable information.
So while I don’t recommend doing this, here is the code.
LocalDateTime ldt = odt.toLocalDateTime() ;
ZonedDateTime
You asked how to adjust into a time zone.
To adjust from our offset to a time zone, merely specify the desired time zone.
ZoneId z = ZoneId.of( "Asia/Tokyo" ) ;
ZonedDateTime zdt = odt.withZoneSameInstant( z ) ;