You can and maybe have to use a LocalDateTime in order to achieve what you want, but the final product should be a ZonedDateTime.
Basically, the timestamp should be converted to a LocalDateTime and that LocalDateTime can then be converted to a ZonedDateTime by adding a specific ZoneId, like this:
Just adding a zone, leaving the datetime as is:
public static void main(String[] args) {
// get or take a timestamp
java.sql.Timestamp timestamp = Timestamp.valueOf("2020-03-12 03:01:45.0");
// transforming it into a LocalDateTime
LocalDateTime localDateTime = timestamp.toLocalDateTime();
// now create a ZonedDateTime by putting a zone
ZonedDateTime zonedDateTime = ZonedDateTime.of(localDateTime,
ZoneId.of("America/Sao_Paulo"));
// and print the result
System.out.println(zonedDateTime);
}
The output is
2020-03-12T03:01:45-03:00[America/Sao_Paulo]
If you are sure the client that runs this code always has the desired time zone, then you can alternatively use ZoneId.systemDefault() when the ZonedDateTime is being created.
But if you don't just want to add a zone but really convert the Instant to another zone, then you can do this:
Converting the Instant to another time zone:
public static void main(String[] args) {
// get or take a timestamp
java.sql.Timestamp timestamp = Timestamp.valueOf("2020-03-12 03:01:45.0");
// transforming it into a LocalDateTime
LocalDateTime localDateTime = timestamp.toLocalDateTime();
// now create a ZonedDateTime by putting a zone
ZonedDateTime zonedDateTime = ZonedDateTime.ofInstant(
localDateTime.toInstant(ZoneOffset.of("+00:00")),
ZoneId.of("America/Sao_Paulo"));
// and print the result
System.out.println(zonedDateTime);
}
This outputs
2020-03-12T00:01:45-03:00[America/Sao_Paulo]
You can have the second one shorter:
public static void main(String[] args) {
// get or take a timestamp
java.sql.Timestamp timestamp = Timestamp.valueOf("2020-03-12 03:01:45.0");
// transforming it into a LocalDateTime
ZonedDateTime utc = ZonedDateTime.of(timestamp.toLocalDateTime(), ZoneId.of("UTC"));
// now create a ZonedDateTime by putting a zone
ZonedDateTime saoPaulo = utc.withZoneSameInstant(ZoneId.of("America/Sao_Paulo"));
// and print the result
System.out.println(saoPaulo);
}
The output stays
2020-03-12T00:01:45-03:00[America/Sao_Paulo]
If you want the output formatted differently, you have to either choose one of the built-in patterns (public constants of DateTimeFormatter, like DateTimeFormatter.ISO_ZONED_DATE_TIME) or give it a custom one (by DateTimeFormatter.ofPattern(String pattern) plus an optional Locale):
public static void main(String[] args) {
// get or take a timestamp
java.sql.Timestamp timestamp = Timestamp.valueOf("2020-03-12 03:01:45.0");
// transforming it into a LocalDateTime
ZonedDateTime utc = ZonedDateTime.of(timestamp.toLocalDateTime(), ZoneId.of("UTC"));
// now create a ZonedDateTime by putting a zone
ZonedDateTime saoPaulo = utc.withZoneSameInstant(ZoneId.of("America/Sao_Paulo"));
// create a formatter for your locale and with the desired pattern
DateTimeFormatter dtf = DateTimeFormatter.ofPattern("EEEE dd MMM yyyy hh:mm:ss a xxx",
Locale.forLanguageTag("pt-BR"));
// and print the result
System.out.println(saoPaulo.format(dtf));
}
This time, the output is formatted in a totally different way:
Quinta-feira 12 mar 2020 12:01:45 AM -03:00