web-dev-qa-db-fra.com

Java - Convertir Java.time.Instant en Java.sql.Timestamp sans décalage de zone

Dans l'application que je développe, j'ai besoin de convertir l'objet Java.time.Instant en Java.sql.Timestamp. Lorsque je crée un objet Instant, par exemple 

Instant now = Instant.now();

et inspecter l'élément. Je reçois quelque chose comme 2017-03-13T14:28:59.970Z Ensuite, j'essaie de créer un objet Timestamp comme ceci:

Timestamp current = Timestamp.from(now);

Et quand j'inspecte l'élément. Je reçois quelque chose comme 2017-03-13T16:28:59.970Z Le même résultat mais avec un décalage supplémentaire de 2 heures . Quelqu'un peut-il expliquer ce qui se passe et me donner une réponse pour résoudre ce problème sans décalage?. 

Quand j'ai créé comme ça:

LocalDateTime ldt = LocalDateTime.ofInstant(Instnant.now(), ZoneOffset.UTC);
Timestamp current = Timestamp.valueOf(ldt);

Tout fonctionne bien. Mais j'essaie d'éviter les conversions. Est-il possible de faire cela uniquement en utilisant l'objet Instant?

22
Aleydin Karaimin

J’ai modifié le fuseau horaire de mon ordinateur en Europe/Bucarest pour une expérience. Il s'agit de l'heure UTC + 2 heures correspondant à votre fuseau horaire.

Maintenant, quand je copie votre code, j'obtiens un résultat similaire au vôtre:

    Instant now = Instant.now();
    System.out.println(now); // prints 2017-03-14T06:16:32.621Z
    Timestamp current = Timestamp.from(now);
    System.out.println(current); // 2017-03-14 08:16:32.621

La sortie est donnée dans les commentaires. Cependant, je continue:

    DateFormat df = DateFormat.getDateTimeInstance();
    df.setTimeZone(TimeZone.getTimeZone("UTC"));
    // the following prints: Timestamp in UTC: 14-03-2017 06:16:32
    System.out.println("Timestamp in UTC: " + df.format(current));

Maintenant, vous pouvez voir que la Timestamp correspond vraiment à la Instant à partir de laquelle nous sommes partis (seules les millisecondes ne sont pas imprimées, mais j'espère qu'elles y sont également). Donc, vous avez tout fait correctement et ne vous êtes confus, car lorsque nous avons imprimé la variable Timestamp, nous appelions implicitement sa méthode toString. Cette méthode saisit à son tour le paramètre de fuseau horaire de l'ordinateur et affiche l'heure dans cette zone. Seulement pour cette raison, les affichages sont différents.

L’autre chose que vous avez tentée, en utilisant LocalDateTime, semble fonctionner, mais elle ne vous donne vraiment pas ce que vous voulez:

    LocalDateTime ldt = LocalDateTime.ofInstant(Instant.now(), ZoneOffset.UTC);
    System.out.println(ldt); // 2017-03-14T06:16:32.819
    current = Timestamp.valueOf(ldt);
    System.out.println(current); // 2017-03-14 06:16:32.819
    System.out.println("Timestamp in UTC: " + df.format(current)); // 14-03-2017 04:16:32

Maintenant, lorsque nous imprimons la Timestamp à l’aide de notre UTC DateFormat, nous pouvons constater qu’il est 2 heures trop tôt, 04:16:32 UTC lorsque la Instant est 06:16:32 UTC. Donc, cette méthode est trompeuse, on dirait que ça marche, mais ça ne marche pas.

Cela montre les problèmes qui ont conduit à la conception des classes de date et d’heure Java 8 pour remplacer les anciennes. Donc, la vraie et bonne solution à votre problème serait probablement de vous procurer un pilote JDBC 4.2 capable d’accepter facilement un objet Instant afin d’éviter toute conversion en Timestamp. Je ne sais pas si cela est disponible pour vous, mais je suis convaincu que ce le sera.

32
Ole V.V.

Si vous voulez l'horodatage actuel, pourquoi ne pas utiliser la fonction suivante, je l'ai utilisée dans divers projets et fonctionne parfaitement

public static Timestamp getTimeStamp()
{
    // Calendar information
    Calendar calendar       = Calendar.getInstance();
    Java.util.Date now      = calendar.getTime();
    Timestamp dbStamp       = new Timestamp(now.getTime());
    return dbStamp;
}   

Exemple:

System.out.println( getTimeStamp() );

Output: 2017-03-13 15: 01: 34.027

MODIFIER

Utilisation de Java 8 LocalDateTime:

public static Timestamp getTimeStamp()
{
    return Timestamp.valueOf(LocalDateTime.now());
}   
1
DazstaV3

Lors de l'enregistrement d'un enregistrement dans SQL Server DB, j'ai rencontré le même problème. J'ai utilisé Java.sql.Timestamp.valueOf(String s) pour obtenir Timestamp inUTC

import Java.time.Instant; import Java.time.format.DateTimeFormatter; .... .... DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss").withZone(UTC); String dateTime = dateTimeFormatter.format(Instant date); Timestamp timestamp = Timestamp.valueOf(dateTime);

Ça marche pour moi.

0
Taras Melnyk