1
resposta

Criar Token JWT - Hora errada quando uso o Instant

Boa tarde. Estou fazendo aula onde gerando um token JWT. Funcionou a principio mas nos meus testes posterior notei que o token não esta expirando no tempo esperado. Após analise notei que quando eu dou um toInstant nessa linha:

Instant instant = LocalDateTime.now().plusHours(2).toInstant(ZoneOffset.of("-03:00"));

É retornado uma data 3 horas a mais. Fiz um main aqui pra validar como mostrado abaixo. Alguem notou esse problema e conseguiu resolver? Eu resolvi mudando para Date ao inves de Instant. Mas gostaria de entender o motivo desse problema.

Fonte:

import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneOffset;

public class DateTimeMain {

    public static void main(String[] args) {
        LocalDateTime localDateTime = LocalDateTime.now().plusHours(2);
        Instant instant = LocalDateTime.now().plusHours(2).toInstant(ZoneOffset.of("-03:00"));

        System.out.println("localDateTime: "+localDateTime);
        System.out.println("instant      : "+instant);

    }
}

Output:

localDateTime: 2024-05-03T17:52:46.299366700
instant      : 2024-05-03T20:52:46.299366700Z
1 resposta

Olá, Calixto! Tudo bem?

Quando você usa LocalDateTime.now().plusHours(2).toInstant(ZoneOffset.of("-03:00")), está adicionando duas horas ao horário local atual e depois convertendo esse horário para um Instant considerando o fuso horário de -03:00.

O Instant é um ponto no tempo que representa um momento específico no UTC (Tempo Universal Coordenado). Por isso, quando você aplica o ZoneOffset.of("-03:00"), está ajustando o horário para UTC, o que acaba adicionando mais três horas ao tempo que você já ajustou, resultando em um total de cinco horas a mais em relação ao horário original.

A confusão aqui é que LocalDateTime não contém informação de fuso horário, então quando você o converte para Instant com um fuso horário específico, ele assume que o LocalDateTime está nesse fuso e faz a conversão para UTC.

Um exemplo prático para resolver isso mantendo o uso de Instant seria utilizar ZonedDateTime, que mantém a informação do fuso horário. Veja como poderia ajustar seu código:

import java.time.ZonedDateTime;
import java.time.ZoneId;

public class DateTimeMain {

    public static void main(String[] args) {
        ZonedDateTime zonedDateTime = ZonedDateTime.now(ZoneId.of("America/Sao_Paulo")).plusHours(2);
        Instant instant = zonedDateTime.toInstant();

        System.out.println("zonedDateTime: " + zonedDateTime);
        System.out.println("instant      : " + instant);
    }
}

Neste código, ZonedDateTime.now(ZoneId.of("America/Sao_Paulo")) cria um ZonedDateTime com o fuso horário de São Paulo. Ao adicionar duas horas e converter para Instant, você obtém o tempo UTC correspondente sem adicionar horas adicionais inadvertidamente.

Espero ter ajudado e bons estudos!

Caso este post tenha lhe ajudado, por favor, marcar como solucionado ✓.